In development

Security model

Scoped read-only grants, current authority and revocation boundaries.

Status: security/domain contract freeze (84A + 84B / W18). Not implemented. Not multi-principal production sharing. First personal companion remains trusted-owner allowlist until sprint 85 enforces this boundary. Imported data never mints authority. UBI bootstrap/pairing values remain a separate blocked contract.

Trust boundaries (unit A)#

BoundaryCurrent observationFreeze rule
Listener startup credentialCopied at Server.start; not dynamic revokeDelivery must recheck current principal policy before send; startup copy alone is insufficient
Application ordinary documents!can_write refuses; owner-poweredFirst bridge uses owner; multi-principal waits for 85
Snapshot leasesProcess-local; not authorityLease ≠ grant; recheck scope on borrow/delivery
MCP / wire sessionAuthenticated store+sessionClient-supplied principal/scope never authoritative
Browser Origin / CORSHost checks exist; missing Origin permitted under native policyAbsent Origin is not privilege; browser path needs explicit profile (86)

Rights vocabulary (normative names)#

Distinct rights (not interchangeable): read, transform, execute, publish, seed, transmit. A grant names grantor, subject, object/field selector, actions, destination, validity window, delegation limit, revocation epoch and audit reference. Owner-only local slice today does not issue these grants. Executable admission today uses owner/can_write / write-gate names from C05; those are current slice gate labels, not members of the frozen grant-rights vocabulary above. Sprint 85 maps or replaces them under accepted semantics.

Normative dimensions (unit B / W18)#

Every authorization decision binds all of the following at the current control-branch head. A stamp from an earlier epoch cannot substitute.

DimensionBindingNotes
PrincipalAuthenticated credential -> principal idNever from caller-asserted context counters
Storestore_id of pinned sessionWrong store -> fail closed
BranchEnvelope branch_id after namespace rulesControl branch 2 is not ordinary data
ActionOperation / right nameread ≠ transform ≠ transmit
ObjectCollection + record id (or schema/metric id)Cross-object needs explicit grant covering both
FieldField selector inside objectPartial views omit unauthorized fields
VersionGrant revision + authority_epochHistorical permission never authorizes new delivery
ErrorTyped deny without sibling disclosurePrefer forbidden / omit; never leak existence via counts when policy forbids

Entry -> resolver -> Application -> send chain#

Maps the actual local service path (C05) to fence sites. Exact send-permit hook file remains an open gate; the stage contract does not.

StageCurrent owner (observation)Authority obligation
Framing / routesrc/transport listener HTTP entryHost/Origin/length/method; invalid framing never reaches resolver
AuthenticateService credential registry resolveBearer -> principal; startup registry copy is authn only
Session / store bindRequest resolver ahead of ApplicationPin store_id + session_id; reject foreign store/session
Authorize (admission)Application can_write / capability (src/product / application path)Bind principal/store/branch/action/object/field/version
PerformApplication + engine under admitted snapshotCommit may produce immutable receipt under then-current epoch
Delivery fenceBefore response bytes leave the processRecheck current control-branch authority head
SendLoopback write path (exact file open gate #3)Queued unsent bytes drop on fence fail; in-flight plaintext not recalled

Admission vs delivery fence#

StageGateEffect if revoke wins race
Framing / authnSession + tokenNo work admitted
AuthorizePrincipal/store/branch/action/object/field/versionTyped deny; zero durable effect
PerformMutation/query under admitted snapshotMay commit under then-current epoch
Delivery fenceCurrent control head before sendQueued unsent bytes dropped; already-sent plaintext not recalled
ReceiptImmutable mutation receiptMay exist after revoke; does not restore delivery rights

Distinguish: (1) bytes already on the wire, (2) admitted committed operations, (3) queued unsent results. Only (3) is fenced by current-authority delivery.

Ownership, expiry and revoke ordering#

ResourceOwnerExpiry / revokeHistory rule
Snapshot leaseProcess that borrowedRelease on cancel/drop; not a grantPast lease ≠ current authority
Mutation admission mutexServiceShared by every mutation route; not held across network waitsLock release ≠ revoke
Delivery permitCurrent control-branch policyRecheck at send; revoke drops queuePrior epoch stamp never reopens send
Grant historyControl namespace (future)Audit trail onlyHistory never grants current authority

Ordering freeze (implementable without inventing clock semantics):

  1. Revoke updates control-branch authority head (or credential registry for authn-only cases such as revokeAllReaders).

  2. New admission reads the post-revoke head; refused work has zero durable effect.

  3. In-flight perform that already passed admission may still commit a receipt.

  4. Delivery fence reads the current head again; queued results fail closed.

  5. Historical grant/permission stamps remain readable for audit and never authorize a new response.

Wall-clock vs monotonic expiry for grants remains an open gate.

Typed error catalog (compact)#

SituationPreferred typed outcomeDisclosure rule
Authenticated but action/object/field deniedforbiddenNo sibling names/counts
Missing/invalid bearer or resolved principalunauthorized (HTTP 401 / slice equivalent)No store contents
Wrong/stale session_idstale_sessionNo mutation
Wrong store_idfail closed / unauthorized storeNo cross-store hint
MCP client scope overrideScopeOverride / tool errorNon-sensitive
Same id, different logical bodyidempotency_conflictReceipt scope only
Delivery fence lose race after commitfence refuse on sendReceipt may already exist; no field leak

Exact wire string aliases remain owned by C02/C05; this catalog binds deny semantics for sprint 85 without inventing new public error codes here.

Decision tables (threat / authority oracle)#

RequestRequiredDeny / no-disclosure / no-effect
Read field FSubject holds read on F at current epochOmit field; do not leak via counts/errors
Mutate documentCurrent slice owner/can_write gate; later grant + expected headTyped forbidden; zero effect
Expand evidenceRecheck current authorityFail closed; no stale handle revival
Queue response then revokeDelivery fence under current control headDrop queued bytes; receipt may already exist
Cross-object or cross-destinationExplicit grant covering bothDeny without naming forbidden siblings
Replay same logical idBound principal+store+branch+bodyidempotency_conflict if body differs
Use restored old tokenFresh runtime credentials after restoreUnauthorized / stale_session
Import / fixture dataNo automatic grant mintData ≠ authority
MCP scope overrideLaunch-fixed collection/branchScopeOverride / tool error; non-sensitive
Stale epoch stamp as delivery permitCurrent control head onlyFence refuse; no sibling disclosure
Control-branch write via ordinary document cmdProtected namespace rulesTyped refuse; durable position unchanged
Caller-asserted principal / Context countersCredential resolve onlyIgnore counters; authn failure if credential missing

Preserve existing owner-only operation limits of the executable local slice until sprint 85 replaces them under accepted semantics.

Linearization#

Explicit order: validate framing -> authenticate session -> authorize principal/store/branch/action/object/field/version -> perform -> current-authority delivery fence -> emit bounded bytes. Revocation cannot retract plaintext already received. Cross-branch atomicity is not promised; fence/order instead.

Proposed source leases (implementation follow-on; not this unit)#

Seam (observed path)Role
Listener credential registry (src/transport / service registry)Authn only; not delivery policy
Application can_write / principal (src/product application path)Admission
Control-branch authority epoch (branch 2 / control head)Delivery fence head
MCP adapter scope (MCP launch pin)Launch pin; never client override
Future grant store on branch 2Sprint 85+
Exact loopback send-permit fileOpen gate #3 — not leased here

Independent interleavings to prove later (cite W09 / SPRINT-40 schedules):

  1. Revoke-before-proposal_prepare vs committed-receipt replay after later revoke

  2. Delivery-fence drop of queued bytes after post-commit revoke

  3. revokeAllReaders resolve-null vs owner retained (authn schedule)

  4. Listener startup credential copy vs on-disk rewrite (HTTP 401; authn-only)

  5. Restore credential rotation (W16) — old token never admits

Open gates (do not invent)#

  1. Clock/expiry/restart rules for grants (wall vs monotonic)

  2. Delegation cycle depth and whether agents may edit spending ceilings

  3. Exact transport send-permit hook site (entry vs loopback send)

  4. Creator handoff without implied decryption

  5. Independent security review assignment before sprint 85 dispatch

Relation#

Does not replace ubi-bridge trusted-owner first proof. Does not authorize browser “owner can do everything” shortcut. Implementation is sprint 85 after accepted authority semantics and registry assignment. No new service route or credential model is implied by this freeze alone.