On this page

On this page

Get started

Writer admission authority

Writer admission authority

This program moves bundled writer admission to one dedicated worker while preserving current authority, FIFO ordering, final host COMMIT authorization, and receipt settlement. No schema, persistence, configuration, or update migration is proposed. Restart reconstructs process-local authority through the existing owners.

The bottleneck is host scheduling, not the cost of a Boolean check. A traced chat.send ACK spent 673 of 765 ms waiting for admission; the preceding change measured ACK p50/p99 of 1,209/1,693 ms with 20 senders (prior measurement). A feasibility probe answered from shared state in 0.064 ms but incorrectly granted after policy revocation. Forwarding the live callback instead waited through a 200 ms host stall. Those diagnostic observations justify transferring authority ownership contracts; they do not predict production latency.

The first slice transfers profile revision/status checks through shared cells and adds a read-only admission service factory with two typed profile checks. Bound and current-settled operations use the same canonical state as host assertions. The factory is exercised through real worker tests; production dispatch stays with the host until remaining dependencies can transfer. A measured intermediate host-to-service preparation detour added latency and was removed. Native publishers fence immediately before physical COMMIT; known rollback preserves the prior revision, while uncertain native outcomes stay fenced. Retired generations never revive through delayed descriptor delivery. First creation retires unresolved profile authority even when the database admission itself remains valid across path-to-file identity promotion. The lifecycle publishes that promotion through its existing shared integrity revision before changing identity, including worker-only creation and alias reconciliation. The existing worker-task owner handles service failure, termination and restart.

This slice transfers no policy payload or native write grant. Descriptors retain their exact shared buffers directly, so no service registration map can reclaim or substitute a generation. Mixed physical/request/run authority, final host COMMIT and settlement remain on their existing path. Descriptors also retain the existing shared admission-revocation cell, so worker-only close refuses reads before asynchronous drainage. Service reads do not certify the remaining physical custody still checked by the host. Later owners must supply those contracts and native-to-service transport before transaction admission can bypass the host.

Current owners and required transfers

Source locations below refer to commit 4ca02f6c720e6346a0d57b158cc38484fdf5c8da; paths start at src/. Admission composes these owners; none alone authorizes a write. Each row names the current read, mutation boundary, and proposed transferable facts.

Owner and source anchor Current facts and mutation points Transfer contract
Physical admission: infra/sqlite-database-admission-record.ts:16–84,153–201; infra/sqlite-database-admission.ts:565–639 File identity, format/schema facts, write revision, exact generation and references; fact invalidation, metadata retirement, explicit retirement before descriptor close. Reuse existing identity/generation/shared cells and open-time retention. These establish physical custody, never user authority.
Logical/native execution: state/openclaw-agent-execution-owner.ts:136–152,327–387,492–503,582–605; state/openclaw-agent-execution-native.ts:119–127,640–641 Current owner/scope, deletion and creation guards, native availability, borrower lifetime; release, close and revoke become effective before awaited cleanup. Separate logical, native, borrower and creation/deletion references. Publish closed state before each transition; retain accepted work through native settlement.
Creation/deletion: state/agent-creation-claim.ts:68–106,158–175; state/agent-deletion-cleanup.ts:98–132,176–191,314–343; sessions/session-agent-work-admission.ts:41–88,112–138; state/agent-deletion-journal.ts:410–454,486–564 Exact creation/cleanup scope, physical target, lease, journal operation and phase; release, deletion handoff, completion/removal. Ingress closes before journal publication. Exact claim/lease/journal references and activity revisions. Invalidate before mutation; retain failed cleanup. Only the same live creation claim may bypass its completed tombstone.
Agent readiness: state/agent-database-admission.ts:276–348,383–395 Per-store/per-agent refusal and temporary preparation scope; refusal replacement, successful preparation and scope close. Exact refusal/preparation generation. Only its live preparation scope may bypass that pending refusal; invalidate before replacement.
Broker request: infra/sqlite-worker-broker-reply.ts:58–70,195–229,545–570 Exact slot/job, dispatch state, cancellation, maintenance and access; current-job replacement and slot failure. Shared job identity/state and applicable cancellation. Post-dispatch caller abort must not silently abandon accepted writes.
Shared lifetime/maintenance: state/openclaw-state-db-async-lifecycle.ts:139–159,197–205,412–423,474–483; process/schema custody: infra/gateway-state-owner.ts:145–153,343–385,452–455,627–662 Captured shared generation, integrity seal, parent/caller admission, maintenance phase, process lock and schema lease; invalidation, closing, custody loss/release. Generation/phase and exact lease references; typed schema preparation. Existing physical verifier publishes loss before mutation. A pathname, heartbeat or expiry alone grants nothing.
Request/device source: gateway/device-revocation.ts:135–179,217–241,285–301 Request versus accepted source, references and revocation; acceptance, device invalidation and owner close. Distinct request/source cells and acceptance state. Preserve accepted source custody across disconnect or tentative transport changes; committed source revocation still denies.
Run/claim: infra/agent-run-registry.ts:360–501 Exact operational instance, claim, lifecycle and composed source; same-ID replacement, release and failure after source assertion. Exact claim/lifecycle references plus typed source assertion; recheck after policy evaluation. Same run ID cannot revive an old claim.
Operator: gateway/operator-run-authority.ts:127–158,284–486 Gateway/source identity, scope, profile, assignment, role and model ceiling; source/assignment/policy changes permanently revoke capture. Captured ceiling plus current profile/config/plugin-metadata revisions and source references. Preserve original/current model-policy intersection and retained continuation lifetime.
Profile: state/user-profile-events.ts:149–177,213–364; state/user-profile-list.ts:236–307 Profile, identity, channel and account-link revisions, pending/uncertain mutations, committed catalog; pre-COMMIT fencing and native settlement. Per-store/per-key cells plus immutable facts. Preserve exact-bound reads versus current-settled reads; unknown outcome never reopens authority on timeout.
Session/sharing: gateway/session-access-authority.ts:257–331; gateway/session-row-projection-generation.ts:92–145; gateway/session-row-membership-read.ts:215–235 Projection/store/generation, session ID/lifecycle, readiness, membership and related policy; replacement/removal, sharing and membership changes. Exact session references plus readiness/membership revisions. Pending is retryable without retirement; identity mismatch or non-pending denial permanently retires the capture. Fence writers before their effects, not from later events.
Config/tool policy: config/runtime-snapshot.ts:230–242; gateway/server-reload-managed.ts:341–346; gateway/session-resource-tool-policy.ts:37–116 Current config/role, selected model, lineage, plugin metadata and sandbox policy; config activation currently precedes notifications. Immutable prepared inputs plus publisher-owned revisions. Invalidate before activation; preserve locked-model denial and sandbox equality. Event subscriptions cannot establish this ordering.
Caller preparation: config/sessions/session-actor-sqlite.ts:113–150; config/sessions/session-entry-patch.ts:84–129; config/sessions/session-turn.ts:218–257 Accepted/current assertions, native observation, authorization, cancellation, mutation guards, source alternatives and pending-input custody. Typed operations over the transaction preimage, preserving order, return values, refusals and bookkeeping effects; never serialize only the last allow/deny answer.
Native settlement: infra/sqlite-worker-operation-settlement.ts:104–143; infra/sqlite-worker-broker-reply.ts:596–691 Actual post-COMMIT receipts, completion/unknown outcome, native exit and publication before reply. Keep existing host owner and transport. Revocation blocks new work, not observation of an already committed receipt.

Shared publication and retention

Each owner exports an immutable descriptor containing its kind, process epoch, exact identity/generation and retained dependency references. Each mutable subject has owner-written atomic cells: revision, status (ready, pending, uncertain, revoked) and the existing lifetime/reference state. Variable-sized policy facts travel as immutable revision-tagged messages. The service stores those payloads as a projection; the shared cells remain canonical. Missing, partial or mismatched revisions refuse or return the owner's existing retryable pending result. Use non-reused generations; retire before counter wrap.

Publication order is mandatory:

  1. Prepare replacement facts without exposing them. Synchronously invalidate the old revision/status before changing authoritative state or granting the native effect that changes it. Preserve owner-specific rollback semantics: permanent retirement stays permanent; aborted tentative config activation must not revoke an accepted source that remains current.
  2. Perform the mutation under the current owner. Preserve pending/uncertain distinctions until native settlement establishes the result.
  3. Install new immutable facts in the service, then let their original owner publish the matching ready revision after installation acknowledgment. Delayed payloads cannot overwrite a later revision. Unrelated keys stay valid; no per-write registry rebuild or filesystem polling.

A reader loads all dependency revisions/statuses, evaluates the typed operation, then rechecks all of them as one attempt before publishing its decision. The writer's final check of those references immediately before the native stage is that stage's authority linearization point. A revocation observed at either boundary denies; later revocation retains today's next-boundary/rollback semantics. Final host COMMIT revalidation remains mandatory. This is not a durable capability or permission to use a prior answer after an await.

The proof obligation for each owner is a complete writer inventory: all paths that change a consumed fact must invalidate first, including worker COMMIT, config activation, deletion, repair and shutdown. A post-change listener cannot satisfy it. Publish a pending revision before an effect whose result is not yet available; stalled publication may delay work but cannot grant stale work. Test the actual publisher, not a synthetic revocation helper alone.

Retain physical generations using the open-time reconciliation in the retention repair: keep the original physical identity, acquire/reconcile the reference before exposing the handle, balance abandoned references, retry metadata closure only, and reject explicit retirement or replacement. Integrate that repair before service cutover; do not duplicate its protocol. Authority descriptors likewise remain retained by operation custody until settlement and native cleanup, not merely until a grant/reply. Revocation and memory reclamation are different transitions.

Service and typed operations

The broker owns one admission worker per Gateway process. It retains the existing per-database FIFO and sends only the current job, exact dependencies, stage and transaction facts through private ports. The service owns decision execution, not SQLite connections, policy mutation, scheduling order or receipts.

Initial operations are assertBoundRevision and readCurrentSettledFacts for profile authority. Later owner modules provide assertRunBinding, authorizeOperatorPolicy, authorizeSessionTarget, validatePreparedSources, acceptConversationAlternatives and authorizePendingInputCustody. Each has a closed input/result type and a defined effect owner. Preserve the actor sequence: accepted/current check → native observation → policy operation → current/accepted check → grant. Preserve ordered preparation, including planners that await while holding the foreground FIFO; move it earlier only with equivalence proof. Transaction-dependent decisions consume the native transaction's preimage. Bookkeeping required before grant moves to its named owner or completes before dispatch; it cannot become an asynchronous notification.

Final host COMMIT authorization, native COMMIT, receipt publication and settlement remain unchanged. Thus host stalls can still delay COMMIT, dispatch and ACK publication. Measure those separately; this program first removes repeated admission delivery waits and their FIFO occupancy, not all main-thread latency. Cold creation/schema preparation stays host-required until its owner is migrated.

Opaque released SDK guards are another explicit host-required case: config/sessions/session-source-authority.ts:47–67,127–156 permits arbitrary synchronous SQLite reads. Keep that adapter and public behavior; migrate all bundled callers of each typed operation together and delete their old callback path. An unsupported callback must never fall through to a shared allow snapshot. Universal SDK off-thread admission requires a separately reviewed public contract.

Service failure must refuse ungranted requests and route dispatched work through existing native retirement/settlement. A terminated worker cannot publish its own death, and synchronous waits cannot rely on port-close callbacks. Before cutover, implement bounded service-response waits: the native waiter atomically expires its pending request without host scheduling; expiry never grants authority. The broker supervisor closes the failed service epoch before replacement. Size the internal wait budget from slow-host measurements; add no user configuration. Preserve completed receipts; report unknown writes as unknown and reconcile through the existing owner, never replay automatically. Replacement uses a fresh service epoch and fresh registrations after old native custody settles. Gateway crash/restart discards shared memory and rehydrates canonical persisted state; no authority survives by token or pathname alone.

Incremental delivery and proof

Land one owner per PR. First transfer profile revisions/status and their existing pre-COMMIT fence, with a service skeleton exercising those two typed reads. Keep mixed operations explicitly host-required until every dependency is transferable; do not claim chat latency improvement from this first slice. Then migrate broker/execution/maintenance custody, request/run/operator owners, config/tool policy, and session/sharing/source operations, in that dependency order. Split each group into its individual owners. Each PR lists callers, mutation coverage, removed callback code, retained public contracts and measured cost; earlier PRs remain safe without later ones.

Required adversarial proof uses barriers through real owner paths: revoke during payload delivery and evaluation; mutate config/membership while the host is blocked; retain then retire in both message orders; replace the physical file; reuse a run ID; disconnect accepted versus unaccepted sources; pending/unknown profile COMMIT; callback-induced revocation; duplicate/delayed grants and receipts; service/native crash before grant, after grant and after COMMIT. Assert refusal, permanent versus retryable state, unchanged FIFO ordering, preserved committed facts and balanced retention. Include process restart and stale-epoch rejection. Run the retained host path and migrated path against identical contract fixtures.

For every executable slice, use a synthetic isolated Team sandbox and four preselected A-B-B-A blocks, identical instrumentation/builds, fresh state per run and no discarded failures. Reuse the writer workload from the writer-count measurement: 20 sessions × five turns, one excluded warmup each, 20 history messages/session, 400 history reads, 100 metadata updates/probe rounds, four subscribers, visible observer, tool events and control plane. Also repeat the 20-sender chat.send protocol from the prior ACK measurement, preserving its fixture and pacing.

Report admission delivery by stage, FIFO hold/occupancy, queue p50/p95, ACK p50/p99, main-thread CPU/event-loop delay, service CPU and allocation, successful operations and refusals. Compare four paired block ratios with uncertainty and retain failed runs. Expect lower non-COMMIT delivery wait and FIFO occupancy; no numeric speedup is established by this document. Neutral results within noise still qualify requested/simplifying changes; added complexity needs demonstrated benefit. Local validation stays changed-file formatting/lint and a handful of focused tests; PR CI owns full gates. Benchmarks use only the constrained sandbox, never production data or normal-validation leases.

Was this useful?