320 lines
24 KiB
Markdown
320 lines
24 KiB
Markdown
# 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](README.md) and [runtime shapes](runtime.schema.json). 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.
|