Skip to content

fix(kernel): fail closed at bootstrap authority boundaries#1257

Merged
joshuajbouw merged 6 commits into
mainfrom
agent/fail-closed-bootstrap-authority
Jul 15, 2026
Merged

fix(kernel): fail closed at bootstrap authority boundaries#1257
joshuajbouw merged 6 commits into
mainfrom
agent/fail-closed-bootstrap-authority

Conversation

@joshuajbouw

@joshuajbouw joshuajbouw commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Linked Issue

Closes #1256

Summary

Closes the remaining first-release bootstrap authority fallbacks without activating the deferred RFC #36 persistence model or adding any product-specific privilege path.

Changes

  • reject kernel and admin management requests whose IPC envelope has no valid principal instead of inheriting the default administrator
  • audit missing and malformed admin callers exactly once as reserved no-capability anonymous before returning the uniform denial
  • preserve the local CLI active-principal behavior before requests cross the kernel boundary
  • attribute principal-less connection lifecycle signals to anonymous and ignore malformed identities
  • abort kernel construction when default administrator profile/key seeding or legacy-profile migration fails
  • reject AgentModify results that remove default from the built-in admin group while preserving idempotent remove-plus-add
  • keep caller resolution in a focused private module so the management router remains below the source-file cap
  • retain the merged device-attenuation, pair-device input-validation, issuance-preflight, cache-refresh, and terminal-audit behavior
  • add live-router, lifecycle, bootstrap, persistence, administrative, and pair-authority regression coverage

Verification

Checklist

  • Linked to an issue
  • CHANGELOG.md updated under [Unreleased]

No release is created or published by this change.

Copilot AI review requested due to automatic review settings July 15, 2026 04:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR tightens Astrid’s security posture at kernel bootstrap and management authority boundaries by eliminating fail-open fallbacks to the default bootstrap administrator and by pinning/propagating authorization inputs (principal, groups, profile, and device scope) at a single decision point per request.

Changes:

  • Reject kernel/admin management IPC requests that lack a valid authenticated principal (no fallback to default).
  • Abort kernel construction when bootstrap profile/key seeding or legacy profile migration fails (fail-closed boot).
  • Extend/pin device-scope attenuation across inventory surfaces and pairing issuance, and harden profile-cache invalidation against stale republish races.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated no comments.

Show a summary per file
File Description
crates/astrid-kernel/src/lib.rs Fail-closed bootstrap: propagate default profile/key/migration failures; add injected-resource boot regressions.
crates/astrid-kernel/src/kernel_router/mod.rs Reject missing/invalid principals at the kernel router boundary; introduce pinned AuthorizedRequest; centralize device-scope resolution.
crates/astrid-kernel/src/kernel_router/device_scope.rs New shared helper to resolve device-scope attenuation with outwardly uniform denials.
crates/astrid-kernel/src/kernel_router/tests.rs Update caller resolution tests; add deterministic denial regression; expand device-scope snapshot/opacity coverage.
crates/astrid-kernel/src/kernel_router/connection_tracker_tests.rs Ensure principal-less lifecycle events map to anonymous and malformed identities are ignored.
crates/astrid-kernel/src/kernel_router/admin/mod.rs Reject missing/invalid principals at admin router boundary; route dispatch through pinned authorization snapshot.
crates/astrid-kernel/src/kernel_router/admin/handlers.rs Thread pinned authorization through read paths; enforce default retains built-in admin group after AgentModify.
crates/astrid-kernel/src/kernel_router/admin/group.rs Apply device-scope attenuation and/or pinned authorization snapshot to group listing visibility.
crates/astrid-kernel/src/kernel_router/admin/state_tests*.rs Add/extend regressions ensuring device attenuation and snapshot pinning across admin inventory.
crates/astrid-kernel/src/kernel_router/admin/pair_device_handlers.rs Harden pairing issuance against missing/invalid/revoked device IDs; require pair-admin for universal * scoped mints; accept pinned snapshot dispatch.
crates/astrid-kernel/src/kernel_router/admin/pair_device_tests.rs Expand end-to-end pairing acceptance coverage for missing/revoked devices and universal-scope gating.
crates/astrid-kernel/src/kernel_router/admin/enforcement_tests.rs Add deterministic denial regression for missing/invalid admin principals.
crates/astrid-capsule/src/profile_cache.rs Add per-principal invalidation generations to prevent stale load publication under concurrent invalidation.
CHANGELOG.md Document fail-closed bootstrap/authority boundary changes and device-attenuation/snapshot hardening under Security.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Comment thread crates/astrid-kernel/src/lib.rs

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Comment thread crates/astrid-kernel/src/lib.rs Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

@joshuajbouw

Copy link
Copy Markdown
Contributor Author

@copilot review exact head 94b1690

Copilot AI commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@copilot review exact head 94b1690

Reviewed 94b1690527feec3570fe29cad62dcb35ae56b6e7. No issues found. Notes by area:

caller.rs / device_scope.rs (new)
Both resolution helpers are correct. resolve_caller is strictly fail-closed; resolve_connection_principal maps a missing principal to anonymous and rejects malformed ones. resolve_device_scope validates the typed DeviceKeyId before lookup and uses a uniform DeviceScopeDenied outward reason so authorization responses cannot reveal whether a key exists.

lib.rs bootstrap
seed_default_principal_admin_profile now propagates via ? through an IdentityError::Storage wrapper; migrate_legacy_profile_path delegates to remove_legacy_profile_file which treats NotFound as success (resolving the TOCTOU thread) while propagating all other IO errors. The three new tests cover: migration obstacle, key-seeding obstacle, and NotFound idempotency.

kernel_router/mod.rs
Principal rejection fires before rate-limiting, which is the correct ordering. AuthorizedRequest pins profile, groups, and device scope at the single policy decision point, preventing a concurrent cache invalidation from changing the effective check after authorization. The CapsuleVisibility::new drop of check.has("*") is safe — check.has("capsule:list") already returns true for a * grant because capability_matches("*", "capsule:list") short-circuits to true.

admin/mod.rs + admin/handlers.rs
Parallel fail-closed boundary on the admin socket. The AgentModify protection for default/admin membership evaluates the post-apply_set_delta profile, so idempotent remove+add still succeeds. handle_redeem_admin_request correctly isolates the redeem audit after dispatch.

admin/pair_device_handlers.rs
preflight_pair_device_issue is called before acquiring the write lock, removing the validation latency from the critical section. resolve_pair_issuer_authority uses the pinned AuthorizedRequest when available rather than re-resolving the profile.

profile_cache.rs
The generation counter prevents a concurrent pre-invalidation load from re-populating a slot that was just bumped, replacing the previous single-winner race with a correct retry loop. The idempotent-endpoint path now refreshes the cache slot in place rather than dropping it, avoiding a wasted re-read.

All completed CI gates are green; the remaining queued gates (Test, MSRV, Security Audit, etc.) are the execution gate per the PR description.

@joshuajbouw
joshuajbouw force-pushed the agent/fail-closed-bootstrap-authority branch from 94b1690 to 8a250f7 Compare July 15, 2026 12:25
@joshuajbouw
joshuajbouw requested a review from Copilot July 15, 2026 12:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.

Comment thread crates/astrid-kernel/src/kernel_router/admin/mod.rs
@joshuajbouw
joshuajbouw requested a review from Copilot July 15, 2026 12:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated no new comments.

@joshuajbouw
joshuajbouw merged commit a5e8762 into main Jul 15, 2026
34 checks passed
@joshuajbouw
joshuajbouw deleted the agent/fail-closed-bootstrap-authority branch July 15, 2026 13:14
joshuajbouw added a commit that referenced this pull request Jul 15, 2026
## Linked Issue

Closes #1239

Refs #1237 and astrid-runtime/rfcs#36.

## Summary

Carries the authenticated device into capsule dispatch so execution and
inventory use the same live authority already enforced at the kernel
boundary. The change is generic to Astrid and introduces no
product-specific role or trust path.

## Changes

- resolve one principal/profile/group/device snapshot per stamped event
- reject disabled, malformed, unknown, and revoked identities before
matching or grant signalling
- use device-effective `capsule:list` only for global describe
visibility
- activate exact device-effective `capsule:access:any` for unrestricted
execution and candidate expansion
- preserve exact per-principal capsule grants, no-device/`Full`
behavior, and principal-less lifecycle dispatch
- emit one `GrantRequired` only for a valid in-view denied match
- preserve legacy dispatch when no access resolver is installed
- preserve merged authority-cache refresh, pairing preflight, audit
classification, and caller-boundary audit behavior
- require base `self:auth:pair` authority for pair issuance while
retaining the additional `self:auth:pair:admin` gate and elevated audit
classification for Full, preset-Full, and explicit-universal scopes
- add a dedicated device-scope dispatch regression suite

## Verification

- restacked onto `main` after #1196, #1238, and #1257 merged
- signed head: `57ec31340db1a1749d5f137a25f4352bb6cb401f`
- `cargo fmt --all -- --check`
- `git diff --check origin/main...HEAD`
- `cargo test --locked -p astrid-capsule` — 563 passed
- `cargo test --locked -p astrid-kernel
admin_cap_without_base_pair_capability_cannot_issue_full_token --
--nocapture`
- `cargo clippy --locked -p astrid-capsule -p astrid-kernel
--all-features --tests -- -D warnings`
- replacement GitHub CI is the complete integration and execution gate

## Checklist

- [x] Linked to an issue
- [x] CHANGELOG.md updated under `[Unreleased]`

No release is created or published by this change.
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.

fix(kernel): fail closed at bootstrap authority boundaries

3 participants