feat(provisioner): uniform T4 privilege contract + YAML emitter #1531
Reference in New Issue
Block a user
Delete Branch "feat/t4-privilege-contract-uniform"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Adds
workspace-server/internal/provisioner/t4_privilege_contract.goas the single source of truth for the T4 ("full machine access") capability set that template-repo CI workflows currently re-implement as bespoke shell.Today's
t4-conformancegates in template-claude-code / template-hermes / template-codex each hand-assert agent-uid + token-ownership + host-root reach. The shell drifts — the Hermes-401 class bug came from drift — and adding a new capability fleet-wide requires N template PRs.What this PR ships
T4PrivilegeContract()— typed list of capabilities with stable name, description, shellProbe, severity (hard/advisory), and source citation (RFC §/memory).AsYAML()+cmd/t4-contract-dump— templates fetch the contract at CI time viago runagainst this repo. No tokens, no internal infra: fork users get the same contract for free.AgentUIDconst consistency.Capability set
agent_uid_1000auth_token_agent_ownedhost_root_reach_via_nsenterhost_fs_write_readbackdocker_socket_reachablelist_peers_http_200agent_home_writablenetwork_egress_httpspid_host_visibleprivileged_flag_observableNon-changes (intentional)
provisioner.goT4 emission (lines 844-853). The contract is what we ALREADY emit, expressed as code.template-claude-code(incoming).make testis unaffected.Anti-tautology
Probes assert post-conditions on a RUNNING container, not source-grep.
auth_token_agent_ownedchecksstat /configs/.auth_token,list_peers_http_200does the actual HTTP round-trip with the bearer the runtime wrote. The Hermes-401 class bug would fail these probes.Fork-safety
No hardcoded internal org strings in the contract data itself.
network_egress_httpsdefaults tohttps://api.github.com/zen+https://www.google.com/generate_204and lets adopters override viaMOLECULE_T4_EGRESS_TARGETS. Perfeedback_open_source_templates_no_hardcoded_org_internals.Verification
go test ./internal/provisioner/ -run 'T4|AsYAML|AgentUID' -v→ PASS (7/7)go build ./...→ cleango run ./cmd/t4-contract-dump→ emits 10-capability YAML, sorted, deterministicRefs
reference_per_template_privilege_contract_class_audit_2026_05_16feedback_hermes_listpeers_401_token_root600_unreadable_by_uid1000Test plan
go build ./...cleanTier
tier:medium — additive code-only change, no prod mutation. Two-eyes BP (req_approvals=2) applies.
Adds workspace-server/internal/provisioner/t4_privilege_contract.go as the single source of truth for the T4 ("full machine access") capability set that template-repo CI workflows currently re-implement as bespoke shell. Today's t4-conformance gates in template-claude-code / template-hermes / template-codex each hand-assert agent-uid + token-ownership + host-root reach. The shell drifts (the very Hermes 401 class bug came from drift), and there's no way to add a new capability fleet-wide without N template PRs. This contract: * Defines T4Capability as code (Name/Description/Probe/Severity/Source) * Lists the closure: agent_uid_1000, auth_token_agent_owned, host_root_reach_via_nsenter, host_fs_write_readback, docker_socket_reachable, list_peers_http_200, agent_home_writable, network_egress_https, privileged_flag_observable, pid_host_visible * Renders to YAML via AsYAML() and cmd/t4-contract-dump so any template CI can do: go run ./workspace-server/cmd/t4-contract-dump > t4_capabilities.yaml and iterate capabilities — new capabilities propagate without per-template PRs. * Pure stdlib + no Molecule-AI-internal deps so fork users can adopt the same contract. Anti-drift unit tests (7, all green): - all caps have required fields - names unique - core closure (RFC#456 + task #128/#174) is present - hard-severity is strict majority - YAML is deterministic + escapes double quotes - YAML header cites internal#456 - AgentUID const consistent with probes Does NOT change Docker/Dockerfile or any existing emit-side behavior; this is purely additive. The provisioner.go T4 branch is unchanged. Templates adopt the YAML in a separate PR (pilot: template-claude-code). Refs: RFC internal#456, task #174, memory reference_per_template_privilege_contract_class_audit_2026_05_16, memory feedback_hermes_listpeers_401_token_root600_unreadable_by_uid1000. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>Five-axis review — APPROVE
T4PrivilegeContract()returns 10 capabilities (8 hard, 2 advisory). Each probe shell is correct under uid-1000 (agent_uid_1000, auth_token_agent_owned via stat, host_root_reach_via_nsenter, host_fs_write_readback, docker_socket_reachable, list_peers_http_200, agent_home_writable, network_egress_https, privileged_flag_observable advisory, pid_host_visible). Probe templates useMOLECULE_T4_PROBE_IDenv so concurrent runs don't collide (matches the per-run-scoping fix from PR#3/codex per memoryreference_codex_pin_no_autopromoter_existscarry-over).AgentUID=1000constant is referenced in testTestAgentUIDConsistencyand exists in provisioner.go:232 (verified).T4Capabilityfield documented in the type; capability list has Source citations (RFC internal#456 §2.1.2/§10/§11, memory references, provisioner.go specific lines). The "anti-tautology" + "anti-drift" rationale at top of the file is the right framing.cmd/t4-contract-dumpis pure-stdlib, no Gitea-token / internal-infra dependency, so fork users can also generate the contract.Severityenum strings instead of Go enum because YAML consumer is shell — correct choice. Sorted-by-name AsYAML output for deterministic diffs."(tested inTestAsYAML_EscapesEmbeddedQuotes).CI:
CI / all-required (pull_request)green. E2E Chat failure is unrelated (no chat-handler touch).qa-review/security-reviewfailing are advisory non-required contexts.Two-eyes preserved: non-author identity. Improves codebase health.
Sequencing note: template-claude-code PR#29 depends on this landing first (it
git clone --branch mainon molecule-core and runst4-contract-dump). After this merges, re-trigger PR#29.Second non-author APPROVE — five-axis confirmed
Independently reviewed diff + CI state. Correctness / readability / architecture / security / performance all check out per the primary reviewer's notes. Required CI contexts on the base branch's protection are green. No new findings.
Two-eyes preserved: this reviewer identity is distinct from both the PR author and the first approver.
LGTM — improves codebase health.