Skip to content

feat: write-verdict foundations — rejection spike, error taxonomy, uniform /health#11

Merged
FelineStateMachine merged 4 commits into
mainfrom
feat/write-verdict-foundations
Jul 19, 2026
Merged

feat: write-verdict foundations — rejection spike, error taxonomy, uniform /health#11
FelineStateMachine merged 4 commits into
mainfrom
feat/write-verdict-foundations

Conversation

@FelineStateMachine

Copy link
Copy Markdown
Owner

Implements the server-side groundwork for lofi's effect system. Closes #10.

Spike outcome — all three rejection properties hold (tests/write_verdict_test.ts): a rejected write surfaces permission_denied correlated to the originating batch id on both verdict surfaces (wait()PersistedWriteRejectedError, and the onMutationError fallback carrying the batch record); an unacked write is re-proposed on reconnect and its rejection fires then; and the verdict is deterministic across reconnects and independent runtimes. No upstream jazz-napi ask is required for the client journal to record verdicts itself.

Two findings shape the client contract: the runtime refuses current-policy violations synchronously at the call site (server adjudication only ever applies to stale-policy writes — accepted locally, denied by a store whose permissions tightened after the client last synced), and the fallback event fires once per runtime lifetime, so consumers persist verdicts keyed by batch id and re-derive on demand via wait().

  • §1 Spike: revoked-permission rejection fires with a correlating batch id
  • §1 Spike: disconnect/reconnect re-sends the unacked write and the rejection re-fires
  • §1 Spike: verdict deterministic across reconnects (and across independent runtimes)
  • §2 Stable codes with permanent/transient classification (src/verdict.ts, exported from mod.ts)
  • §2 Code audit: alpha.53 emits exactly permission_denied; unknown codes default to transient by design (never compensate on an uninterpretable code — the upstream registry ask is deferred until more codes exist)
  • §2 Classification exposed so the lofi runtime never string-matches reason
  • §3 /health verified available and cheap in open, ticket, and peer modes (no gate change needed — verification, tests, and the written contract)
  • §3 Client contract documented: WS lifecycle + health polls compose into a connection observable
  • §4 Harness coverage for the spike scenarios and /health across modes
  • §5 /node docs: write-verdicts.md + /health contract in http-surface.md (bump LOFI_NODE_REF from the lofi side after this lands)

deno task check clean; deno task test 58/58; deno task publish:dry succeeds.

…d by code

Consumers classify rejection codes through one exported registry instead of
string-matching reason text. The pinned alpha emits exactly one code over the
sync protocol (permission_denied, permanent); unknown codes classify transient
so an unrecognized code can never trigger irreversible compensation.
…rivation, determinism

The server adjudicates only stale-policy writes (the client runtime refuses
current-policy violations synchronously), so the fixture tightens permissions
while devices are offline. Pins three properties a client-side write journal
needs: rejections correlate by batch id on both verdict surfaces, unacked
writes re-sent on reconnect re-derive their rejection, and the verdict is
stable across reconnects and independent runtimes. The fallback event fires
once per runtime lifetime; re-derivation goes through wait().
Open mode: Jazz serves it on the public URL. Ticket mode: unauthenticated at
the top level and under a ticket base; revocation 401s the ticket path while
the top level stays 200. Peer mode: carried over the iroh tunnel. A dead
store degrades to 502, never a hang.
New write-verdicts page: where verdicts come from, local refusal vs server
adjudication, the three rejection properties, at-least-once implications for
consumers, and the permanent/transient taxonomy. The HTTP surface page gains
the /health contract per connection mode and the client-side composition into
a connection observable.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: write-verdict foundations for the lofi effect system

1 participant