Files
stack/docs/plans/foundation-v1-candidate/RUNTIME.md
T

24 KiB

Mediated runtime contract — phase-2 review candidate

Status: proposed technical contract after Jason's Q28 A ruling. No component below has been installed. Pi remains the engine. A Mosaic-controlled terminal is acceptable; native Pi screen/shortcut parity is not an initial requirement. The same authorized operations are intended for later desktop/web clients.

This file completes the operation and evidence rules alongside the package rules and runtime shapes. Closed JSON shapes are necessary, not sufficient. check.py checks synthetic examples, not a live permission system. Fixtures are independent shape cases, not one valid run graph.

1. Components and authority

Component Owns Must not do
Mosaic client Scope display, user interaction, authenticated requests, authorized rendering Hold client-private task truth, set trusted actor/producer, bypass the broker
Control broker Authentication binding, policy intersection, current claims/controllers, admission, routing Treat agent text or engine events as approval, fall back to another scope/account
Trusted publisher Serialized immutable records, artifact index, receipts, recoverable projections Accept a worker's producer label as proof, acknowledge an undurable commit
Engine adapter Exact Pi instance/session, pinned configuration, reviewed tool bridge Expose raw engine control channels, discover ambient extensions/context
Command gateway and supervisor Enforced command limits, process cohort identity, observations and stopping Mount credentials, host control endpoints, private engine home, or shared evidence into command jobs

The broker/publisher/supervisor are runtime infrastructure, not a new autonomous conductor agent. Git, credentials and shared policy retain conductor/owner authority. This design does not add a background goal scheduler.

Initial ingress proposal: a local owner client over a private, ownership-checked local channel. Bind owner identity through OS credentials and reviewed bootstrap policy, not a JSON principal ID. Sandboxed engines/jobs must not reach that owner control endpoint. Agent/service ingress uses a distinct, execution/delegation-bound channel with narrower operations. Provider API credentials are never control-plane credentials. Remote ingress is refused until an authenticated mapping is approved and tested; a future web interface is not permission to trust HTTP actor headers. A compromised host owner/root is outside the sandbox boundary, not something this contract claims to contain.

2. Wire, operations, and receipts

The proposed control transport uses bounded UTF-8 JSON frames. Reject duplicate keys, non-finite numbers, unknown fields, bad encodings and metadata frames over 1 MiB before admission. No shell expansion, URL fetching or host-path resolution is implied by an argument. Sidecar body ingestion is authenticated, private, bounded by the selected operation/profile, and correlated to the request. It cannot publish work or grant authority independently. Validate content and digest before replacing a staging handle with a trusted artifact reference.

controlRequest defines request ID, target scope, expected record references, optional assignment reference, exact operation and closed parameters. Actor, producer, authorization and outcome come from the service. Public ingress validates only its request sub-schema; a valid runtime-record or response object is never accepted as a client request. command.execute retains its separate command request shape. inputRequest is exclusively for prompt, stop and approved dialog replies, with execution/connection generations.

All 29 permission names have a request contract: 28 control operations and the separate command request. Descriptive CLI commands are wrappers, never another permission system. JSON stdin/file forms submit the same request; they do not allow arbitrary engine JSON. No new command described here exists today.

Family Required interpretation beyond shape
Project/workspace create/change Proposed ID/payload is not a published envelope. Validate exact record-kind payload, owning scope, lifecycle and reserved/delegated target IDs; publisher supplies envelope/authorization. Workspace creation needs an existing exact project.
Mission/task create/change Preserve single-parent ownership, mission policy intersection, dependency acyclicity and current approved intent. A proposed accepted status cannot bypass acceptance.
Assignment change Null current reference explicitly requests creation; otherwise exact current ID/revision must match. New assignment does not abandon existing assignments.
Registration manage Explicit creation/update; grantee identity, parent ceilings, allowed role and delegation must resolve. Never infer membership from creation or dependency.
Work read records returns authorized work records; execution-status returns safe execution metadata; configuration runs the shared hash check. No transcript, account secret or private launch-input dump.
File read/change Only the bound workspace, permitted path components and current limits. Contents/entries are distinct views. Put with null expected digest requires absence; delete requires an existing matching digest. No root deletion.
Work propose/result submit A proposal is not approved work; a submitted result is not acceptance. File/work changes require a recorded assignment.
Task/mission accept Exact subject/criteria revisions, independently authorized reviewer, verified evidence and current approval authority.
Decision issue Validate decision-kind basis and issuing authority. Creation uses a new ID; revision/revocation requires the exact current decision in expectedRefs and the same immutable identity/scope. A model cannot issue owner approval because it can write prose or name the owner.
Conversation read/observe Check separate conversation grants on each page/stream. Record visibility never auto-loads a transcript.
Execution launch/control/transfer Apply sections 3-4, not native engine launch/attach semantics.
Workspace retire/reopen Stop admission immediately; finalize retirement only after safe stop/reconciliation. Retain files/history. Reopen does not restore revoked grants or restart work.
Message send Apply section 5 at both send and delivery. No automatic work assignment or acceptance.
Audit read Resolve classified artifacts with the caller's own rights; knowing a reference is not permission.
Session adopt Explicit reviewed decision plus preserved legacy snapshot; no filename-derived membership or in-place historical conversion.

New creation/change/acceptance/adoption operation names are separate explicit grants, not implicit additions to Reader/Contributor/Reviewer/Coordinator. In particular mission.accept does not follow automatically from task.accept. System-scoped registration delegation requires reviewed ceiling authority and an approved delegation-basis: grantee, allowed operations, existing scopes, preallocated new target IDs, parent decision, expiry and finite use limit. The parent's limits still intersect it. A scope role cannot redefine shared policy. Bootstrap creation uses explicit owner authority and an auditable bootstrap assignment/bundle; ordinary agents cannot select a bootstrap bypass. Once work exists, changing actions bind to their recorded assignment. Taskless discussion and inspection never silently become file changes.

controlResponse distinguishes succeeded, accepted, already-active, refused and unknown. Accepted means durable admission only. Success/acceptance needs a receipt. An already-active response exposes identity only after authorization. Pre-admission invalid/unauthorized requests may receive an unreceipted refusal; an audit outage or uncertain action is never represented as success. Unknown effects require recovery, not a retry under a new ID. Outcome data is a classified reference.

Reason codes are closed: allowed, invalid-request, not-authorized, stale-revision, missing-state, already-active, control-conflict, retired, unsupported-capability, audit-unavailable, unknown-effects, unsafe-replacement, request-id-conflict, expired. Client copy must distinguish these without leaking private state.

Request identity is bound to authenticated principal, instance/epoch and canonical request digest, including referenced input digests. A matching retry returns its existing receipt/state. Different content under the same ID refuses. Private bodies are not copied into a public request log. After a reset/lost index, old channels/claims cannot authorize replay: recover the authoritative namespace or require explicit reinitialization and new intent. Do not silently recreate it.

3. Launch, claims, sessions, and configuration

  1. Authenticate, resolve exact identities/revisions and current policy. Closed or ambiguous scope, bad config, missing evidence or unsupported adapter refuses.
  2. Resolve work selection. Continue is the default; select/abandon name exact assignments. Abandon changes only those assignments after authorization. None permits conversation/inspection, not arbitrary changes.
  3. Reserve the single (agent, project, workspace) claim in a serialized durable transaction. Concurrency initially remains one per tuple; unsupported higher tuning refuses rather than being silently ignored.
  4. Resume selects the recorded current session or an explicit same-scope session. Genuine first use creates and announces an initial conversation. Once history or initialization is recorded, missing state is an error, not new first use. Resume pins an immutable pre-load snapshot and selected leaf (null only for a verified empty history). Verify the engine loads that history/branch; unsupported selection refuses. These private hashes are not part of the comparable base.
  5. Fresh creates a new conversation with no old chat/automatic summary. Metadata may retain predecessor references; they are not transcript loading authority. If an execution is active, an explicit replacement binding/generation and authority are required. Stop admission, verify old engine and command cohorts stopped, reconcile effects, then release its claim. Idle/abort/EOF is not proof.
  6. Bootstrap the selected pinned engine in a private instance with inference and tool admission closed. Obtain/verify native session identity and effective settings. If the adapter cannot establish this before effects, it is unsupported. Do not guess the latest file or invent an engine session header.
  7. Publish the session binding and full launch manifest, verify snapshot digests, then open only the approved capabilities. Record started state and actual process identity. Incomplete bootstrap enters recovery, not automatic replay.

A manifest includes exact agent/session/settings/capability references, image identity, comparable base projection, context snapshots, policy references and selected assignments. agentConfigHash hashes the normalized base projection; launchManifestHash hashes normalized inputs, not its own hash or timestamps. Preserve ordered inputs. Normalize the skill set before JCS serialization. Credentials and credential hashes are absent. Account selection is non-secret identity metadata, resolved through #50 without fallback or in-session swapping.

Private/personal/project/work context appears only in authorized launch inputs. Designated shared general preferences need their classification record; when they serve as shared behavior instructions, include their content digest in the base instruction projection. Do not omit a shared instruction merely because its source is named USER. Context selection verifies source kind, classification, audience and scope; a supplied category is not proof. Work context is a structured projection of R6's approved records, preserving proposed/unverified labels.

Canonical approved configuration publication triggers a comparison for affected executions. Also compare on client connection/reconnection and on demand. Publish matching/changed/unknown and checked time. Missing current sources yields unknown, not matching. Deduplicate notices by execution/old-hash/new-hash/status, retain the current status badge, and deliver on reconnect using the recorded cursor. A local UI toast acknowledgement changes no canonical state. No periodic model polling or silent reload is required. These are event-triggered comparisons, not proof of continuous live memory equality. Permission revocation acts immediately even though ordinary configuration drift is a non-blocking Fresh recommendation.

4. Control and the Pi adapter boundary

A connection is observe or control. Both need their own visibility grants; control is not implicit transcript access. There is one current controlling connection and generation per execution. Check both execution and controller generations on admission. Transfer is explicit, targets an authorized connection, and invalidates old queued input before admitting new-controller input. Previously admitted work keeps its true causal actor; transfer does not retroactively rename it.

A client disconnect does not release an execution claim or prove work stopped. Recovery replacement without the current controller requires an explicit qualified owner/delegation decision; knowing the current generation is not a grant. Revocation closes affected ingress/streams and fences new unsafe actions. It also stops affected running work, recording uncertainty until actual stopping is proven. Unrelated independently authorized/recordable work can continue.

Proposed Pi integration: a broker-owned RPC process with a reviewed, pinned tool bridge, no builtin tool escape, no ambient packages/extensions/templates/context, and no raw RPC endpoint exposed to clients. The bridge requests gateway actions; it does not execute arbitrary project commands inside the credential-bearing engine process. Engine events report observations, never permission decisions. This architecture is proposed, not a claim that the current adapter does it.

Initial prompt body is bounded text. Stop means fence admission and request safe cancellation; only supervisor proof closes the execution. Dialog replies match an outstanding approved dialog, connection, execution and generation. Unsupported engine commands/dialogs fail visibly; no pass-through of bash, session switching, model changes, login, package installation or reload. Additional reviewed mappings must preserve the same contracts. Display engine text as untrusted data: no terminal control/clipboard escape execution or web markup privileges.

5. Messages, queues, and late results

A message has sender, source scope, recipient agent/scope, routing mode, class, private body reference, subject references, expiry, reply correlation and trusted authorization. Sender identity comes from the channel. Record admission before publishing to the queue. Delivery rechecks current sender delegation, receiver membership, body visibility, expiry and exact target binding.

  • Current-scoped-session is for permitted ordinary notices. Resolve at delivery within that exact agent/workspace, never a global newest session. Missing or inactive recipient can remain queued until expiry; it does not auto-launch.
  • Exact-session never follows Fresh. Exact-execution requires both session and execution identity. Results/interactive approvals use exact-execution routing.
  • An approval message only references a separately valid decision. Match pending request ID/digest, intent revision, scope and execution; text saying approved confers nothing. Late results remain evidence for their original execution.
  • Delivered means an attributable receiver acknowledgement, not task success or acceptance. Lost acknowledgement gives unknown, not safe permission to resend.
  • Retries reuse identity/content. Receiver deduplication precedes processing. Do not claim exactly-once delivery across an unproved crash boundary.

Expiry is explicit and checked against trusted service time and policy bounds; there is no hidden default TTL or automatic approval on timeout. Current-schema calendar validation does not establish clock correctness.

6. Command limits and concrete evidence

command-spec contains reviewed command-profile/parameter-schema identities, classified parameter/input references and workspace-relative cwd (null explicitly means workspace root). No raw argv/environment appears in public metadata. The reviewed profile fixes executable identity and parameter grammar; it is not an agent-supplied shell wrapper. The parameter-schema reference must equal the profile's registered schema; callers cannot substitute a weaker schema. Profile/schema bodies are immutable reviewed contract assets identified by commit/content, not per-workspace copies of authority.

sandbox-limits records the selected sandbox profile, workspace grants, permitted endpoint identities, wall-time/memory/process ceilings, and the explicit absence of credential/host-control access. Workspace paths supplement the reviewed image, scratch and system-filesystem rules in the profile; they do not pretend to list all internal reads. Resolve current policy and take the least-privilege limits. The profile must actually enforce filesystem and network boundaries, including symlinks, mounts, /proc access, endpoint redirects/DNS and child processes. A declaration, Pi tool allowlist or --offline flag alone is insufficient.

Initial file-effect concurrency proposal: a workspace read/write lease. Writers are exclusive; read-only commands may share a read lease. Hold a write lease until its cohort ends and effects are accounted for. An uncertain writer blocks affected access, not unrelated workspaces or control-plane recovery. Finer concurrency is a later reviewed optimization. Metadata publication uses its separate serialized revision guard. File put uses verified content/destination and durable atomic publication; crashes never turn absence of a result into permission to replay.

Evidence bodies now include process observations, termination proof, decision basis and delegation basis. The publisher verifies their producer and meaning:

Body Required additional truth check
Process observation Exact backend object/cohort from admitted launch, pinned image, observation attributable to supervisor; PID/name alone is insufficient
Termination proof Admission is fenced and original cohort/descendants are gone. Never-started proof also establishes no start was admitted and no old producer can start it later. Absence or idle alone supplies neither proof.
Decision basis Subject/criteria/evidence revisions resolve; authors derived from delivery provenance; reviewer is authorized and not an author; request-bound approvals match digest/binding
Delegation basis Issuer/parent authority, target allocations, operations, expiry/use limit and ceilings all hold at use time
Command result Resolve outcomeEventId to the actual command finished/recovered event with matching command/binding. There is no second outcome/signal vocabulary. Classified stdout/stderr/output references and truncation remain distinct from work acceptance.

Artifact indexes disclose kind, scope, digest, byte length, media type, visibility, publisher and authorization, not absolute storage paths. Index and referenced body must agree. Metadata reads do not authorize body reads. Output capture is bounded/classified by profile; truncation must be explicit in the result evidence, never silently presented as full output. Credentials are allowed in neither metadata nor evidence; do not rely on a generic secret-pattern regex as proof.

The trusted journal publishes intent before effects, started after attributable creation, and outcome only after observed completion. Failure after effects blocks that execution and preserves unknown state. Recovery first proves stopping and reconciles actual files/results, then appends a new observation; it never edits an old receipt or blindly repeats the invocation.

Launch authorization must preauthorize the supervisor's specific fail-safe fencing and stopping of its own bound cohort when required recording fails. Attempt that stop even if a new stop event cannot be written; do not start exploratory recovery commands through an unaudited fallback. Signal the outage without sensitive content and retain unknown state until recording recovers and stopping/effects are verified. A later observed-at time records the later observation, not a fabricated stop time.

7. Storage, retention, and implementation admission

Use the storage ownership/publication rules in README sections 2 and 6. Mutable indexes are rebuildable projections, not the authority. The recorded runtime namespace/epoch and exact scope must survive restart or be declared unavailable. No metadata search may infer scope from an engine filename or host working path. Legacy sessions remain separate until reviewed adoption preserves the original. Adoption rollback before activation discards only unpublished staging and appends its failure receipt. After activation, safely stop affected work, explicitly revise/revoke the adoption approval, and preserve all original/new history and work effects. A now-invalid current mapping causes refusal; it does not silently select another conversation or become first use. A separately authorized explicit Resume/Fresh can establish the next valid mapping. Reversing work effects requires its own reconciliation/assignment, never an automatic historical rewrite.

No new retention duration is implied: retain records and history by default. Workspace retirement is not deletion. Evidence needed for current state, active claims, unresolved effects, live references or required recovery cannot be pruned without satisfying its protection/receipt rules. A pruned reference is explicitly pruned, not current verifiable evidence. Existing reset/prune scripts have not acquired these protections; reconcile and test them before enabling this mode.

The first mediated adapter is admitted only after an implementation charter and proof of: complete mediation; narrow mounts/egress/credential separation; exact session/config binding; crash-safe writer/idempotency; cohort stopping; revocation and stale-controller fencing; context/output privacy; protected retention; closure of legacy broad-mount/unmediated entrypoints into the protected namespace; and #50 account/materialization compatibility. Unsupported capability fails closed. Pinned Pi documentation is not a passing admission test.

Capability Evidence available now Still required before managed execution
Native/print launch Current source inspected; earlier owner launch/resume example New mediated launch implementation and negative tests
Exact selection and RPC events Pinned 0.84.4 documentation read Verify exact bootstrap/resume identity and cancelled/error cases
Pre-action mediation Architecture and typed requests only Reviewed bridge/gateway and bypass/failure tests
Sandbox Pinned Pi documentation says no builtin sandbox; current Compose broad mount inspected Actual filesystem/network/credential boundary tests
Stop/replace/control Typed records and synthetic traces Real process-cohort, crash, concurrent-client and revocation tests
Audit/publication/recovery Existing writeOnce source plus candidate rules/models Durable failure-injection and trusted-producer tests
Context/config/privacy Source risks identified; hashes and candidate classifications Admission/loading/output tests on actual adapter
OAuth refresh #50 boundary read; gate 7 still open Separately authorized provider/materializer proof

These are explicit implementation acceptance gates, not missing permissions that an agent may improvise around. No runtime feature claim follows from this draft.