Skip to content

Sync

Sync is the one-way signed channel from the TapPass control plane to every governed agent.

It delivers Compiled Policy updates within seconds. It is unidirectional by design — there is no upward channel from agent to control plane that could be used for escalation.

Per governed-agents.md §12. Sync is what makes "live policy" usable at scale: the operator changes a Rego rule, every governed agent's enforcement updates within seconds, and any drift gets detected and re-pushed.

DirectionControl plane → data plane (one-way)
ModesPush (SSE) · Pull (HTTP fetch) · Reconcile (background loop)
CarriesSigned, monotonic Compiled Policy payloads
Triggered byOperator policy change · agent boot · agent reconnect · periodic heartbeat · drift detection
Latency< 5 seconds for a typical enterprise footprint (push path)
Failure modeFail-closed — capability tokens expire within 5 min if Sync stops working

Per Strategy Memo v3 §07.3:

ModeDirectionUse case
PushControl plane → data plane (SSE bus)Compiled Policy version bumps; broadcast to all connected agents; expect ACK within seconds. The primary path for live updates.
PullData plane → control plane (HTTP fetch)Agent boots and fetches its assigned Compiled Policy. Agent reconnects after offline and catches up. Periodic heartbeat verifies version match. Resilience and bootstrap.
ReconcileControl plane internal (background loop)Compares desired Compiled Policy version per agent against last-ACK'd version. Re-pushes where ACKs are missing. Marks drifted agents. Surfaces stale or disconnected agents.

All three run continuously. Push is the fast path; Pull is the resilient path; Reconcile is the integrity check.

[Operator changes Policy at any cascade level]
[TapPass cascade-merges + re-compiles every stale Compiled Policy]
├──▶ updates Compiled Policy rows server-side
├──▶ revokes old gateway_token / mcp_session_token if scope narrowed
└──▶ pushes signed payload over sync_url
[tappass-host validates signature + monotonic policy_version,
atomic-renames `keyring.json` file, applies provider changes]
[Agent observes via inotify; tappass-agent rebinds clients]
[Host ACKs new policy_version → control plane]
[Reconciler clears the stale flag]

Signed, monotonic, replay-resistant payload

Section titled “Signed, monotonic, replay-resistant payload”
{
"sandbox_id": "sbx_a1b2c3",
"policy_version": 17,
"issued_at": "2026-05-08T10:00:00Z",
"expires_at": "2026-05-08T10:05:00Z",
"compiled_policy": { network: {}, filesystem: {}, tools: {},
interpreter: {}, budget: {}, compliance_tags: [] },
"signature": "ed25519:<TapPass key>:<sig>"
}

The host validates:

  • Signature — Ed25519 against the publicly-pinned TapPass signing key
  • Monotonic versionpolicy_version must be strictly greater than the currently-applied version
  • Sandbox matchsandbox_id must match this host's enrollment
  • Freshnessexpires_at not in the past

If any check fails, the payload is rejected and the host stays on its current Compiled Policy.

Every Provider has its own update model. The host runtime supervisor encapsulates these:

ProviderUpdate model
OpenShell networkHot-reload via L7 proxy reconfiguration (no restart)
OpenShell FS / execRestart container with new profile; supervisor handles state
nonoRestart-only — supervisor uses --supervised mode (parent stays unsandboxed; child restarts under new flags)
Claude Code settings.jsonFile rewrite; harness reloads on next prompt
Monty manifestRe-imported on next interpreter boot
K8s NetworkPolicykube-apiserver picks up live; no pod restart needed
LLM Gateway capability tokensToken rotation in-place; old tokens revoked at expiry
MCP Broker capability tokensSame as gateway

The user-visible promise — "policy updates apply within seconds" — holds across all of them. The supervisor library makes the per-target nuance invisible.

TokenTTLRenewed by
gateway_token5 minsync push
mcp_session_token5 minsync push
Host mTLS cert1 hourtappass-host re-auth
Bootstrap URL15 min, single-use(burned on consumption)

If sync stops working, every capability token expires within minutes and the agent stops being able to act. Fail closed.

The pre-deployment evaluation establishes a baseline (what the agent should do under this Policy); the runtime emits behavioral metrics; the dashboard learns the baseline and alerts on drift.

Drift signalWhat it catches
Tool-call distribution shiftAgent calls delete_* 10× more than baseline
Argument-shape driftArgs that don't match pre-deployment patterns
Session-length anomaliesSessions running far longer than typical
Detection-rate spikesdetect_pii or detect_secrets firing more — possibly a prompt-injection campaign
Unenrolled-tool discovery rateSurge in discovered rows = agent reaching for tools it hasn't before
Cross-sandbox correlationSame drift signal across multiple sandboxes = upstream change (LLM provider behavior shift, new prompt template)

Drift signals raise dashboard alerts with: which baseline metric, current vs. expected, audit replay link, recommended action (re-evaluate? tighten policy? approve as new normal?).

This is a hard architectural property, not a soft preference. Without it, the same channel that delivers Policy updates would be a vector for the agent to influence its own Compiled Policy.

Enforced by:

  • Package design: tappass-agent exposes no client classes for admin endpoints.
  • Transport: kernel-ring egress allowlist blocks anything not in the Compiled Policy's URL set.
  • Authentication: the agent's tokens have no admin scope.

A first-class attacker who owns the agent process cannot: modify the Compiled Policy, forge a sync payload, reach admin endpoints, replay older Compiled Policy versions, read other sandboxes.

EngineWhat it doesStatus
Push channelSSE broadcast on Compiled Policy changeconcept (Q3 2026 — critical-path M)
Pull endpointHTTP fetch; heartbeatconcept (Q3 2026, parallel)
ReconcilerBackground loop closing on the agent registryconcept (Q3 2026)
Token rotationIssues new capability tokens on Policy changeconcept (extends shipped gateway)
Drift monitorBehavioral baseline + alertsconcept (Q4 2026)
PersonaSurfaceWhat you see
OperatorDashboard sandbox listPer-sandbox: desired vs. applied Compiled Policy version; last ACK time; drift state
Operatortappass sync statusSame data via CLI
OperatorDrift alertsDashboard notification + optional email/Slack
Host ownertappass-host statusLocal sandbox status: applied version, last sync, mTLS cert health
Agent(none — read-only)Inotify on keyring.json triggers client rebind
  • deliversCompiled Policy (the artifact pushed/pulled)
  • between → control plane (server) ↔ data plane (host) — never the other way
  • authenticated byIdentity (host mTLS; agent capability tokens)
  • detects drift againstProbe baselines + audit metrics
  • applied by → host runtime supervisor invoking each Provider
TopicFile
Visiongoverned-agents.md §12 — sync flow + drift
Privsep modelgoverned-agents.md §13
Component (push)live-policy-push-channel
Component (drift)behavior-drift-monitor
  • Sync ≠ HTTP polling. Sync is signed and monotonic. A polling agent that fetches "the latest config" without signature checks would be a forgery vector. Every payload TapPass delivers is Ed25519-signed against a publicly-pinned key.
  • Sync ≠ sync (the bash command). This is the architectural channel between control plane and data plane, not a filesystem operation.
  • Push and pull are not mutually exclusive. They cover different conditions. Push is fast; pull is resilient. Both are first-class.
  • Sync is one-way. There is no "agent requests more scope" path. That's the architectural property that makes live policy usable.