- Scope: Windows-local Hub at
127.0.0.1:8790, optional exact private-tailnet browser origin, and signed outbound host fabric - State root:
%LOCALAPPDATA%\Cacheboard\Orchestrator - Evidence status: implemented against broker schema 12. Migration, runtime, provider-free browser, deterministic backup/restore, and security results belong in the verification ledger; every receipt proves only its named tree and environment.
Cacheboard may coordinate powerful local and enrolled-host development tools without becoming a general remote shell, credential store, or alternate owner of provider conversations. Compromise of browser presentation state, a connector, or one remote host must not grant broader filesystem, provider, Git, deployment, identity, lease, or approval authority.
flowchart LR
UI["Cacheboard browser UI"]
Broker["Windows host broker\n127.0.0.1:8790"]
DB["SQLite/WAL\nLocalAppData"]
Claude["Claude child process\nper-identity config"]
Codex["Codex child process\nper-identity home"]
Repo["Allowlisted repositories\nand worktrees"]
Metrics["Docker metrics service\n127.0.0.1:8787"]
Fabric["Signed host fabric\ncommand/result receipts"]
Remote["Per-user host agents\nWindows/Linux/macOS"]
Mobile["Exact private-tailnet\npaired browser"]
Connectors["Typed SSH/container/wmux\nconnector catalogs"]
UI -->|"HttpOnly session + CSRF mutations"| Broker
Broker -->|"authenticated SSE"| UI
Broker -->|"transactional metadata"| DB
Broker -->|"owned stdio"| Claude
Broker -->|"owned stdio"| Codex
Broker -->|"typed Git and file operations"| Repo
UI -->|"existing dashboard contract"| Metrics
Broker -->|"Bearer-authenticated plan readings"| Metrics
Broker -->|"signed typed commands"| Fabric
Fabric -->|"outbound poll + signed receipts"| Remote
Mobile -->|"HttpOnly session + CSRF mutations"| Broker
Broker -->|"fixed typed operations"| Connectors
The browser never connects directly to provider stdio, provider private sockets, profile files, SQLite, arbitrary repository paths, host-agent journals, SSH shells, or container runtime sockets.
| Class | Examples | Storage rule | Browser rule | Logging rule |
|---|---|---|---|---|
| Provider secrets | OAuth/access/refresh tokens, auth.json, Claude credential files, API keys |
Never copy into Orchestrator SQLite or configuration. Existing provider profile homes remain authoritative. | Never send. | Never log, hash, preview, or include in errors. |
| Authentication material | Broker signing key, bridge/bootstrap/SSE tickets, Dashboard session cookie, exact-origin Orchestrator session, CSRF secret | Signing material remains local with owner-only permissions; tickets are single-use and short-lived; sessions expire. | The Dashboard cookie is HttpOnly. The separate Orchestrator session is held only in origin-scoped sessionStorage after its one-time fragment is removed; CSRF proof is held only for the active page session. |
Record issuance/revocation metadata only, not values. |
| Conversation content | Prompts, assistant output, tool output, question answers | Provider history remains authoritative. The local dispatch vault encrypts pending provider action payloads, but bounded session/task metadata remains ordinary workflow data. Remote managed launch/follow-up prompts and non-secret question answers are bounded plaintext JSON in Fabric command history; they are not encrypted at rest or automatically deleted. Bounded redacted event/history projections may be retained for recovery and inspection; unrestricted transcripts are not duplicated by default. | May be streamed to the active authenticated view; never use localStorage as history. | Default deny; log event type, size, sequence, and redaction result instead. |
| Work Item content | Task titles/descriptions, project descriptions, link labels, safe external URLs, bounded validated proposed activity text, nullable date-only planned day, and nullable bounded minute estimate | Bounded plaintext in the schema-10 Work Item base plus schema-12 planning columns and backups. Sensitive-text recognition rejects common credential shapes but cannot prove arbitrary text is secret-free. Credentials, provider homes, raw signed receipts, prompts, and unrestricted transcripts are prohibited. | Item summaries may expose the allowlisted planning fields but omit descriptions/activity/link metadata. Authenticated detail exposes only the selected item's plaintext description, safe typed links, planning fields, and paged allowlisted activity. Never store Work Item content or planning snapshots in browser storage. | Log safe IDs, operation, changed-field names, revision, source class, and outcome; never bodies, proposal text, controller data, or arbitrary provider payloads. |
| Quick Note content | Human-authored title/body, plaintext preview, literal search, fixed color, context-only Work Item relation | Bounded local plaintext in schema-11 SQLite and backups. The sensitive-text recognizer rejects common credential shapes but is defense in depth; secrets remain prohibited. Link rows copy no Work Item text. | Authenticated allowlisted list/search/detail DTOs only. An unsaved draft may exist only in current-page memory; browser storage, bootstrap, generic snapshots, URL/history, and automatic provider prompts never contain note/search text. Render with literal textContent, not HTML/Markdown, and never auto-open URL- or filesystem-looking text. |
Logs, audit detail, idempotency request/response JSON and text-free mutation receipts, SSE, cursor, conflicts, and errors contain only safe IDs/actions/revisions/digests/field names, never title, body, preview, query, or linked Work Item title. |
| Work Item private control data | Held dispatch/run correlations, requested revision, start idempotency key, admission state, start event, execution baseline | Private scheduler-schema-2 dispatch correlation and Orchestrator-schema-10 automation-run correlation tables only. Never copy into resource-link metadata or generic events. | Never send through Work Item, dispatch, automation, bootstrap, audit, SSE, or idempotency DTOs. | Log only bounded safe reconciliation codes and opaque record IDs; never controller bodies or encrypted instructions. |
| Curated Tools & Memory content | Collection summaries, decisions, facts, handoffs, per-chat asset bindings | Persist as bounded plaintext broker workflow data and include in Orchestrator backups. Never treat it as secret storage or an unrestricted transcript mirror. | Show only for exact authenticated chat/workspace scope. | Record bounded metadata and delivery evidence, not credentials or authority. |
| Remote host material | Enrollment codes, host public keys, signed challenges, command/result receipts, local agent journal | Enrollment codes are short-lived and single-use. Host private keys and the journal stay owner-only on the execution host; the Hub stores public identity and durable bounded receipts. Remote command payload caveats above still apply. | Never expose a host private key, journal secret, provider home, or executable path. | Log host/command IDs, signatures' verification result, and bounded redacted status; never private key material. |
| Orchestration metadata | Lane/session IDs, normalized states, timestamps, capability snapshot, action status | Persist in SQLite under an explicit retention policy. | Display only within authenticated scope. | Structured, bounded, and redacted. |
| Project metadata | Canonical root, worktree, branch, dirty/test status, assigned paths, PR links | Persist canonical paths needed for recovery. | Display only to the local authenticated operator. | Avoid file contents; redact user-home segments in routine logs where practical. |
| Audit metadata | Actor, action type, target, decision, result, reason code | Append-only logical records; corrections are new records. | Read-only audit surface. | This is the log of authority changes; never include secrets or full transcript bodies. |
| Presentation preferences | Allowlisted theme, canvas width, density, 3/5/7-day planner horizon, Essential/Detailed task-card view, selected layout/view, reduced motion, validated current Work Item filters, and at most 12 saved project views containing only id, bounded name, and projectId |
Browser storage is permitted only for the exact bounded, versioned preference schemas. Current filters are separate from saved project views; selecting a saved view changes only the current project filter. Work Item/Quick Note text, planning dates/estimates or snapshots, links, events, revisions, provider data, repository/Room evidence, prompts, receipts, arbitrary CSS/scripts, and remote theme URLs are forbidden. | Non-authoritative; invalid entries fail closed to reviewed defaults, and project staleness is decided only after authoritative projects load successfully. A preference may shape a projection but cannot recover or mutate canonical data. | Not required. |
Retention must be bounded by both age and count/size wherever a retention control exists. Expiration removes Orchestrator-owned metadata, not provider history or project files. Audit retention changes require an explicit operator action and an audit record. The current remote Fabric history and curated Tools & Memory store do not yet offer a complete operator cleanup/retention feature; do not claim automatic expiry for them.
The managed-session transcript is a browser presentation over the separate authenticated exact-session event projection; it is not a new transcript store. The browser accepts only the projection's exact envelope and item keys, requires every item to match the selected canonical session, rejects duplicate event IDs and malformed or over-bounds values as invalid_payload, including event times above ECMAScript's inclusive 8_640_000_000_000_000 millisecond Date limit, and copies only the allowlisted normalized scalars into page memory. Stream refresh and event Retry capture that exact selected session ID and request only its authenticated event URL; they do not replace either paginated managed-session projection or fall back to another loaded row. When no exact managed session is selected, event evidence is not counted as view-loading truth, no event request is issued, and transcript-empty copy is not shown. It never merges bootstrap/session rows, stored payloads, provider-native frames, raw paths, prompts, credentials, or arbitrary fallback fields into that evidence.
The only valid identity IDs are:
earl
bbpyderz
ehayestrainer
claude
For each provider, the broker resolves an ID through the existing stable registry. It never chooses an identity by plan tier, label, directory order, “default” profile, or nearest match. A managed launch requires exact identity verification from the selected adapter or trusted setup metadata, according to that adapter's compatibility contract.
The broker passes the selected existing CLAUDE_CONFIG_DIR or CODEX_HOME to its owned child process. It does not read credential bodies for display, copy credentials into its state root, merge provider homes, or fall back to another identity on failure.
Cacheboard's current Claude OAuth/profile integration is a local, owner-operated workflow boundary, not a redistributable authentication design:
- each Claude profile must belong to the purchaser/operator authorized to use that subscription; Cacheboard does not share login information, make an account available to another person, or transfer a profile between operators;
- Free, Pro, Max, Team, and Enterprise OAuth is used only through the owner's ordinary local Claude Code/Anthropic application flow;
- Cacheboard never offers Claude.ai login to third-party users and never routes another user's requests through the owner's Free, Pro, or Max credentials;
- any hosted, distributed, multi-user, customer-facing, or service-provider edition must replace consumer-plan OAuth routing with an Anthropic-approved API-key or commercial authentication design before release; it also needs a fresh terms/security review and separate credential isolation.
Exact identity verification proves which account a lane selected; it does not prove contractual authority to use that account. Do not activate a lane backed by another person's or a shared login. This local-use boundary is an engineering release constraint, not a legal approval.
This boundary follows Anthropic's current first-party guidance: Claude Code legal and compliance maps Free/Pro/Max use to the Consumer Terms and Team/Enterprise/API use to the Commercial Terms, states that OAuth is for purchasers' ordinary Claude Code/native-app use, and directs developers building products or services with the Agent SDK to API-key authentication. The Consumer Terms also prohibit sharing account login information, API keys, or credentials or making an account available to someone else. These sources were rechecked on 2026-08-12; recheck them before any distribution decision.
Loopback alone does not authenticate a browser tab. The Hub requires:
- A high-entropy, short-lived, single-use bootstrap ticket delivered outside ordinary page state. The authenticated Dashboard bridge mints a separate one-time loopback ticket rather than widening or reusing the Dashboard cookie.
- After ticket consumption, one separately signed exact-origin Orchestrator session is delivered in the URL fragment once. The client moves it into origin-scoped
sessionStorage, removes the fragment from history, omits cookie credentials, and sends it only asX-Cacheboard-Session. - Protected controller projections use six explicit phases:
loading,unpaired,unavailable,loaded-empty,loaded, andstale. Only a validated authenticated empty response may produce ordinary empty copy or a zero count. Stale protected data is page-memory-only evidence with visible age and cannot authorize a mutation. - Browser-session replacement or loss and authenticated
401/403failures abort protected requests, clear pending refresh/announcement timers, queued announcements and rendered protected messages, advance an immutable reset epoch, invalidate route/resource generations, and clear session, exact-session event, request, queued-work, host, Cloud, remote-control, connector, capability, and independently tracked Audit projections before rendering recovery. Reset-sensitive knowledge and exact-metadata reads plus direct provider-asset activation must prove that epoch before publishing ordinary success, failure, reconciliation, notices, announcements, follow-up reads, or renders.401becomes unpaired and points to the authenticated Dashboard/Start Cacheboard flow;403becomes unavailable. Hosts pairing is not an authentication recovery substitute. - Exact Origin validation on every browser mutation and stream-ticket request.
- A per-session CSRF value on every state-changing request, bound to the session and compared in constant time, plus an exact body/header idempotency-key match where required.
- Authenticated
GET /api/events/ticketissues a single-use, 60-second, purpose-bound SSE ticket becauseEventSourcecannot carry the session header. The browser then opens ticketedGET /api/events; replay, expiry, origin mismatch, and wrong-purpose use fail closed. - Session expiry/revocation remains bounded. Bootstrap/SSE tickets, provider credentials, durable signing material, and CSRF values are never placed in
localStorage, persisted Work Item data, HTML, or JavaScript configuration; the one-time session fragment is removed immediately.
Requests without an Origin are accepted only for a separately authenticated non-browser administrative surface explicitly defined by implementation. Absence of Origin must never silently bypass browser CSRF enforcement.
The browser sends typed actions such as “interrupt session,” “answer request,” or “pause recipe.” It never supplies an arbitrary executable, shell string, working directory, environment block, provider home, or unrestricted path.
Every mutation validates:
- authenticated session and CSRF proof;
- exact action schema and bounded payload;
- target lane/session/room ownership;
- current state transition;
- active adapter capability;
- project-root and write-lease authority;
- pending request ID and exact approval scope where applicable;
- idempotency key and prior result;
- action-specific rate limit.
When more than one eligible chat exists in a lane, lane identity is insufficient: provider control must include the exact Cacheboard session ID, and exact host/provider/profile/provider-session bindings must agree. Ambiguous lane-only control fails closed. Logical sessions are not capped at eight, but active work is admitted through bounded lane/host queues and provider capacity rather than unbounded process creation.
Approval is never transferable through a room message or agent result. “Approve for scope” is disabled for every workspace-write session and otherwise exposed only when the adapter defines and enforces that exact scope. A writer session cannot fork because its authority is not transferable. Deployment, push, merge, destructive cleanup, privilege change, installation, global configuration, and credential operations always require direct human authorization and are never recipe-auto-approved.
Provider controls are state-transition constrained in addition to capability-constrained: message from idle; answer from waiting_input; approval/deny from waiting_approval; defer from either waiting state; steer from working; interrupt/stop only from in-flight states; resume from paused; and read-only fork from idle. This keeps one provider pump/callback authoritative at a time. Terminal, archived, disconnected, and observed sessions cannot accept ordinary provider control.
The operation catalog classifies every installed provider method as direct, native_only, observe, handoff, unavailable, or prohibited. Only direct dispatch crosses the adapter command boundary. A documented or newly discovered provider method does not become executable until its exact installed version, state gate, authority requirements, and fallback have an explicit classification.
Schema 10 makes Work Items durable organizer records; it does not make them an authority source. The only execution topology remains four fixed identities (earl, bbpyderz, ehayestrainer, and claude) by Claude/Codex, for exactly eight stable lane keys. A lane assignment chooses an identity/profile/capacity boundary only. A Work Item, project, saved view, link, Attention source, proposal, or activity event transfers no provider approval, exact-session claim, provider adoption, Room membership, repository allowlist entry, project-root access, worktree, branch, assigned path, writer claim, lease, shell, credential, deployment permission, or human-presence proof.
- Every Work Item/project/link/action/automation object uses an exact recursive key allowlist. Browser callers cannot supply actor/source provenance, sequence, rank, lifecycle timestamps, repository identity, authority, server-only relations, controller/correlation/baseline fields, signed receipts, prompts, transcripts, provider homes, or credential paths.
- Text bounds are UTF-8 byte limits. Recognizable bearer values, JWTs, common provider/GitHub/Slack/AWS key forms, sensitive assignments, and PEM private-key headers are rejected in persisted human, automation, and provider-proposal text. This is defense in depth; operators remain responsible for excluding undiscoverable secrets.
- Public serializers select every field explicitly and never spread a database row. List summaries omit description, link metadata, and activity. Item detail adds only its plaintext description and safe typed-link summaries. Activity omits actor-session internals, projection source keys, controller context, provider payloads, and receipts.
- Normal lists are cursor-paginated and Work Item rows never enter
/api/bootstrap,Broker.snapshot(), generic event snapshots, launcher payloads, or generic idempotency receipts. - Local browser persistence keeps the validated current filter object separate from saved project views. Each saved view contains only a local
id, boundedname, andprojectId; selecting it changes only the current project filter. Neither structure contains Work Item data or becomes canonical state.
Every resource link has fixed authority: "context_only". Browser and automation callers may create only relation context; execution_dispatch, execution_session, execution_automation, source_attention, and source_result are server-derived after the exact record is verified. Metadata follows a closed kind/relation schema and cannot carry controller, correlation, baseline, receipt, prompt, transcript, provider-home, credential, project-root, lease, or capability claims. Observed/manual context links are permanently ineligible for execution projection.
DELETE /api/work-items/:id means reversible Trash. Archive and Trash are mutually exclusive lifecycle markers, restore is explicit, and P0 has no permanent purge route or browser control. Only an authenticated owner move may enter Done; creation and automation cannot create, move, or restore into a completed state.
Each HTTP mutation is authenticated, exact-origin/CSRF/rate/body bounded, validated before execution, and tied to a 16–128-byte idempotency key whose header and body values match. Creation has no expectedRevision: project creation returns project revision 1 without a work_item_events row, while item creation returns item revision 1 and appends that item's created event. Project updates use project CAS and advance the project revision, but do not append work_item_events because those events require a Work Item ID. Ordinary item edits, movement, link/unlink, archive, Trash, and restore require the current item revision; each successful transaction advances the affected item once and appends its scoped immutable item event. Duplicate checks the source revision, advances the source with its duplicate event, and creates a separate revision-1 item with its own created event; its canonical result therefore includes both source and duplicate. A stale CAS proven before any effect may return 409 with an explicit public details.current; the internal no-effect marker is removed. Post-commit audit/SSE failures remain indeterminate and are not converted into replayable conflicts.
SSE publishes only work_item.created|updated|moved|linked|unlinked|archived|trashed|restored|execution_projected|execution_reconciliation_proposed|edit_proposed invalidation facts with safe IDs, revision, state/changed-field names, outcome, and at most a boolean proposal-available marker. Descriptions, proposal text, prompts, transcripts, tokens, receipts, link metadata, controller context, and arbitrary provider text are forbidden. Strict Last-Event-ID replay applies; invalid/expired cursors require bounded reload rather than silent omission.
manual, capacity_auto, and exact_lane decide routing only. All starts reuse the current scheduler/session/recipe validation and encrypted queue. The controller first persists one held scheduler job or paused Automation Engine run, then transactionally rechecks Work Item CAS, moves to Doing, appends the start event, and creates the server-only execution link. Only after the private correlation is finalized may the same effect be released. Failed cleanup stays held/paused for reconciliation; restart repairs/releases/cancels that persisted effect and never enqueues a replacement.
Private scheduler/run correlation tables never join public serializers, events, SSE, audit, bootstrap, links, or browser DTOs. dispatch.succeeded proves launch acceptance only and leaves the item Doing. Review requires an exact privately correlated provider-turn success or canonical completed automation run. Failure, question/approval need, cancellation, indeterminate outcome, or required reconciliation projects to Blocked. Only an owner moves Review to Done.
Provider edit proposals are extracted before global provider event publication. A validated, exactly correlated proposal may append bounded outcome: proposed activity while leaving item revision/state unchanged. Its body is available only through authenticated item activity; global events/SSE/audit/action/dispatch/run DTOs and link metadata carry at most a safe proposalAvailable fact. Applying selected fields is a separate owner-authenticated CAS patch.
Automation work_item_action steps may create, update, move, link/unlink, archive, trash, and restore through the same validators/CAS/events/audit/idempotency boundary. They cannot enter Done, start a provider, recursively run a recipe, purge, approve, grant protected/write authority, change Room membership/worktrees/leases, inject server relations/provenance/controller data, or bypass confirmation. Work Item events do not trigger recipes in P0. A committed step stores only the bounded work_item_action_receipt fields schemaVersion, namespace, runId, stepId, action, workItemId, beforeRevision, afterRevision, and outcome; it contains no task text, link metadata, actor session, provider payload, signed receipt, or controller data.
Explicit source creation accepts only { "kind": "attention", "id": "<UUID>" }, { "kind": "session", "id": "<UUID>" }, { "kind": "automation_run", "id": "<UUID>" }, or { "kind": "room_result", "id": <positive integer> }. The source must resolve to an exact existing Attention record, a failed/indeterminate exact session, a canonical failed or cancellation-indeterminate automation run, or a user-selected Room result_summary; an ordinary paused reconciliation run is not eligible. The server derives the default state/link/provenance, while the required owner-confirmed title and optional description pass the ordinary bounded sensitive-text validators; client-supplied transcript/body/provenance/relation/metadata is rejected. Creating a task cannot retry a provider effect or grant source-record authority.
The Task 11 browser fixture is a test-only trust boundary, not a production mode. It injects one 127.0.0.1 origin and one fixture-only localhost alternate origin into ordinary origin-bound ticket/session authentication, without widening production allowedOrigin, loopback, or tailnet policy. It uses a file-backed SQLite database and data directory beneath a newly created cacheboard-work-items-browser-* operating-system temporary root. The ready receipt contains those temporary paths and two one-use entry URLs, so it belongs in a controlled local test terminal and not a durable public log.
Both fake provider adapters count and reject every invoke, probe, or observe request. Fixture interception makes known browser provider-effect submissions fail before the adapter boundary; a zero provider-call counter is still required after automated and served QA. Rendered assertions cover authenticated empty copy, structural suppression while required This PC evidence has never loaded, read-only retention of authenticated prior evidence during refresh, protected-text clearing on browser-session loss, unpaired Dashboard/launcher recovery, and prior authenticated local/remote host success followed by transient failures with visible stale age and retained local host truth, then re-read the fixture counters. GET /__fixture/status exists only on the fixture listener and discloses only counters plus seeded fixture identifiers. Shutdown resolves and verifies the cleanup target is beneath the operating-system temp directory and its final component has the exact fixture prefix before recursive removal; it refuses any broader target. Exact historical results remain in the verification ledger and are not current-state proof. Fixture source presence, deterministic seed data, or server readiness alone still proves nothing; these checks do not verify a live provider, remote host, device, screen reader, or production environment.
Quick Notes is a separate human-owned schema-11 domain inside Tasks, governed by ADR 0007 and the exact Work Items/Quick Notes contract. Only authenticated human-owner routes mutate it. Provider output, automations, sessions, remote hosts, task text, context, links, and model output cannot become the actor or mutation authority.
The browser storage boundary is absolute for note content: localStorage and sessionStorage never hold title, body, preview, search query, linked Work Item title, or an unsaved reconciliation payload. The exact-origin Orchestrator session itself still uses its separately allowlisted sessionStorage slot. Note text is also absent from bootstrap, Broker.snapshot(), generic state snapshots, launcher payloads, audit detail, SSE, logs, idempotency request/response JSON and receipts, and automatic provider prompts. A current-page in-memory draft is the only browser draft copy and may disappear on ordinary reload; an ambiguous request retains its exact in-memory payload/key only until determinate reconciliation.
List/search return allowlisted summaries; exact detail returns only the selected note and allowlisted Work Item link summaries. Search is literal and body-only through authenticated POST /api/quick-notes/search. The opaque cursor contains a server-keyed query digest plus filter/order anchors, never query or content text. Note and search text never enters a URL, route label, request/error log, or audit row.
Mutation/idempotency results use the direct seven-field text-free mutation receipt. Conflicts and quick_note.changed SSE are also text-free; the latter contains only note ID, revision, action, and changed-field names. Audit detail contains only safe note ID/action/result/revision metadata. Public serializers are exact allowlists and never spread a database row.
Quick Note–Work Item links always store context_only, copy no Work Item text, and grant no provider, filesystem, execution, approval, session, Room, host, project-root, worktree, lease, writer, automation, remote, or deployment authority. Link creation accepts active or archived Work Items, refuses Trash, and never opens a URL or filesystem-looking note string. Archive/restore is reversible; V1 has no purge.
Project roots are explicitly allowlisted by the operator. For every filesystem or Git action, the broker must:
- Require an absolute Windows path and reject NULs, device paths, alternate data streams, and unexpected UNC paths.
- Resolve the existing target or nearest existing parent through the operating system, including junction/reparse-point resolution.
- Compare canonical paths using Windows case-insensitive semantics and a path-relative containment check, never a string-prefix check.
- Reject
..traversal and any resolved target outside the allowlisted root. - Recheck canonical containment immediately before use to reduce time-of-check/time-of-use substitution.
- Pass executable arguments as an array; never concatenate a shell command from browser values.
- Refuse a writable action without a broker-authored worktree receipt (
broker_created, exact cleanrecovered_broker_worktree, or explicitverified_attach), exact member worktree/branch match, and non-overlapping active write lease.
Allowlisting a repository does not allow its configuration to redefine executable paths, profile roots, approval policy, or Orchestrator state location. Repository configuration is untrusted input.
GitHub validation is a separate read-only operator evidence service governed by ADR 0008, not an AI lane, provider credential surface, or repository mutation authority. One allowlisted expected login is compared with gh api --hostname github.com --method GET user; the broker invokes only the canonical reviewed Program Files executables on Windows. Cacheboard never reads, copies, stores, logs, or renders the token used by the owner-controlled CLI process.
Local repository discovery disables system/global Git config, includes, credential helpers, hooks, prompts, lazy locks, and external protocols. Only the exact local remote.origin.url is accepted, and identical repositories across worktrees are deduplicated before bounded GitHub API permission reads. Raw Git/CLI failures never enter the public receipt.
The receipt is loaded only by the authenticated This PC and Settings resources, uses an exact recursive DTO, and is absent from bootstrap, generic state/compatibility, mutation receipts, SSE, audit, and provider prompts. Its cache refresh is outside the startup critical path. It reports observed viewerPermission and permanently carries remoteMutationAuthority: none, fetchAuthorized: false, and pushAuthorized: false. It proves neither Git transport readiness nor SSO, branch protection, LFS/submodules, commit-author identity, fetch, push, merge, pull request, deployment, or any remote action. Failure or mismatch never changes local project-root, Room, worktree, lease, provider, or broker-health authority.
Anthropic's sandboxing documentation says the Claude Code OS-level Bash sandbox supports macOS, Linux, and WSL2 and that native Windows support is planned. Cacheboard therefore uses two explicit host contracts:
- Native Windows does not receive a
sandboxclaim. Claude workspace-write exposes worktree-boundedRead,Glob, andGrep,AskUserQuestion, plus directWrite,Edit, andNotebookEdit;WebSearch,WebFetch,Bash,Task,Agent, andSkillare denied/unavailable. - Native-Windows
Globrejects a missing, empty, NUL-containing, or greater-than-4,096-byte UTF-8 pattern; absolute, drive-qualified, UNC, Windows namespace, alternate-data-stream/colon-bearing patterns; and any..path segment. Its optionalpathremains subject to verified-worktree containment and symlink/junction checks, with the verified worktree root used when it is omitted. - Before any native-Windows direct write reaches Attention, the adapter requires the exact tool-specific target field with no target alias, caps the entire serialized JSON tool input at 12,000 UTF-8 bytes, resolves the target inside the current lease root, rejects
.git, symlink/junction and Windows hardlink paths, and permits only a missing target or existing regular file. The matching approve-once repeats that resolution and compares the canonical target before allowing the provider callback; reusable scope is unavailable. Attention persists the exact redacted input and provider request/session/tool-use correlation in context bounded to 16,000 JSON characters. - On macOS, Linux, and WSL2, workspace-write requires the Agent SDK OS sandbox with
failIfUnavailableenabled and unsandboxed-command fallback disabled. Direct editors retain the same exact-lease guard;Task,Agent, andSkillremain unavailable.Bashis exposed only when the active lease is the entire verified worktree, never when authority is narrower.
Every workspace-write launch asks the Worktree Manager to query the actual checked-out Git branch and Git common-directory identity and compare them with the protected receipt before reserving a writer. Every workspace-write message, question answer, approve-once, steer, and resume repeats that live Git check, re-queries the exact physical writer claim, active/unexpired logical lease, verified member worktree and branch, lane/room binding, assigned-path containment, and canonical root, then recomputes the logical lease as a root inside that worktree. Caller-carried roots are not authority.
The native-Windows direct-tool boundary is intentionally narrower than shell access, but it is not represented as OS-level process isolation. Repository settings and command hooks are not loaded into the broker host on either boundary. The final target recheck occurs before Cacheboard returns allow to a cooperative local provider process, not atomically with the provider's file operation. A same-user local process can still race path replacement in that interval; this design reduces accidental/path-substitution risk but is not protection from a hostile concurrent process.
An enrolled host agent runs outbound in the provider-owning desktop user's context on Windows, Linux, or macOS. Enrollment binds a host-generated Ed25519 key through a short-lived code. Signed challenges, controller-instance epochs, replay protection, host revocation, fresh-heartbeat requirements, durable command/result receipts, and an owner-only local journal prevent a stale controller or copied result from silently acquiring current authority.
A remote profile advertises only { provider, profileId, expectedEmail, managedControl }; profile directories and executable paths remain local to the execution host. The Hub leases work only when provider, fixed profile ID, normalized expected email, and exact managed mode agree with the central lane. The current remote managed modes run Claude with a read-only tool allowlist, permissionMode: dontAsk, no settings sources, and explicit write/shell/nested-agent denial; Codex uses sandbox: read-only and approvalPolicy: never. Remote provider approval, reusable scope, workspace-write, Project Room writer claims, and arbitrary executables are unavailable.
Every Hub start resets persisted host presence to offline. New work and lease renewal require a fresh signed heartbeat from the current controller epoch; exact terminal-result retries remain acceptable only to finish durable reconciliation. Restart reconciliation runs after the HTTP listener is ready, pages bounded unreconciled terminal commands, and leaves uncertain exact sessions unavailable for ordinary control until their central/provider/profile/session binding reconciles.
SSH/cloud/container connectors accept only their pinned typed observation catalogs and bounded JSON results. They do not accept browser-supplied shell strings, expose SSH forwarding, or open Docker/Podman/Kubernetes sockets from the Hub. wmux may send explicit text/keys to an exact wmux-owned surface, but raw terminal input is not provider-native ownership or approval. Consumer web/desktop/IDE sessions remain observed, registered, open-native, or explicit context handoff unless the official provider surface proves an exact quiescent adoption.
The optional iOS path is an authenticated responsive browser at one exact HTTPS private-tailnet origin. Pairing codes are five-minute, single-use bootstrap material. Tailscale Serve is the intended private publication boundary; public Funnel exposure is not part of this design. iOS supervises enrolled execution hosts and never becomes a persistent provider execution agent.
- The broker spawns only pinned or explicitly probed provider executables from validated local paths.
- Each managed provider process is bound to one exact session, one fixed identity/provider lane, and one verified profile home. A lane may have multiple independently bound sessions within its configured admission budget.
- Child environment variables are built from an allowlist; unrelated parent secrets are not copied by default.
- Stdio lines, JSON messages, and stderr are size-bounded before parsing or logging.
- Malformed output fails the adapter honestly and cannot become a shell command or HTML.
- Local stop and interrupt target only the recorded broker-owned process tree. Remote lifecycle commands target only the exact signed Cacheboard-owned session binding. External Terminal/Desktop/IDE/web processes are observed or registered, not killed.
- A newly created launch error is a determinate terminal failure only when the session has no provider binding, the adapter positively proves no provider effect, and the adapter reports no active ownership. The session becomes
failed, its reserved writer claim is released transactionally, and reconciliation is not required. A no-effect marker on an existing writer continuation does not qualify. - Exit, disconnect, timeout, and uncertain provider outcome are distinct events. When provider effect cannot be ruled out, the session becomes
disconnectedand its writer claim is retained. A provider-bound writer requires provider terminal evidence; an unbound disconnected writer may be explicitly archived only with authenticatedreconcile: true, noproviderSessionId, and no adapter ownership. A lost process is never reported as completion or determinate failure by inference. - If a claimed lease's TTL elapses, it remains
activein storage but is surfaced stale and blocks overlap, continuation, release, and handoff. The same holder may renew it; otherwise the writer claim must first be cleared by terminal evidence or the narrow unbound reconciliation path. - Provider events that advance a session to
idle, a waiting state,paused, terminal, ordisconnectedtake precedence over a stale in-flight action return. After an explicit Claude terminal result, a subsequent iterator/transport error is not emitted as disconnect evidence.
The SSE stream is an Orchestrator protocol, not a provider passthrough. Each event includes a broker-generated event ID, schema version, type, timestamp, target references, and redacted payload. Per-session sequence order is monotonic.
Reconnect uses the last accepted broker event ID and bounded replay. If the cursor is expired or inconsistent, the broker sends a snapshot-required event; it does not silently omit authority-changing actions. Event payloads are encoded as data, never interpolated HTML.
- Schema migration starts at version
1; the current broker schema is12. Schema 10 provides the Work Item base, schema 11 additively creates only the Quick Note tables/indexes, and schema 12 additively creates nullable Work Item planning fields and their active planned-day index. Version13or later fails closed until explicitly supported. PRAGMA journal_mode=WAL, foreign keys, and a bounded busy timeout are required and verified on open.- The database and WAL/SHM files inherit owner-only local permissions where Windows supports them.
- Provider credentials and unrestricted transcript bodies are prohibited columns, not merely hidden UI fields. This does not imply encryption for ordinary workflow data: remote managed prompt/answer payloads and curated Tools & Memory text have the explicit bounded-plaintext exceptions described above.
- Idempotency keys, lease changes, audit records, and state transitions commit atomically.
- Schema 2 snapshots each automation run's exact recipe ID/version/definition and bounded redacted context; a database trigger makes those inputs immutable while reconciliation state remains in separate runtime JSON.
- Schema 3 removes the legacy one-active-primary admission invariant and adds exact host/source/ownership/capability session bindings; schema 4 adds bounded provider-conversation inventory and claims; schema 5 adds exact-chat asset and curated-memory tables; schemas 6–9 add bounded cloud receipts/inventory/apply custody and central remote-writer authority; schema 10 adds Work Item workflows, states, projects, items, context-only resource links, append-only events, and private automation-run controller correlations.
- Schema-10 Work Item events are protected by no-update/no-delete triggers. Active items have a partial unique state/rank index, and private projection/correlation uniqueness makes replay idempotent without exposing controller data.
- Schema 11 adds
quick_notesandquick_note_work_item_linkswith exact constraints/indexes. Schema 12 adds nullableestimated_minutesandplanned_dayWork Item columns plus the active planned-day index; it does not transfer scheduler, timer, provider, or execution authority. Production migration authority requires the awaited verified pre-construction backup receipt described in the runbook; new/empty and current-schema-12 databases skip migration backup. - Startup refuses an unknown future schema version and preserves the files for recovery.
- Backup uses a broker-supported consistent snapshot or a clean broker stop; copying only the main database while WAL is active is not a valid backup.
Redaction runs before persistence and before logs leave an adapter boundary. It must cover known credential shapes, authorization headers, cookies, query secrets, environment values, provider-home credential filenames, and configured secret values without printing those values during rule construction.
Redaction is defense in depth, not permission to ingest secrets. Oversized or binary output is summarized with byte count and a non-secret reason. Browser rendering uses text-safe APIs or strict escaping; tool output is never treated as trusted HTML.
| Threat | Required control |
|---|---|
| Malicious page on the workstation calls loopback | HttpOnly session, exact Origin, CSRF, rate limits, no permissive CORS. |
| Identity/profile mix-up | Fixed registry, exact provider verification, no fallback, lane-bound process environment. |
| Browser requests arbitrary shell command | Typed command schemas and fixed executable/argument builders. |
| Traversal or junction escapes project root | Canonical real-path containment, reparse checks, pre-use revalidation. |
| Native Windows Claude is mistaken for OS-sandboxed | Explicit platform capability, no Bash/nested execution, direct editors only, exact-lease path guard, and broker approval. |
| Native Windows writer reads or reaches the network outside its worktree | Read/Glob/Grep canonical containment; fail-closed Glob pattern grammar and optional-path link checks; WebSearch/WebFetch omitted. |
| Direct-write target changes before approval | Exact tool field and 12,000-byte whole-JSON-input check; repeat canonical, symlink/junction, hardlink, file-type, .git, and lease validation at approve-once. |
| Worktree branch/common directory changes after receipt | Query live Git branch and common-directory identity at launch and every writer continuation; fail closed on mismatch. |
| Same-user process races after approval | Document residual cooperative-process race; preserve isolated single-writer worktrees and require post-write diff review. |
| Narrow Claude lease is broadened through shell | Bash requires both a non-Windows mandatory OS sandbox and whole-worktree authority. |
| Two lanes write the same checkout/path | Unique worktrees plus transactional overlapping write leases. |
| Provider emits malformed or hostile content | Bounded parser, schema validation, redaction, safe encoding. |
| Transcript deltas hide a tool or cross session/turn authority | Coalesce only contiguous display-soft events with the same exact session, opaque turn reference, author, channel, and text content type; every hard/unknown/malformed event remains a visible boundary. |
| Stale exact-session response publishes after navigation or reset | Per-resource controller, route and selection generations, immutable reset epoch, request abort, and exact-session recheck before every publish. |
| Retry duplicates an approval or Git action | Idempotency key and stored response in one transaction. |
| Overlapping message/action starts another provider pump | Exact per-action state-transition table; pending question/approval states block messages. |
| Lane-only action controls the wrong chat | Require exact Cacheboard session ID and exact host/lane/provider-session binding; reject ambiguity. |
| Stale action result overwrites provider terminal state | Provider-authoritative event precedence and no post-terminal disconnect synthesis. |
| External session is killed or adopted concurrently | Observed default, explicit handoff proof, broker ownership lock. |
| Stale/replayed remote controller leases work | Controller epoch, fresh signed heartbeat, replay protection, host revocation, and durable exact reconciliation. |
| Remote read-only session gains write/approval authority | Exact managed mode, Claude denylist/dontAsk, Codex read-only/never, and no remote writer-claim path. |
| Remote prompt is mistaken for encrypted secret storage | Explicit bounded-plaintext disclosure; prohibit secrets and provide no automatic-retention claim. |
| Paired phone origin becomes public control | Exact HTTPS private-tailnet origin, single-use pairing, authenticated browser controls, Serve only, no Funnel. |
| Agent message weakens permissions | Message schema has no authority fields; recipient revalidates its own policy. |
| Task/project/link is mistaken for provider or filesystem authority | Fixed context_only links, exact eight-lane routing, private controller correlations, and complete revalidation through existing scheduler/Room/worktree/lease gates. |
| Work Item text captures a credential or transcript | UTF-8 bounds and recognizable-sensitive-text rejection plus explicit plaintext warning; prohibit secrets, raw receipts, prompts, provider homes, and unrestricted transcripts even when the recognizer does not match. |
| Private execution correlation leaks to a public surface | Separate private tables/internal serializers; explicit public DTO/SSE/audit/bootstrap/link allowlists and sentinel scans. |
| Dispatch acceptance is mistaken for completed provider work | dispatch.succeeded remains Doing; only an exact correlated provider-turn terminal or canonical completed automation run can project Review. |
| Provider proposal silently edits a task | Extract before public publication, persist only bounded proposed activity, and require a separate owner-authenticated CAS apply. |
| Browser permanently deletes a task | DELETE means reversible Trash, restore is explicit, and no P0 purge method/route/control exists. |
| Recipe auto-approves destructive work | Hard-denied action classes independent of recipe input. |
| Database copied inconsistently | Supported online snapshot or clean-stop backup including WAL state. |
Fixture tests must cover authentication, CSRF, strict Origin, rate limits, duplicate commands, identity mismatch, redaction, oversized/malformed events, schema migrations through version 11 and future-12 refusal, Work Item and Quick Note UTF-8/sensitive-input bounds, explicit DTO allowlists, Quick Note POST-search/cursor/text-free evidence, CAS/no-effect conflict serialization, strict cursor/SSE replay, bootstrap non-growth, reversible lifecycle/no purge, typed-link authority, private controller/proposal non-disclosure, held dispatch/run crash recovery without replacement effects, exact provider-terminal projection, owner-only Done, exact automation schemas/receipts, multi-session exact targeting and ambiguity refusal, canonical root enforcement, traversal, symlink/junction and hardlink escape, write-lease collision, approval scope, message authority separation, restart recovery, native-Windows worktree-bounded reads/network denial/direct-tool validation, strict Glob pattern and optional-path enforcement, 12,000-byte whole-input and exact-field enforcement, 16,000-character durable redacted Attention correlation, approval-time target revalidation, live Git branch/common-directory checks at launch and continuation, writer continuation/fork/scope rules, pinned stale claims, narrow unbound reconciliation, non-Windows mandatory-sandbox failure, whole-worktree-only shell exposure, determinate initial-launch release, uncertain-outcome writer retention, operation-catalog completeness, host enrollment/signature/replay/controller-epoch handling, exact remote profile binding, read-only remote mode enforcement, durable result retry/reconciliation, connector schemas, mobile origin/pairing, and exact-chat Tools & Memory authority separation.
Required Work Items/Quick Notes evidence includes the focused security/HTTP/projection/automation/Quick Notes suites, schema-10-to-11 maintenance round trip and preflight failure paths, full unfiltered Orchestrator suite, repository gate, served provider-free browser checks, static private/public data-flow review, and a zero provider-call receipt. Record exact dated results in the verification ledger.
Live verification must additionally prove that one Claude and one Codex lane use the intended profile, multiple chats on one lane remain exactly addressed, unsupported controls stay hidden, browser reconnect does not lose pending attention, and no credential value appears in the browser, SQLite, logs, audit export, or screenshots. A Windows-to-Ubuntu/macOS host-agent flow, private-tailnet iOS pairing, SSH/container observation, or wmux action is not live-verified until the exact environment's receipt is recorded; deterministic fixtures do not substitute for it.