Skip to content

docs: document the contract, the client, the security model, and 0.3.0's breaks - #99

Open
V3RON wants to merge 7 commits into
fix/0003-05-grant-device-projectionfrom
feat/0003-06-docs
Open

docs: document the contract, the client, the security model, and 0.3.0's breaks#99
V3RON wants to merge 7 commits into
fix/0003-05-grant-device-projectionfrom
feat/0003-06-docs

Conversation

@V3RON

@V3RON V3RON commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Stacked on #98. PR 5 of 5 implementing ADR 0003 (§11, §12, Consequences).

New and rewritten documentation

  • docs/CLIENT.md (new) — the programmatic client: connecting, the four abort behaviours, and the contract that it never reconnects and never retries, so reconnect policy is the caller's. Linked from README.md and docs/ABOUT.md.
  • docs/ARCHITECTURE.md — a new section on the contract module, the single dispatcher serving every transport, roles, and the principal/requester/owner distinction. Makes explicit that HTTP calls the dispatcher in-process rather than routing through the loopback socket.
  • The security model, stated plainly, as §4 and §5 require: socket identity is cooperative — every socket peer is the same OS user, which is the real trust boundary, and ownership checks protect against accidents, not a hostile local process. Documents both admin credentials and the CLI's resolution order, and that doctor.run without fix is agent-visible and read-only but shells out per device.

Breaking changes documented for 0.3.0

  • MCP: timeout_secondstimeoutMs. A unit change as well as a rename — an un-updated caller is silently wrong by 1000×. Documented prominently; it is the highest-risk item in this release. Also slimdevice.featureProfile.
  • CLI: --json and stderr lines are contract values; the snake_case keys are gone. Exit codes unchanged.
  • HTTP: bodies are contract types; GET /v1/leases/:id returns 404 rather than 403 for another requester's lease.
  • Wire: protocol 3, no compatibility shim. PROTOCOL_VERSION_UNSUPPORTED on mismatch, the client never restarts the daemon, and daemon.stop is accepted at any protocol version the daemon has spoken — while still requiring the admin role.

Bug fixes documented as such

The allowDownload clamp now applying to HTTP, and an HTTP request during startup parking rather than being refused. Both were divergences the ADR set out to close.

Docs that disagreed with the code

Found and fixed, rather than papered over: HTTP's "same role interfaces" description and its startup-refuse behaviour; the 403/404 change; undocumented allowDownload clamping; MCP's breaking changes documented nowhere; README.md's pre-ADR snake_case example; stale slim references in known-pitfalls.md; and ARCHITECTURE.md bullets describing code paths this stack deleted.

Follow-ups recorded in known-pitfalls.md

True cancellation during provisioning is not implemented — aborting mid-provision releases the grant rather than stopping the work, exactly as §10 requires be recorded. The HTTP tracker and notice buffer are named as the last frontend-held state, which #72 removes.

docs/EVENTS.md was already in sync — PR 2 documented ownerId on lease.released/lease.expired in the same change, per events rule 8.

Smoke tests (§12)

All four exist. Client, CLI and MCP are explicitly labelled as the §12 smoke test. HTTP's round-trip lifecycle test covers it in substance but is not labelled and runs against a fake dispatcher — noted rather than reworked.

Notes for reviewers

  • CHANGELOG.md is new and hand-written. The repo generates it via release-it/conventional-changelog, but this stack's commits carry no ! or BREAKING CHANGE: footers, so automatic detection would not have surfaced any of the breaks above. Worth deciding whether future commits adopt that convention.
  • src/contract/*.ts still carry stale in-code comments from earlier PRs ("PR 2 adds…", "no handler exists yet" for token operations) that no longer match reality. Not documentation, so untouched here; flagged for a cleanup pass.
  • ADR 0003's status is now Accepted, with the index synced.

…urity model

ADR 0003's dispatcher moved HTTP onto the same in-process Dispatcher the
socket uses and gave the daemon roles/ownership/admin credentials, but
ARCHITECTURE.md still described the pre-ADR world (role interfaces, the
superseded daemon-client MCP path, HTTP started only after convergence).
Rewrite the topology bullets against the current src/, and add a new
"Contract, dispatcher, and roles" section covering the contract module,
the shared dispatcher, the principal/requester/owner distinction, and the
cooperative-identity security model (ADR §4/§5) plainly, as the ADR asks.

Mark the ADR implemented now that this stack (PRs 1-5) lands it.
Document simlock/client and simlock/admin (ADR 0003 §10): connecting,
requesting a lease, the four abort-signal cases, and the one-connection
no-reconnect-no-retry contract that makes "reconnecting never implicitly
acquires a device" provable. Link it from README and ABOUT.md, and fix
README's worked example, which still showed the pre-ADR snake_case JSON
shape (`eta_seconds`, `udid`, ...) instead of the contract's own vocabulary
the CLI now serializes as-is.
- CLI.md: document the grant's device field as a projection (id,
  driverDeviceId, spec, address?, featureProfile?), not the full registry
  record; fix the stale `slim` references now that it's
  device.featureProfile; add a prominent MCP breaking-changes callout for
  `timeout_seconds` -> `timeoutMs` (a unit change, not just a rename -- the
  highest-risk item in this release) and the top-level `slim: boolean` ->
  `device.featureProfile`.
- HTTP-API.md: replace the stale "same role interfaces" description with
  the actual shared-dispatcher wiring; document the allowDownload
  clamping bug fix, the startup-readiness bug fix (the gateway now starts
  at socket-claim time and parks like a socket request instead of
  refusing), and GET /v1/leases/:id's 403->404 fix for another requester's
  lease -- distinct from the lease-request routes, which still answer 403
  and stay HTTP-specific until #72.
- True cancellation during provisioning (ADR §10) is explicitly out of
  scope: aborting while device work is in flight releases the grant on
  arrival rather than interrupting it, so the abandoned work still runs
  to completion and pays its purge.
- The HTTP tracker and notice buffer remain the last frontend-held state
  after the dispatcher unification, called out in the ADR's own
  Consequences as the seam #72 is meant to close.

Also fix the iOS-slim pitfall's stale "every lease response carries a
`slim` flag" line now that the flag is device.featureProfile.
Bump the version and add CHANGELOG.md (release-it + conventional-changelog
generates this file going forward via `pnpm release`; hand-written here
since none existed yet and this stack's commits don't carry BREAKING
CHANGE footers or ! markers for the automated generator to pick up).
Breaking changes are called out explicitly given how wide this release's
wire-format break is (ADR 0003).
The 0.3.0 examples rewritten in this branch collapsed onto single lines, which
oxfmt --check rejects and CI enforces via pnpm check.
@V3RON
V3RON force-pushed the feat/0003-06-docs branch from 4e5537e to 5ed7cc1 Compare September 4, 2026 06:25
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.

1 participant