Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/spec/change-feed.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ As with [the auth checklist](./wire-format.md#server-implementation-checklist),
- **Close on buffer overflow; never drop a frame silently.**
- **Only the storage owner can emit.** [Exactly one process owns a stack's storage](./adapters.md#concurrency--storage-ownership), so events exist only in that process. A multi-process server needs its own fan-out from the owner; a second process subscribing to its own `Stack` sees nothing and looks fine in testing.
- **Mint cursors in the base64url alphabet only** — a value containing a newline truncates the frame that carries it.
- **Emit for every mutating endpoint**, not the convenient ones. The list is the exhaustive one under [Versions](./wire-format.md#versions), plus create, purge, the [association](./wire-format.md#associations) and [permission](./wire-format.md#permissions) endpoints, and a `PATCH` naming only no-bump keys. None of that second group bumps `version`, so a server that emits off its snapshot path alone silently serves no association, permission, move or listing events at all.
- **Emit for every mutating endpoint**, not the convenient ones. The list is the exhaustive one under [Versions](./wire-format.md#versions), plus create, purge and every [no-bump write](./versioning.md#version-history). None of that second group bumps `version`, so a server that emits off its snapshot path alone silently serves no association, permission, move or listing events at all.

## Why SSE, and why not `EventSource`

Expand Down
5 changes: 3 additions & 2 deletions docs/spec/wire-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ A server built on core reaches this through the wire parsers in `@haverstack/cor
| `GET /changes` | `parseChangeParams()` |
| `GET /attachments/:fileId` | `parseDownloadParams()` |
| `POST /types` | `parseTypeBody()` |
| `POST /installs` | `parseInstallBody()` |
| `POST /auth/challenge` | `parseAuthChallengeBody()` |
| `POST /auth/token` | `parseAuthTokenBody()` |

Expand Down Expand Up @@ -464,7 +465,7 @@ A move that would make the record its own ancestor answers **409** (code `confli

## Versions

**The server snapshots prior state automatically on every mutating endpoint that bumps `version`** — there is no client-initiated endpoint to write a version directly. The list is exhaustive on purpose: `PATCH /records/:id/content`, `DELETE` (soft), `POST .../undelete`, `POST .../migrate`, and `POST .../restore/:version` itself (restore always creates a new version). The parent, unlisted, association and permission endpoints are the deliberate exception: none of them bumps `version`, so none snapshots either. `APIAdapter` has no [`importRecord()`](./portability.md#writing-history) — the server is the only snapshot writer for this adapter — so a server that implements anything less than every endpoint above silently loses rollback history for that endpoint's mutations.
**The server snapshots prior state automatically on every mutating endpoint that bumps `version`** — there is no client-initiated endpoint to write a version directly. The list is exhaustive on purpose: `PATCH /records/:id/content`, `DELETE` (soft), `POST .../undelete`, `POST .../migrate`, and `POST .../restore/:version` itself (restore always creates a new version). The parent, unlisted, association and permission endpoints are the deliberate exception: each is a [no-bump write](./versioning.md#version-history), so none snapshots either. `APIAdapter` has no [`importRecord()`](./portability.md#writing-history) — the server is the only snapshot writer for this adapter — so a server that implements anything less than every endpoint above silently loses rollback history for that endpoint's mutations.

```
GET /records/:id/versions — list all versions (newest first)
Expand All @@ -484,7 +485,7 @@ The second durable tier a mutation writes is [the change journal](./journal.md),

`POST .../restore/:version` accepts the same optional `If-Match` precondition described under [Optimistic concurrency](#optimistic-concurrency). It settles `content` and `typeId` alone, so it never moves the record and never lists or unlists it: neither the **403** nor the **409** a `PUT .../parent` can earn has a site here. A snapshot naming a `file-ref` the requester cannot currently reach still answers **403**, which is the only reference a restore can re-convey. See [Versioning § Restore semantics](./versioning.md#restore-semantics).

**The [change feed](./change-feed.md) reports on a wider list than snapshotting does**: every endpoint above, plus create, purge, the association and permission endpoints, and a `PATCH` naming only no-bump keys — none of which snapshots. A server that skips an endpoint there loses reactivity for that verb exactly as silently as a version-bumping endpoint's omission loses rollback history here.
**The [change feed](./change-feed.md) reports on a wider list than snapshotting does**: every endpoint above, plus create, purge and every [no-bump write](./versioning.md#version-history) — none of which snapshots. A server that skips an endpoint there loses reactivity for that verb exactly as silently as a version-bumping endpoint's omission loses rollback history here.

## Journal

Expand Down
Loading