Optimize control-plane contract: per-action isolation, authorization closure, storage compaction - #14
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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/-clitask paths) and its doc.What & why
TaskService::evaluateresolved a single task-levelIsolationLevelfor the whole plan, butIsolationLevel::satisfiesis non-linear, so a mixed L2 microVM + L3 brokered plan could never be all-Allow — and it contradicted create-timeplan_fully_granted, which is per-action.evaluatenow resolves isolation per action: whole-planisolationoverride, then a per-actionoverridesmap, then the action's risk minimum. A new test proves the mixed plan is now fully Allow.grant_capabilities+POST /v1/tasks/{id}/capabilitiesso anAwaitingApprovaltask can be topped up, and policy-gates transitions:AwaitingApproval -> Readyrequires a fully granted plan;Ready -> Runningre-runs policy per action and rejects anyDeny/Ask.deny_unknown_fields(code-quality docs: add Andromeda OS research and product plan #1). Added to untrusted deserialization targets (ActionPlan,ActionSpec,Intent,Capability,CapabilityResource,PolicySet, and the taskd request bodies) so a mistyped field likeexpiresAtis rejected instead of silently widening permissions.validate_plannow delegates structural checks (duplicate ids, dangling deps, cycles) to coreActionPlan::validate(Kahn), removing the duplicate DFS and parallel error set; it keeps only schema/limit/risk-floor/subject checks.latestpointer + revision compaction under the exclusive lock (one file per task, no full-dir scan), with NotFound-retry on lock-free reads to tolerate the compaction race. Crash-safety ordering preserved.path_starts_withnow folds ASCII case on macOS too, so/system/Librarycannot dodge/Systemon APFS.subjectinto the evaluate data path (issued_tois checked when supplied); fixed thesingle_usedoc to say "reserved; not yet enforced".Breaking wire changes (v0, previously unconsumed)
EvaluationRequestmoved to the runtime crate and changed shape:isolation: IsolationLevel->isolation: Option<IsolationLevel>(whole-plan override) plusoverrides: BTreeMap<ActionId, IsolationLevel>,external_side_effect_confirmed, andsubject.TaskEventKind::Evaluated.isolationis noweffective_isolation: BTreeMap<ActionId, IsolationLevel>; a newGrantedevent variant was added.POST /v1/tasks/{id}/capabilitiesroute.Tests
cargo fmt --all --check,cargo clippy --workspace --all-targets --locked -- -D warnings, andcargo test --workspace --lockedall 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.