diff --git a/.github/scripts/sync-from-marfa.test.sh b/.github/scripts/sync-from-marfa.test.sh index 692bd631..fbae8ce2 100644 --- a/.github/scripts/sync-from-marfa.test.sh +++ b/.github/scripts/sync-from-marfa.test.sh @@ -542,7 +542,7 @@ event_fields_expected="$(cat <<'EOF' | `stream_incomplete` | `reason` | `string` | Why. | | `catchup_too_old` | `requested` | `string` | The ID you sent. | | `cursor_ahead` | `head` | `string` | The latest ID. | -| `read_view_changed` | None | | | +| `reach_changed` | None | | | EOF )" @@ -723,7 +723,7 @@ schemas = { "StreamIncompleteFrame": frame("stream_incomplete", {"reason": {"type": "string", "enum": ["reader_behind"], "description": "Why."}}), "CatchupTooOldFrame": frame("catchup_too_old", {"requested": {"type": "string", "description": "The ID you sent."}}), "CursorAheadFrame": frame("cursor_ahead", {"head": {"type": "string", "description": "The latest ID."}}), - "ReadViewChangedFrame": frame("read_view_changed", {}), + "ReachChangedFrame": frame("reach_changed", {}), } print(json.dumps({"openapi": "3.1.0", "info": {"title": "Marfa", "version": "0", "description": sys.argv[1]}, "paths": {}, "components": {"schemas": schemas}})) PY diff --git a/content/docs/(overview)/events.mdx b/content/docs/(overview)/events.mdx index 2062018c..c75e706d 100644 --- a/content/docs/(overview)/events.mdx +++ b/content/docs/(overview)/events.mdx @@ -36,4 +36,4 @@ A webhook has no cursor and no replay: it delivers only events written after you [Receive webhooks](/guides/receive-webhooks) shows how to register one and check each delivery. -The rules behind this page are in the [events](https://github.com/withmarfa/marfa/blob/main/conformance/spec/events.md) and [read views](https://github.com/withmarfa/marfa/blob/main/conformance/spec/read-views.md) chapters of the contract. +The rules behind this page are in the [events](https://github.com/withmarfa/marfa/blob/main/conformance/spec/events.md) and [reach](https://github.com/withmarfa/marfa/blob/main/conformance/spec/reach.md) chapters of the contract. diff --git a/content/docs/(reference)/swift-sdk.mdx b/content/docs/(reference)/swift-sdk.mdx index 9e830da3..4b2e503d 100644 --- a/content/docs/(reference)/swift-sdk.mdx +++ b/content/docs/(reference)/swift-sdk.mdx @@ -131,7 +131,7 @@ Each `Change` names the `itemId` or `edgeId` it concerns, and its `origin` says | `.queueDrained`, `.queueNotDrained` | The drain the stream ran when the server came back ended, or stopped with an error. | Nothing: the stream drains by itself. | | `.stopped(MarfaError)` | What fed the stream stopped. Local writes are still told. | See below. | -**Two stops need the app's help.** On `.copyExpired`, hydrate again: the queue survives. Its `reason`, such as `read_view_changed` or `instance_changed`, is an open string, so keep a `default`. On `.unauthorized` or `.signedOut`, give the copy a new credential with `useKey(_:)`. +**Two stops need the app's help.** On `.copyExpired`, hydrate again: the queue survives. Its `reason`, such as `reach_changed` or `instance_changed`, is an open string, so keep a `default`. On `.unauthorized` or `.signedOut`, give the copy a new credential with `useKey(_:)`. ## Send writes and read verdicts diff --git a/content/docs/guides/keep-in-sync.mdx b/content/docs/guides/keep-in-sync.mdx index 493075ed..889e3fb4 100644 --- a/content/docs/guides/keep-in-sync.mdx +++ b/content/docs/guides/keep-in-sync.mdx @@ -5,7 +5,7 @@ description: Follow an instance's event stream from a cursor, so a copy of your A search index, a cache or a report keeps its own copy of an instance's data. Read what you need once, then apply each change from the [event stream](/events) and save a cursor, so that after a break you receive everything you missed and nothing twice. The [Swift SDK](/swift-sdk) and the [CLI](/cli) do this for you. -You need a credential that can read the types you copy. A copy that answers reads offline in the instance's place, as a device does, needs more: the [read views chapter of the contract](https://github.com/withmarfa/marfa/blob/main/conformance/spec/read-views.md) says what. +You need a credential that can read the types you copy. A copy that answers reads offline in the instance's place, as a device does, needs more: the [reach chapter of the contract](https://github.com/withmarfa/marfa/blob/main/conformance/spec/reach.md) says what. ## What the stream sends diff --git a/content/docs/guides/sync-a-folder.mdx b/content/docs/guides/sync-a-folder.mdx index 81f80fce..e4b0b087 100644 --- a/content/docs/guides/sync-a-folder.mdx +++ b/content/docs/guides/sync-a-folder.mdx @@ -189,7 +189,7 @@ defaults: A new key with the same `--source` is refused `409 conflict` while the old key is live. [Revoke the old key](/guides/manage-keys#revoke-a-key), run the `keys create` command from the first step again, then run `marfa keys keep` so the folder reads the new key from the keychain. -Then run `marfa folders push Notes`. If the key's read view changed, the push rebuilds the working copy once and sends the waiting writes in the same run, keeping earlier verdicts. If the view changes again during that run, the push stops and keeps the remaining writes queued. Try again once the key's access is settled. +Then run `marfa folders push Notes`. If the key's reach changed, the push rebuilds the working copy once and sends the waiting writes in the same run, keeping earlier verdicts. If the reach changes again during that run, the push stops and keeps the remaining writes queued. Try again once the key's access is settled. ## Stop following a folder diff --git a/content/docs/guides/troubleshooting.mdx b/content/docs/guides/troubleshooting.mdx index e7c82125..831ca979 100644 --- a/content/docs/guides/troubleshooting.mdx +++ b/content/docs/guides/troubleshooting.mdx @@ -233,7 +233,7 @@ You asked to resume from a cursor older than anything the instance's event log s Start over as you did the first time: read your data again from the API, and follow the stream from its head. The log keeps events for at least 30 days unless the instance is set otherwise. [Keep a copy in sync](/guides/keep-in-sync) shows the whole loop. - + What your credential may read has changed since the working copy was built, for example because its key was narrowed. The copy can't be resumed, because what it holds no longer matches what the credential reads. @@ -242,7 +242,7 @@ Build the working copy again. [Devices](/devices) explains when a copy has to st -This is how the CLI's device commands report `catchup_too_old` and `read_view_changed`, with the code `copy_expired` and exit code `4`. Writes waiting in the queue are kept. +This is how the CLI's device commands report `catchup_too_old` and `reach_changed`, with the code `copy_expired` and exit code `4`. Writes waiting in the queue are kept. Run `marfa device hydrate` again. If the credential no longer reads one of the types you held, leave that type out of `--types`, or the hydrate is refused with `type_not_permitted`. diff --git a/openapi.json b/openapi.json index 7b230927..87ded3d3 100644 --- a/openapi.json +++ b/openapi.json @@ -1966,7 +1966,7 @@ "properties": { "listed": { "type": "boolean", - "description": "`true` if listings show you this item, `false` if `source_filter` leaves it out of them and you can read it only by ID. Present only when you send `X-Marfa-Read-View`." + "description": "`true` if listings show you this item, `false` if `source_filter` leaves it out of them and you can read it only by ID. Present only when you send `X-Marfa-Reach`." } } } @@ -2042,7 +2042,7 @@ }, "listed": { "type": "boolean", - "description": "`true` if listings show you this item, `false` if `source_filter` leaves it out of them and you can read it only by ID. Present only when you send `X-Marfa-Read-View`." + "description": "`true` if listings show you this item, `false` if `source_filter` leaves it out of them and you can read it only by ID. Present only when you send `X-Marfa-Reach`." }, "neighbors": { "type": "array", @@ -8661,7 +8661,7 @@ ], "description": "An error response." }, - "ReadViewChangedRefusal": { + "ReachChangedRefusal": { "type": "object", "properties": { "error": { @@ -8670,7 +8670,7 @@ "code": { "type": "string", "enum": [ - "read_view_changed" + "reach_changed" ], "description": "A machine-readable code for the error. Use it in your logic." }, @@ -8908,9 +8908,9 @@ "type": "string", "description": "Only on a copy stream: the instance's ID, as `GET /` returns it." }, - "read_view": { + "reach": { "type": "string", - "description": "Only on a copy stream: the read view to send as `X-Marfa-Read-View`, to resume or to read the working copy's data." + "description": "Only on a copy stream: the reach to send as `X-Marfa-Reach`, to resume or to read the working copy's data." } }, "required": [ @@ -8938,9 +8938,9 @@ "type": "string", "description": "Only on a copy stream: the instance's ID, as `GET /` returns it." }, - "read_view": { + "reach": { "type": "string", - "description": "Only on a copy stream: the read view to send as `X-Marfa-Read-View`, to resume or to read the working copy's data." + "description": "Only on a copy stream: the reach to send as `X-Marfa-Reach`, to resume or to read the working copy's data." } }, "required": [ @@ -9031,13 +9031,13 @@ "head" ] }, - "ReadViewChangedFrame": { + "ReachChangedFrame": { "type": "object", - "description": "The last frame of a copy stream, with no `id:`, when its read view changes, such as after a retype or a narrowed key. Rebuild the working copy.", + "description": "The last frame of a copy stream, with no `id:`, when its reach changes, such as after a retype or a narrowed key. Rebuild the working copy.", "properties": { "event_type": { "type": "string", - "const": "read_view_changed", + "const": "reach_changed", "description": "The frame's name, which is also its `event:`." } }, @@ -9070,7 +9070,7 @@ "$ref": "#/components/schemas/CursorAheadFrame" }, { - "$ref": "#/components/schemas/ReadViewChangedFrame" + "$ref": "#/components/schemas/ReachChangedFrame" } ] }, @@ -9156,8 +9156,8 @@ "minimum": 0 } }, - "X-Marfa-Read-View": { - "description": "A matching opaque read-view certificate, supplied only after a conditional copy read and its snapshot have completed. Successful conditional reads and snapshot-attributed resource refusals carry it with Cache-Control: no-store. Ordinary reads and write receipts carry none.", + "X-Marfa-Reach": { + "description": "The matching opaque reach, supplied only after a conditional copy read and its snapshot have completed. Successful conditional reads and snapshot-attributed resource refusals carry it with Cache-Control: no-store. Ordinary reads and write receipts carry none.", "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$", @@ -9943,7 +9943,7 @@ "in": "query" }, { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -9952,7 +9952,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ], "responses": { @@ -9981,13 +9981,13 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "400": { - "description": "- `validation_error`: a query parameter is unknown or invalid, `updated_after` comes with a different `sort` or `direction`, `cursor` came from another ordering or listing, or `X-Marfa-Read-View` comes without `include=metadata`.\n- `unknown_type`: `type` is a concrete type that nothing registers.", + "description": "- `validation_error`: a query parameter is unknown or invalid, `updated_after` comes with a different `sort` or `direction`, `cursor` came from another ordering or listing, or `X-Marfa-Reach` comes without `include=metadata`.\n- `unknown_type`: `type` is a concrete type that nothing registers.", "content": { "application/json": { "schema": { @@ -10074,17 +10074,17 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -10270,7 +10270,7 @@ "in": "query" }, { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -10279,7 +10279,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ], "responses": { @@ -10308,8 +10308,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -10401,8 +10401,8 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -10434,17 +10434,17 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -13732,7 +13732,7 @@ }, "responses": { "200": { - "description": "Returns the items you can read, `metadata` if you asked for it, and `listed` if you sent `X-Marfa-Read-View`.", + "description": "Returns the items you can read, `metadata` if you asked for it, and `listed` if you sent `X-Marfa-Reach`.", "content": { "application/json": { "schema": { @@ -13757,7 +13757,7 @@ "items": { "type": "boolean" }, - "description": "For each item returned, in the same order: `true` if listings show you the item, `false` if `source_filter` leaves it out of them. Present only when you send `X-Marfa-Read-View`." + "description": "For each item returned, in the same order: `true` if listings show you the item, `false` if `source_filter` leaves it out of them. Present only when you send `X-Marfa-Reach`." } }, "required": [ @@ -13782,8 +13782,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -13875,19 +13875,19 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { "anyOf": [ { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" }, { "$ref": "#/components/schemas/InstanceChangedRefusal" @@ -14064,7 +14064,7 @@ }, "parameters": [ { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -14073,7 +14073,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." }, { "name": "X-Marfa-Instance-Id", @@ -22590,7 +22590,7 @@ "in": "query" }, { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -22599,7 +22599,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ], "responses": { @@ -22628,8 +22628,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -22721,17 +22721,17 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -23436,7 +23436,7 @@ "in": "path" }, { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -23445,7 +23445,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ], "responses": { @@ -23474,8 +23474,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -23567,8 +23567,8 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -23600,17 +23600,17 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -25163,7 +25163,7 @@ "in": "query" }, { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -25172,7 +25172,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ], "responses": { @@ -25201,8 +25201,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -25294,8 +25294,8 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -25327,17 +25327,17 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -26238,8 +26238,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -26304,11 +26304,11 @@ } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -26459,7 +26459,7 @@ }, "parameters": [ { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -26468,7 +26468,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ] }, @@ -28722,8 +28722,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -28788,11 +28788,11 @@ } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -28943,7 +28943,7 @@ }, "parameters": [ { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -28952,7 +28952,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ] } @@ -31630,10 +31630,10 @@ "enum": [ "1" ], - "description": "Set to `1` for a copy stream, which a working copy follows. It takes `edges=all` and no other parameter. Its `stream_cursor` and `stream_live` carry `instance_id` and `read_view`, and its item frames carry `listed`." + "description": "Set to `1` for a copy stream, which a working copy follows. It takes `edges=all` and no other parameter. Its `stream_cursor` and `stream_live` carry `instance_id` and `reach`, and its item frames carry `listed`." }, "required": false, - "description": "Set to `1` for a copy stream, which a working copy follows. It takes `edges=all` and no other parameter. Its `stream_cursor` and `stream_live` carry `instance_id` and `read_view`, and its item frames carry `listed`.", + "description": "Set to `1` for a copy stream, which a working copy follows. It takes `edges=all` and no other parameter. Its `stream_cursor` and `stream_live` carry `instance_id` and `reach`, and its item frames carry `listed`.", "name": "copy", "in": "query" }, @@ -31666,11 +31666,11 @@ "schema": { "type": "string", "pattern": "^[0-9a-f]{64}$", - "description": "On a copy stream, the `read_view` from the last `stream_cursor` or `stream_live` you received. Send it with `Last-Event-ID` to resume, and leave both out to start a new copy." + "description": "On a copy stream, the `reach` from the last `stream_cursor` or `stream_live` you received. Send it with `Last-Event-ID` to resume, and leave both out to start a new copy." }, "required": false, - "description": "On a copy stream, the `read_view` from the last `stream_cursor` or `stream_live` you received. Send it with `Last-Event-ID` to resume, and leave both out to start a new copy.", - "name": "X-Marfa-Read-View", + "description": "On a copy stream, the `reach` from the last `stream_cursor` or `stream_live` you received. Send it with `Last-Event-ID` to resume, and leave both out to start a new copy.", + "name": "X-Marfa-Reach", "in": "header" }, { @@ -31686,7 +31686,7 @@ ], "responses": { "200": { - "description": "Returns the stream. Each frame's `event:` names it:\n- `stream_cursor`: first, where the log stands.\n- An event, such as `item.created`, with its event ID as `id:`.\n- `stream_live`: once the catch-up is over.\n- `stream_incomplete`, `catchup_too_old`, `cursor_ahead` or `read_view_changed`: last, before the stream closes.", + "description": "Returns the stream. Each frame's `event:` names it:\n- `stream_cursor`: first, where the log stands.\n- An event, such as `item.created`, with its event ID as `id:`.\n- `stream_live`: once the catch-up is over.\n- `stream_incomplete`, `catchup_too_old`, `cursor_ahead` or `reach_changed`: last, before the stream closes.", "content": { "text/event-stream": { "example": ": connected\n\nevent: stream_cursor\ndata: {\"event_type\":\"stream_cursor\",\"cursor\":\"1041\"}\n\nevent: stream_live\ndata: {\"event_type\":\"stream_live\",\"cursor\":\"1041\"}\n\nid: 1042\nevent: item.created\ndata: {\"event_type\":\"item.created\",\"item\":{\"id\":\"0199a9c4-7c1e-7d3a-9f2b-3c4d5e6f7a8b\",\"type\":\"core.note\",\"properties\":{\"title\":\"Reading list\",\"body\":\"Finish the chapter on tides.\"},\"state\":\"active\",\"tier\":\"library\",\"version\":1,\"schema_version\":0,\"source\":\"notes-app\",\"occurred_at\":\"2026-10-03T09:30:00.000Z\",\"created_at\":\"2026-10-03T09:30:00.000Z\",\"updated_at\":\"2026-10-03T09:30:00.000Z\"},\"metadata\":{\"item_id\":\"0199a9c4-7c1e-7d3a-9f2b-3c4d5e6f7a8b\",\"tags\":[],\"extensions\":{}}}\n\n", @@ -31714,7 +31714,7 @@ } }, "400": { - "description": "- `validation_error`: a parameter or header is invalid, or not one this endpoint takes. For example, `type` has more than 10 entries or is `*`, or `Last-Event-ID` isn't an event ID. A copy stream takes only `copy=1` and `edges=all`, and both resume headers or neither; another stream takes no `X-Marfa-Read-View`.\n- `unknown_type`: a `type` entry isn't registered.", + "description": "- `validation_error`: a parameter or header is invalid, or not one this endpoint takes. For example, `type` has more than 10 entries or is `*`, or `Last-Event-ID` isn't an event ID. A copy stream takes only `copy=1` and `edges=all`, and both resume headers or neither; another stream takes no `X-Marfa-Reach`.\n- `unknown_type`: a `type` entry isn't registered.", "content": { "application/json": { "schema": { @@ -31804,11 +31804,11 @@ } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -44921,8 +44921,8 @@ "X-RateLimit-Reset": { "$ref": "#/components/headers/X-RateLimit-Reset" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, @@ -45014,17 +45014,17 @@ "X-Error-Code": { "$ref": "#/components/headers/X-Error-Code" }, - "X-Marfa-Read-View": { - "$ref": "#/components/headers/X-Marfa-Read-View" + "X-Marfa-Reach": { + "$ref": "#/components/headers/X-Marfa-Reach" } } }, "409": { - "description": "`read_view_changed`: the read view in `X-Marfa-Read-View` has changed. Rebuild the working copy.", + "description": "`reach_changed`: the reach in `X-Marfa-Reach` has changed. Rebuild the working copy.", "content": { "application/json": { "schema": { - "$ref": "#/components/schemas/ReadViewChangedRefusal" + "$ref": "#/components/schemas/ReachChangedRefusal" } } }, @@ -45175,7 +45175,7 @@ }, "parameters": [ { - "name": "X-Marfa-Read-View", + "name": "X-Marfa-Reach", "in": "header", "required": false, "schema": { @@ -45184,7 +45184,7 @@ "minLength": 64, "maxLength": 64 }, - "description": "A read-view certificate from a copy stream, for a working copy. Marfa reads the current data and checks the view in one snapshot, and returns `409 read_view_changed` if the view has changed. Leave it out for an ordinary read." + "description": "The reach from a copy stream, for a working copy. Marfa reads the current data and checks the reach in one snapshot, and returns `409 reach_changed` if it has changed. Leave it out for an ordinary read." } ] } diff --git a/scripts/sync-from-marfa.sh b/scripts/sync-from-marfa.sh index da4032c0..a41bcf4f 100755 --- a/scripts/sync-from-marfa.sh +++ b/scripts/sync-from-marfa.sh @@ -932,7 +932,7 @@ def render_spec(): # The frames of a stream that are not events, each named by the constant # its event_type holds. A frame with no other field is a row with None. frames = [] - for name in ("StreamCursorFrame", "StreamLiveFrame", "StreamIncompleteFrame", "CatchupTooOldFrame", "CursorAheadFrame", "ReadViewChangedFrame"): + for name in ("StreamCursorFrame", "StreamLiveFrame", "StreamIncompleteFrame", "CatchupTooOldFrame", "CursorAheadFrame", "ReachChangedFrame"): props = properties(name) frame = props.get("event_type", {}).get("const") if not isinstance(frame, str): diff --git a/src/generated/GLOSSARY.md b/src/generated/GLOSSARY.md index 2a93dd1f..cb02a757 100644 --- a/src/generated/GLOSSARY.md +++ b/src/generated/GLOSSARY.md @@ -125,6 +125,7 @@ Access is read the same way wherever a person sees it: on the pages where they a | **device** | Something that keeps a working copy of a slice and a queue of writes, through the core: an app built on the Swift SDK or the Node module, or the CLI. A folder is a device whose face is a directory. | | **core** | The Rust engine every native client embeds, through UniFFI to Swift and a native module to Node. | | **working copy** | A device's local replica of its slice. It is a copy, not a peer: the server is the truth. | +| **reach** | The server's proof, for one credential, that the inventory, the direct reads and the event stream a working copy holds were all read under the same limits on what that credential may read. A copy stream gives it as `reach` in its markers, and a conditional read or a resumed stream sends it back as `X-Marfa-Reach`. It changes when what the credential may read changes, and then the server answers `reach_changed` and the working copy is built again. A key's reach, in the other sense, is what its permissions and maps let it read and write. | | **slice** | The declared subset of an instance one device holds: a type list and a tier, and any edge types it holds whole. What a working copy is a copy of. | | **pin** | To hold one row in a working copy by id, whatever the slice says of it. A pinned row is read at once, kept current by catch-up and read again by every hydration, and goes once its pin is off and the slice does not take it (where a write to it waits, at an answered move, the next catch-up that touches it or the next hydration), or when it is purged or its create refused. | | **verdict** | What a device gives a queued write once the server answers it, or once it cannot be sent: one of `accepted`, `merged` (applied with changes), `conflicted` (written to a conflicted copy), `refused` (with a reason), `blocked` (held, for one of six reasons such as a refused credential or a write it waits on) and `dead` (given up after retries). | @@ -216,5 +217,5 @@ Its sibling `updated_before` closes the same window at the top and is **exclusiv - `item_not_found`: no item this credential may read has this id, or, on the folder operations, no folder: a readable item that is not a `system.folder` answers it there too. An item of a type it may not read answers exactly as one that does not exist, so the answer is not a statement that no such row exists. A key learns its own reach from `GET /keys/current`, and a signed-in app's token from the scope list on its token response, never from a refusal. - `api_key_not_found`: no key within this credential's reach has this id. A key it could not have minted answers exactly as one that does not exist, as `item_not_found` does for an item it may not read. - A **malformed** identifier is neither: it never reached a lookup, so it answers the generic `validation_error` with the field named. -- `instance_changed`: a request named, in `X-Marfa-Instance-Id`, an instance other than the one at the address, so it reached a different instance from the one its sender's copy came from. A `409`, judged before anything about the request but its credential, and never recorded under an `Idempotency-Key`. Not `read_view_changed`, which says the read view a credential holds on the same instance has changed. +- `instance_changed`: a request named, in `X-Marfa-Instance-Id`, an instance other than the one at the address, so it reached a different instance from the one its sender's copy came from. A `409`, judged before anything about the request but its credential, and never recorded under an `Idempotency-Key`. Not `reach_changed`, which says the reach a credential holds on the same instance has changed. - `edge_cycle`: an edge that would close a cycle. A **self-loop** is refused on every edge type; a longer cycle is detected only on the cycle-prone types, `parent-of` and `supersedes`, where the graph is not acyclic by construction. diff --git a/src/generated/catalog/event-fields.md b/src/generated/catalog/event-fields.md index 4e773c01..da21cb7b 100644 --- a/src/generated/catalog/event-fields.md +++ b/src/generated/catalog/event-fields.md @@ -31,14 +31,14 @@ | ------------------- | ----------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `stream_cursor` | `cursor` | `string` | The ID of the latest event in the log, or `0` if it's empty. Read state after this frame, and you can resume from this ID without missing a change. | | `stream_cursor` | `instance_id` | `string` | Only on a copy stream: the instance's ID, as `GET /` returns it. | -| `stream_cursor` | `read_view` | `string` | Only on a copy stream: the read view to send as `X-Marfa-Read-View`, to resume or to read the working copy's data. | +| `stream_cursor` | `reach` | `string` | Only on a copy stream: the reach to send as `X-Marfa-Reach`, to resume or to read the working copy's data. | | `stream_live` | `cursor` | `string` or `null` | A position you can resume from without receiving again what the catch-up covered. `null` only when Marfa couldn't read the log in time and had nothing to replay. | | `stream_live` | `instance_id` | `string` | Only on a copy stream: the instance's ID, as `GET /` returns it. | -| `stream_live` | `read_view` | `string` | Only on a copy stream: the read view to send as `X-Marfa-Read-View`, to resume or to read the working copy's data. | +| `stream_live` | `reach` | `string` | Only on a copy stream: the reach to send as `X-Marfa-Reach`, to resume or to read the working copy's data. | | `stream_incomplete` | `reason` | `string` | `replay_failed`: catch-up failed. `backlog_overflow`: changes piled up as it opened. `live_delivery_failed`: live events failed. `credential_ended`: your credential ended. `reader_behind`: you fell behind. `server_stopping`: Marfa is stopping. | | `stream_incomplete` | `cursor` | `string` or `null` | The ID of the last event the stream sent, or `null` if it sent none. | | `catchup_too_old` | `min_retained_id` | `string` | The ID of the oldest event the log still holds. | | `catchup_too_old` | `requested` | `string` | The `Last-Event-ID` you sent. | | `cursor_ahead` | `requested` | `string` | The `Last-Event-ID` you sent. | | `cursor_ahead` | `head` | `string` | The ID of the latest event in the log. | -| `read_view_changed` | None | | | +| `reach_changed` | None | | | diff --git a/src/generated/contract-index.json b/src/generated/contract-index.json index c8a55576..bfdd53e1 100644 --- a/src/generated/contract-index.json +++ b/src/generated/contract-index.json @@ -390,9 +390,9 @@ "device/pin-reads-edges": "5aadd0abb87421d4", "device/pin-again-reads": "abf35af216a2bc44", "device/pin-says-pinned": "9c3b21c5731549e7", - "device/pin-not-hydrated": "7fa6c5422b327ba1", + "device/pin-not-hydrated": "3d3e544871075465", "device/pin-absent": "6da98a0d44a08847", - "device/pin-absent-evicts": "64f8ecf416c839a5", + "device/pin-absent-evicts": "1f40e7c4f9536761", "device/pin-absent-unpinned": "19b22cfd9c95fe84", "device/pin-own-create": "b5c1e4207262e26f", "device/pin-follows-create": "b293385b38df4f74", @@ -432,7 +432,7 @@ "device/instance-changed-one-write": "336fb0f00e394f18", "device/instance-changed-holds-report": "ccfe5b45d7246410", "device/late-answer": "8424582da6b3bd42", - "device/proof-lost": "857089af3a8907d7", + "device/proof-lost": "76b9363afb142100", "device/reading-handle-reads": "b636171f4c8c9f5a", "device/reading-handle-refuses": "eb22b3b1d33dd635", "device/reading-handle-queues-nothing": "5233a43007cbf49b", @@ -446,22 +446,22 @@ "device/report-no-request": "bfdd27f370a6e399", "device/report-never": "ecdac026d83e515e", "device/report-in-progress": "d30c4fa06bcda15c", - "device/report-complete": "56af1a011b897ebd", - "device/report-expired": "d02996ac2767f922", + "device/report-complete": "d2748225fa94f924", + "device/report-expired": "33f146f6722a3bcd", "device/hydrate-empty-refused": "fd499898003b6ead", "device/hydrate-bare-wildcard": "1d11276a28846c1b", "device/hydrate-grammar": "36ce9b40ea99bf14", "device/hydrate-wildcard-empty": "b58618a4f651a48c", - "device/hydrate-unheld-type": "832a4b3a35aaa5e1", - "device/hydrate-unheld-edge-type": "67ad4fbb14f87d82", - "device/hydrate-unreadable-type": "df7acddb5c9ef4af", + "device/hydrate-unheld-type": "1c698a8ade62fff5", + "device/hydrate-unheld-edge-type": "87477273796da42c", + "device/hydrate-unreadable-type": "9324a6081e09b8b1", "device/hydrate-readable-descendant": "8aa7960e9e478bd0", "device/hydrate-unreadable-non-key": "e614d60be1f6ecc0", "device/hydrate-head-first": "993f2e7ccba35d1a", "device/hydrate-listing": "68509be7af8494d9", "device/hydrate-page-walk": "1fa660839033f68f", - "device/hydrate-pins-batched": "a78f096df9c2c03d", - "device/hydrate-repeated-cursor": "06bb28f5a7d42fdf", + "device/hydrate-pins-batched": "6b3a0c15f38af506", + "device/hydrate-repeated-cursor": "17324c90fa8bdf95", "device/hydrate-replays": "6ddc6395664cb986", "device/hydrate-live-marker": "eacb9491ddbc5e87", "device/hydrate-replaces": "20ec8939407baf43", @@ -786,18 +786,18 @@ "device/catalog-changed-told": "f49c94e775a2b3de", "device/catch-up-catalog-told": "550712baa365440c", "device/catch-up-failed-catalog-told": "576bdd57c3bd5a63", - "device/resume-presents-view": "7ef8137b6e054cef", + "device/resume-presents-reach": "6bd2a00e840207a7", "device/live-marker-required": "d3c7abd2c0659c3a", - "device/proof-invalid": "089019e39cc6b482", + "device/proof-invalid": "f9b4103ff6fe6419", "device/page-termination": "860dfc3fb73b9c13", - "device/proof-invalid-reason": "c801dcee1bf618d2", - "device/undecodable-answer": "95a022caadc22f58", - "device/undecodable-answer-keeps-copy": "5d6b511783e69255", + "device/proof-invalid-reason": "bdfdbf5ea219b611", + "device/undecodable-answer": "523a673561ba6730", + "device/undecodable-answer-keeps-copy": "965be7412cfa91d2", "device/undecodable-event-keeps-cursor": "03692cd765e80c0e", - "device/view-changed": "13a68aafa95a5589", + "device/reach-changed": "2e9c22e9c32ee09c", "device/listed-membership": "7c5e18ffc76bd490", - "device/uncertified-keeps-copy": "2695e1c603124f34", - "device/credential-ended": "1215d88840847111", + "device/uncertified-keeps-copy": "745ab260f59a85ba", + "device/credential-ended": "e7a16f038b1bae10", "device/read-back-keeps-verdict": "02ad40847c61e512", "device/save-before-sync": "1b14422d1b26d947", "device/save-before-sync-queued": "3d0128392294b293", @@ -951,7 +951,7 @@ "device/system-write-refused": "de72d7ec156fad76", "device/system-write-nothing-saved": "4fefafa5af6d6f95", "device/system-folder-door": "fd597c49fb8a7d7b", - "device/drain-no-cursor": "50aa80ada9aed6f7", + "device/drain-no-cursor": "2176dc67ba1c0479", "device/drain-incomplete": "7573a83c2526630d", "device/drain-expired": "3223a3a9ad3c8583", "device/catalog-served": "27dd9df7849ddb83", @@ -1334,9 +1334,9 @@ "errors/idem-not-retained": "31a83a4793f1f753", "errors/idem-not-retained-status": "6917632b9ef54caa", "errors/idem-not-retained-nothing": "694eb16b42067d1f", - "errors/unmatched-path": "5d3ca1810ef0dfa3", + "errors/unmatched-path": "b481fffe1995ddff", "errors/unmatched-method": "553775f00a1e730b", - "errors/unmatched-read-view": "5063794e64f75f04", + "errors/unmatched-reach": "46f06bc57ca15722", "errors/contention": "cda8909650cadf37", "errors/contention-declared": "a2f3c16a9fc5a0bc", "errors/contention-budget": "964de57f56b59d21", @@ -1396,7 +1396,7 @@ "events/stream-unauthenticated": "7b9a0dd5f29b011b", "events/stream-reads-no-type": "c07072113d7221a5", "events/stream-undeclared-key": "33409dd44d8a06d7", - "events/stream-refusal-order": "7452b49fb2459ec7", + "events/stream-refusal-order": "8a0974dfcf3b3f1a", "events/writes-while-open": "1ac968c1df782d54", "events/stream-cursor-first": "fd653d2663f15a96", "events/stream-cursor-no-id": "b59e417701098694", @@ -1478,7 +1478,7 @@ "events/source-filter-item": "26be392b17ec7faf", "events/source-filter-edge": "542a061ca80d9c48", "events/source-filter-current": "6fa2525d004a037e", - "events/source-filter-copy": "4723b13ee05e4aab", + "events/source-filter-copy": "3f28f4f8783cbba8", "events/held-authority": "2f29b378f4152027", "events/replay-consumed": "784bd84afb33d773", "events/credential-narrowed": "85cdbd41f1573cde", @@ -2299,11 +2299,11 @@ "folders/watch-follows": "d8954d53cda45305", "folders/watch-follows-files-written": "d1997baf7f810dd7", "folders/expired-folder-hydrates": "91bbd244d1d55c94", - "folders/view-changed-push-rebuilds": "b8ad5ef567d57d78", - "folders/view-changed-push-pulls-again": "e8e08728196c22c8", - "folders/view-changed-push-once": "843cd799621cf879", - "folders/view-changed-rebuild-fails": "2991ac1cdbda89be", - "folders/view-changed-watch-rebuilds": "c95a4638937031c5", + "folders/reach-changed-push-rebuilds": "7fa2011583935492", + "folders/reach-changed-push-pulls-again": "268a321f58827579", + "folders/reach-changed-push-once": "0551592836b6410f", + "folders/reach-changed-rebuild-fails": "bb28b7cd49193d93", + "folders/reach-changed-watch-rebuilds": "dbab8ff4841952ec", "folders/failed-hydration-retried": "a7167cd9a69d6c31", "folders/watch-hydration-retry": "721d7664a33e46b4", "folders/watch-retry-delay": "763c318c1f0eca53", @@ -3034,7 +3034,7 @@ "instance/write-instance-not-recorded": "9c7583369f41859d", "instance/write-instance-replay": "a723f31161006dfc", "instance/write-instance-every-door": "ee82675830bd4afe", - "instance/write-instance-ignored": "2e4f66174d3e2660", + "instance/write-instance-ignored": "e14ba136e4ae2efc", "instance/root-no-credential": "173bdaf186d1c92a", "instance/root-fields": "0aca6005f699f19c", "instance/root-name": "46717bc3472d9a07", @@ -4359,104 +4359,104 @@ "queue-and-verdicts/edge-edit-no-change": "de545ce28670461b", "queue-and-verdicts/edge-move-shown": "ca002db265f12567", "queue-and-verdicts/edge-move-refused-back": "b9b4191d30b0cf49", - "queue-and-verdicts/edge-source-move-expires": "624448e792e3c676", + "queue-and-verdicts/edge-source-move-expires": "313bf64218e3de03", "queue-and-verdicts/edge-source-move-carries-on": "b00f6ea2d32b31d5", - "queue-and-verdicts/edge-source-move-reads-owed": "2aa60fdc97b21cf1", - "queue-and-verdicts/edge-source-move-one-expiry": "fe0d7bab00259b70", + "queue-and-verdicts/edge-source-move-reads-owed": "c96aaa7efce0f577", + "queue-and-verdicts/edge-source-move-one-expiry": "852acd8a1d74f53c", "queue-and-verdicts/edge-source-move-report-kept": "adff2ce6dc4f6751", "queue-and-verdicts/edge-source-move-error-wins": "a41f9c94ac59a6e2", - "queue-and-verdicts/edge-source-move-refused-keeps-copy": "843a097560212675", - "queue-and-verdicts/view-change-ends-drain": "569af27db80b329f", + "queue-and-verdicts/edge-source-move-refused-keeps-copy": "05482bfa0ebd1391", + "queue-and-verdicts/reach-change-ends-drain": "5f2da87431dc96d0", "queue-and-verdicts/edge-move-waits-new-end": "4f5cac39fbf813f4", "queue-and-verdicts/edge-move-names-landed": "ff09fe254d58edff", "queue-and-verdicts/edge-move-always-refused": "9593b0e85374e768", "queue-and-verdicts/edge-self-loop": "3e53cc9e30a7ef5b" }, - "read-views": { - "read-views/copy-bootstrap": "02f2cdacbf39ecb3", - "read-views/copy-resume": "8b8c9aed435d94ee", - "read-views/copy-query-refused": "4004640de42ba806", - "read-views/copy-resume-unpaired": "be847ff4608be7ff", - "read-views/copy-cursor-refused": "53d6b9dea54add7b", - "read-views/copy-view-refused": "b54b6fcceef021a1", - "read-views/copy-view-ordinary": "8d1a630acc24af24", - "read-views/copy-no-type": "f67fcbca8ff1bfea", - "read-views/copy-refusal-order": "fd5e4b0c132ac1c8", - "read-views/stream-no-header": "7e79e270827b59f8", - "read-views/marker-first": "d56ab9e7e0f2f316", - "read-views/marker-no-id": "5fa7e2661078bcd4", - "read-views/marker-body": "7827e7fa6b6a2c32", - "read-views/marker-event-type": "9d6f018002c56bb1", - "read-views/marker-cursor": "d1a87485613e6b97", - "read-views/marker-view": "03a7c3c62c58eabc", - "read-views/marker-instance": "ebcd36f512fcc993", - "read-views/marker-same-view": "f6418428514ea9e9", - "read-views/marker-live-bound": "e9c020193fc9b835", - "read-views/marker-live-after-replay": "975fb91bf68e9c63", - "read-views/resume-same-view": "f7328db959e9f198", - "read-views/resume-ahead": "47f5037b3b5ec414", - "read-views/resume-ahead-closes": "2d42622ea5ef8105", - "read-views/resume-ahead-no-live": "117eafcea4fc0f25", - "read-views/opening-incomplete": "5499e79b41e581cc", - "read-views/view-per-credential": "6d0ce4686dbbea1c", - "read-views/view-per-app": "0edb43f9fc2e59b8", - "read-views/view-moves-type-reach": "7b99228ff098604d", - "read-views/view-moves-edge-reach": "e7a989ea0fa9e41a", - "read-views/view-moves-metadata-reach": "8c2a2f50d32e48ad", - "read-views/view-moves-extension-reach": "e428934d7486ff2c", - "read-views/view-moves-source-filter": "e2e7af9540cfd746", - "read-views/view-keeps-write-reach": "fa36a5a8936bcef3", - "read-views/view-keeps-content": "d27cd031f9decffd", - "read-views/view-keeps-lifecycle": "10bf6a8572f1083b", - "read-views/view-moves-retype": "ea95d25973d110b1", - "read-views/view-keeps-same-type": "ddc0ce926f137bc1", - "read-views/view-moves-edge-source": "9fd998fdce5b376e", - "read-views/view-keeps-edge-writes": "c3efec7f40935a46", - "read-views/view-moves-type-topology": "02747452c35cccfe", - "read-views/view-keeps-type-update": "995ef051650de950", - "read-views/view-moves-edge-type": "5fa4b29c9cf6de96", - "read-views/view-moves-purge-sweep": "b4137726fe262009", - "read-views/view-change-before-answer": "109c0f7eef7a181e", - "read-views/view-keeps-on-rollback": "9d056247bd089cfe", - "read-views/conditional-certified": "b2a8e7e32db7552f", - "read-views/conditional-no-store": "9a7b768540b8dfd7", - "read-views/conditional-no-body-view": "42b77ae257c9bed1", - "read-views/conditional-ordinary": "668de967af6a6c5f", - "read-views/conditional-item-page": "07b36ef07ecc71e3", - "read-views/conditional-door-refused": "d44a08bc431c4656", - "read-views/write-header-ignored": "7ce0e2c962a21d23", - "read-views/write-header-replay": "9460f4371a43f8e2", - "read-views/conditional-view-refused": "b32b47c92893015a", - "read-views/conditional-query-ordinary": "debe7e72677899b8", - "read-views/conditional-order": "44b8de760b62a4e8", - "read-views/conditional-coherent": "fd7ca641ec648ceb", - "read-views/certified-absent": "7b93296d4b9e3e8e", - "read-views/certified-type-refused": "cd1070ac4484b69b", - "read-views/certified-edge-refused": "24adf020f398358f", - "read-views/certified-keys-current": "ce47d8f59f65cc45", - "read-views/uncertified-failures": "3f7a9af932e194dd", - "read-views/page-next-cursor": "c88936c9f37fab89", - "read-views/page-rows": "dc3d843441fd7135", - "read-views/page-excludes": "d4d075fe0cb0cb48", - "read-views/listed-direct": "47a74250052b489c", - "read-views/listed-neighbor": "a0050044eb38caff", - "read-views/listed-definition": "d188910b35776221", - "read-views/listed-by-id": "5d0ecb10a578425b", - "read-views/listed-bulk-get": "924337379c79911a", - "read-views/listed-not-on-edges": "7f0aeed0ed9f3ed3", - "read-views/receipt-uncertified": "1789abfbfc377f21", - "read-views/changed-conditional": "31cdb21353d00bfb", - "read-views/changed-resume": "7ca4effb5830e0ba", - "read-views/changed-body": "7207e25a9bc646ff", - "read-views/changed-uncertified": "c886869b46a4872f", - "read-views/terminal-frame": "a93e3941bba55d4b", - "read-views/terminal-closes": "e7191440d4330791", - "read-views/terminal-withholds": "169fda60f5041b62", - "read-views/terminal-races": "8749c97d2110ccdd", - "read-views/terminal-races-silent": "e5cd63365308d64a", - "read-views/frame-listed": "cf058fcf4508e9fd", - "read-views/frame-excluded": "505bfa023c93eba8", - "read-views/frame-edge-shape": "1b9ccffd7f2d7dfb" + "reach": { + "reach/copy-bootstrap": "b11094f8a5162ac7", + "reach/copy-resume": "570b100b15fe4ba2", + "reach/copy-query-refused": "4004640de42ba806", + "reach/copy-resume-unpaired": "92c441fad774996e", + "reach/copy-cursor-refused": "53d6b9dea54add7b", + "reach/copy-reach-refused": "639427239343d101", + "reach/copy-reach-ordinary": "eebcae075ad2b7f3", + "reach/copy-no-type": "f67fcbca8ff1bfea", + "reach/copy-refusal-order": "96f7e676ed749c5d", + "reach/stream-no-header": "b2dc8ee2bb00d631", + "reach/marker-first": "d56ab9e7e0f2f316", + "reach/marker-no-id": "5fa7e2661078bcd4", + "reach/marker-body": "e17d4d069b7e36c4", + "reach/marker-event-type": "9d6f018002c56bb1", + "reach/marker-cursor": "d1a87485613e6b97", + "reach/marker-reach": "d0c993ea3f645f18", + "reach/marker-instance": "ebcd36f512fcc993", + "reach/marker-same-reach": "5638cf105002ae71", + "reach/marker-live-bound": "e9c020193fc9b835", + "reach/marker-live-after-replay": "975fb91bf68e9c63", + "reach/resume-same-reach": "649ffc53866548b0", + "reach/resume-ahead": "47f5037b3b5ec414", + "reach/resume-ahead-closes": "2d42622ea5ef8105", + "reach/resume-ahead-no-live": "117eafcea4fc0f25", + "reach/opening-incomplete": "9523282de3332861", + "reach/per-credential": "b6afeb6c064848ae", + "reach/per-app": "c7897d3be4978835", + "reach/moves-type-reach": "deca63c7cf83edab", + "reach/moves-edge-reach": "6c1659d6eb20c2e0", + "reach/moves-metadata-reach": "bafc4132f047b3df", + "reach/moves-extension-reach": "1471aa89a4facdc3", + "reach/moves-source-filter": "6eb8dd1bc2639357", + "reach/keeps-write-reach": "47d79d8968408141", + "reach/keeps-content": "93c09baaa15eb792", + "reach/keeps-lifecycle": "c19b85c8b46ad546", + "reach/moves-retype": "2006a025cd4272a4", + "reach/keeps-same-type": "f38ee07bc3ffe65d", + "reach/moves-edge-source": "4b28ec48f9a6b47f", + "reach/keeps-edge-writes": "aebbcf7ee90054ba", + "reach/moves-type-topology": "8d25945196b9d41a", + "reach/keeps-type-update": "ceaa4f17a2e14c9f", + "reach/moves-edge-type": "9f7ab6b6914a20b9", + "reach/moves-purge-sweep": "d297f813fccb75fe", + "reach/change-before-answer": "65f1435a4f60e7ed", + "reach/keeps-on-rollback": "909a21d60bebc971", + "reach/conditional-certified": "51a29cb05e69fa01", + "reach/conditional-no-store": "e05852a21caf8c81", + "reach/conditional-no-body-reach": "8b7c48be78df2ea8", + "reach/conditional-ordinary": "17c276be5875c3e5", + "reach/conditional-item-page": "de9329802cf8228b", + "reach/conditional-door-refused": "d351362f78bb0b76", + "reach/write-header-ignored": "9b78c79b82aadfb0", + "reach/write-header-replay": "be3cf4bc16477966", + "reach/conditional-reach-refused": "6edd33115c65862e", + "reach/conditional-query-ordinary": "607c9af425777812", + "reach/conditional-order": "268abe9833ce49ec", + "reach/conditional-coherent": "e0edffa9cfc32a73", + "reach/certified-absent": "ea9db5946ed52ea4", + "reach/certified-type-refused": "b9ac50d61fff2c8f", + "reach/certified-edge-refused": "9404f64b796e5e0f", + "reach/certified-keys-current": "cf48b803cc45555b", + "reach/uncertified-failures": "88215f33ce4c4ad1", + "reach/page-next-cursor": "e44de2cc41aea89c", + "reach/page-rows": "d2435b392262cc6e", + "reach/page-excludes": "d4d075fe0cb0cb48", + "reach/listed-direct": "a7868bd56f2b99c3", + "reach/listed-neighbor": "dea9844bd91cf7e7", + "reach/listed-definition": "d188910b35776221", + "reach/listed-by-id": "f36e379e95b9ea54", + "reach/listed-bulk-get": "c0399825c901a005", + "reach/listed-not-on-edges": "7f0aeed0ed9f3ed3", + "reach/receipt-uncertified": "7fc05fa5c5932807", + "reach/changed-conditional": "be4fd3304744d092", + "reach/changed-resume": "d6bfcb5714091bd7", + "reach/changed-body": "5a5e2974d9b0d050", + "reach/changed-uncertified": "79fe028e6422fe0f", + "reach/terminal-frame": "9bafaf455dea5e9e", + "reach/terminal-closes": "593ae63a31c258e9", + "reach/terminal-withholds": "022014429db248a0", + "reach/terminal-races": "508e8d981bc25f2d", + "reach/terminal-races-silent": "f716d0c7b23eea9d", + "reach/frame-listed": "cf058fcf4508e9fd", + "reach/frame-excluded": "505bfa023c93eba8", + "reach/frame-edge-shape": "1b9ccffd7f2d7dfb" }, "search-and-filters": { "search-and-filters/undeclared-key": "392a348d6d5dd797", diff --git a/src/generated/error-codes.md b/src/generated/error-codes.md index 48d2899f..d1a826e3 100644 --- a/src/generated/error-codes.md +++ b/src/generated/error-codes.md @@ -52,7 +52,7 @@ | `instance_changed` | 409 | A request names another instance in `X-Marfa-Instance-Id`. Nothing is written. Rebuild the working copy from the instance at this address. | | `link_taken` | 409 | A write would give an item a link that another item of its type holds. | | `owner_exists` | 409 | The instance already has an owner. | -| `read_view_changed` | 409 | A conditional copy read or copy stream carries a proof for a read view that has since changed. Rebuild the working copy. | +| `reach_changed` | 409 | A conditional copy read or copy stream carries a proof for a reach that has since changed. Rebuild the working copy. | | `source_id_conflict` | 409 | A change to `source_id` names a natural key that another item already holds under the same source. | | `type_already_exists` | 409 | A type is already registered under this identifier. | | `type_chain_unresolvable` | 409 | The stored parent chain of a type is circular or too deep to resolve. `PUT /types/{id}` still accepts a corrected schema. | diff --git a/src/generated/event-types.md b/src/generated/event-types.md index 735ae4b1..fdbe5bd3 100644 --- a/src/generated/event-types.md +++ b/src/generated/event-types.md @@ -8,11 +8,11 @@ | `item.state_changed` | Streams and webhooks | An item moves to another lifecycle state. | | `metadata.changed` | Streams and webhooks | An item's tags or extensions change. | | `edge.created` | Streams and webhooks | An edge is created. | -| `edge.updated` | Streams and webhooks | An edge's properties change. | +| `edge.updated` | Streams and webhooks | An edge's properties change, or one of its ends moves to another item. | | `edge.deleted` | Streams and webhooks | An edge is deleted. | | `stream_cursor` | Streams | First, when the stream read the log as it opened: where the log stood then. | | `stream_live` | Streams | Once the catch-up is over: everything up to its cursor has been sent or withheld, and what follows is live. | | `stream_incomplete` | Streams | Last, when the stream can no longer deliver what it opened with. | | `catchup_too_old` | Streams | Last, when the log no longer holds the events after the `Last-Event-ID` the client sent. | | `cursor_ahead` | Streams | Last, when the `Last-Event-ID` the client sent is past the latest event in the log. | -| `read_view_changed` | Streams | Last on a copy stream, when its read view changes. | +| `reach_changed` | Streams | Last on a copy stream, when its reach changes. | diff --git a/src/generated/settings.md b/src/generated/settings.md index 071136d0..4d43f341 100644 --- a/src/generated/settings.md +++ b/src/generated/settings.md @@ -46,7 +46,7 @@ | `TRUSTED_PROXY_CIDRS` | None | Comma-separated CIDR ranges, IPv4 or IPv6 | The address ranges of the proxies whose `X-Forwarded-For` header the server believes. When empty, the header is ignored. | | `TRUSTED_PROXY_HEADER` | None | An HTTP header name | The name of a header that the platform's edge overwrites with the client address. It takes precedence over `TRUSTED_PROXY_CIDRS`. | | `API_KEY_SALT` | None. Required in production. | Text with no whitespace around it | The salt for hashing API keys and app tokens. Changing it invalidates every existing key and token. Outside production, an unset salt falls back to a built-in one. | -| `MARFA_AUTH_SECRET` | None. Required in production. | Text of at least 32 characters, with no whitespace around it | The secret that signs sign-in cookies, authorize queries, read-view tokens and credential-free blob links. It must be at least 32 characters. Outside production, an unset secret falls back to a random one for each process. | +| `MARFA_AUTH_SECRET` | None. Required in production. | Text of at least 32 characters, with no whitespace around it | The secret that signs sign-in cookies, authorize queries, reach proofs and credential-free blob links. It must be at least 32 characters. Outside production, an unset secret falls back to a random one for each process. | | `MARFA_AUTH_BASE_URL` | None. Required in production. | Absolute `http` or `https` URL | The public URL for OAuth, cookies, and links. It has no user name, password or query string. Outside production, an unset URL uses the assigned port with `http://127.0.0.1` when `MARFA_LISTEN_HOST` is `127.0.0.1`, otherwise `http://localhost`. | | `CORS_ORIGINS` | None | Comma-separated origins, each `scheme://host[:port]` with no path | The browser origins allowed to call the API across origins, beside the web pages the owner approves, and trusted by the sign-in forms. Each is an exact scheme and host with no trailing slash. | | `MARFA_PERMISSION_BUNDLES` | None | JSON array of permission bundles | The permission bundles the consent screen offers, replacing the built-in ones. Each entry has a string `id`, an array of `scopes` and a boolean `default_on`. | @@ -74,7 +74,7 @@ | `AUDIT_CLEANUP_INTERVAL_MS` | `86400000` ms | Whole number of milliseconds, 1 to 3153600000000 | How often the `audit-cleanup` job runs. | | `MARFA_REVOKED_GRANT_RETENTION_DAYS` | `90` days | Whole number of days, 0 to 36500 | How long a revoked application grant is kept. At 0 the job that purges them is off. `PUT /config` does not override it. | | `MARFA_GRANT_INACTIVITY_DAYS` | `365` days | Whole number of days, 0 to 36500 | How long an application grant may go unused before the server retires it. At 0 grants are never retired. `/config` overrides it. | -| `MARFA_EVENT_LOG_RETENTION_HOURS` | `168` hours | Whole number of hours, 0 to 876000 | The least time an event stays in the event log, which bounds how far back a stream can replay. At 0 no event expires by age. `PUT /config` overrides it. | +| `MARFA_EVENT_LOG_RETENTION_HOURS` | `720` hours | Whole number of hours, 0 to 876000 | The least time an event stays in the event log, which bounds how far back a stream can replay. At 0 no event expires by age. `PUT /config` overrides it. | | `MARFA_EVENT_LOG_CLEANUP_INTERVAL_MS` | `3600000` ms | Whole number of milliseconds, 1 to 3153600000000 | How often the `event-log-cleanup` job runs. | | `VERSION_THINNING_INTERVAL_MS` | `3600000` ms | Whole number of milliseconds, 1 to 3153600000000 | How often the `version-thinning` job runs. | | `FEED_EXPIRY_INTERVAL_MS` | `3600000` ms | Whole number of milliseconds, 1 to 3153600000000 | How often the `feed-expiry` job runs. |