Skip to content

Optimize control-plane contract: per-action isolation, authorization closure, storage compaction - #14

Merged
oratis merged 5 commits into
mainfrom
opt/control-plane-contract
Aug 1, 2026
Merged

Optimize control-plane contract: per-action isolation, authorization closure, storage compaction#14
oratis merged 5 commits into
mainfrom
opt/control-plane-contract

Conversation

@oratis

@oratis oratis commented Aug 1, 2026

Copy link
Copy Markdown
Owner

Implements PR1 of the optimization pass, per the architecture, code-quality, and security reviews. All changes are confined to the task control plane (andromeda-core/-policy/-runtime/-taskd/-cli task paths) and its doc.

What & why

Breaking wire changes (v0, previously unconsumed)

  • EvaluationRequest moved to the runtime crate and changed shape: isolation: IsolationLevel -> isolation: Option<IsolationLevel> (whole-plan override) plus overrides: BTreeMap<ActionId, IsolationLevel>, external_side_effect_confirmed, and subject.
  • TaskEventKind::Evaluated.isolation is now effective_isolation: BTreeMap<ActionId, IsolationLevel>; a new Granted event variant was added.
  • New POST /v1/tasks/{id}/capabilities route.

Tests

cargo fmt --all --check, cargo clippy --workspace --all-targets --locked -- -D warnings, and cargo test --workspace --locked all pass. Test count 109 -> 119, including new coverage for the mixed-isolation plan, grant-then-Ready, gated transition rejections, unknown-field rejection, macOS deny-root, and compaction reclamation.

Do not merge; scoped to the control-plane contract only.

oratis and others added 5 commits August 1, 2026 17:01
Add #[serde(deny_unknown_fields)] to the control-plane types deserialized
from untrusted input (ActionPlan, ActionSpec, Intent, Capability,
CapabilityResource, PolicySet) so a mistyped field such as a camelCase
`expiresAt` is rejected rather than silently dropped into a
permission-widening default (a never-expiring grant).

Fold ASCII case on macOS in the denied-root prefix check so
`/system/Library` cannot dodge the `/System` deny root on case-insensitive
APFS, mirroring the existing Windows branch. Correct the single_use doc
comment to state it is reserved and not yet enforced (no executor exists).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Each write now advances a per-task `{task_id}.latest` pointer and compacts
away every superseded revision file under the exclusive lock, so steady
state keeps one revision file per task instead of growing without bound and
reads no longer scan the whole directory to find the latest revision.

Lock-free get/list resolve the latest revision from the pointer (falling
back to a directory scan for pre-pointer stores or crash windows) and retry
on a NotFound caused by a concurrent compaction, closing the TOCTOU window.
Crash-safety ordering is preserved: the revision file is durable before the
pointer moves, and compaction runs only after the pointer names the
survivor.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Resolve isolation per action in TaskService::evaluate (whole-plan override,
then a per-action overrides map, then the action's risk minimum) so a mixed
L2 microVM + L3 brokered plan can be fully allowed. A single task-level
isolation could never allow both, because IsolationLevel::satisfies is
non-linear (neither MicroVm nor Brokered satisfies the other), which also
contradicted the per-action model used by plan_fully_granted at creation.

Add grant_capabilities so an AwaitingApproval task can be topped up after
creation, recording a Granted event and whether the plan is now fully
granted. Policy-gate transitions: AwaitingApproval -> Ready now requires a
fully granted plan, and Ready -> Running re-runs policy per action at its
minimum isolation and rejects the transition if any action is Deny or Ask.

Unify plan validation by delegating structural checks (duplicate ids,
dangling deps, cycles) to core ActionPlan::validate, dropping runtime's
duplicate DFS and parallel error set. Add deny_unknown_fields to the
request DTOs and wire the optional evaluation subject into the policy
context.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Import EvaluationRequest from the runtime crate (now a per-action request),
add the POST /v1/tasks/{id}/capabilities grant route and handler, and map
the new transition-guard error to 422. Default the CLI `evaluate` command to
per-action minimum isolation, keeping --isolation as an optional whole-plan
override.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Describe the new capabilities/grant endpoint, per-action evaluate isolation,
the policy-gated AwaitingApproval->Ready and Ready->Running transitions, and
the storage compaction policy (latest pointer, superseded-revision deletion,
crash-safety ordering, and race-tolerant reads).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@oratis
oratis merged commit 019e6ed into main Aug 1, 2026
5 checks passed
@oratis
oratis deleted the opt/control-plane-contract branch August 1, 2026 10:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant