Skip to content

feat(broker): persist managed ACP authority generations - #33

Open
malkovitc wants to merge 3 commits into
mainfrom
feat/mobility3b1-durable-authority
Open

malkovitc wants to merge 3 commits into
mainfrom
feat/mobility3b1-durable-authority

Conversation

@malkovitc

@malkovitc malkovitc commented Sep 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • add a loopback-only buzz-broker-host for durable managed-ACP authority.status
  • issue CSPRNG bearer credentials through owner-only files while persisting only SHA-256 digests
  • enforce canonical identity integrity, one active generation per normalized task scope, and permanent scope+generation uniqueness across restart
  • persist exact-byte request receipts for idempotent replay and reject conflicting request IDs
  • keep relay effects, atomic effect commit, drain, and runtime cutover explicitly out of this slice

Related issue

None found. This is the first durable host slice following the managed-ACP client/runtime authority contract.

Testing

  • cargo test -p buzz-broker-host — 11 passed
  • cargo clippy -p buzz-broker-host --all-targets -- -D warnings
  • cargo test -p buzz-sdk broker:: — 44 passed
  • cargo test -p buzz-broker-client — 13 passed
  • cargo clippy --workspace --all-targets -- -D warnings
  • independent final full-diff security/correctness review — APPROVE after all fail-closed findings were fixed
  • just ci completed Rust/workspace, Desktop/Web, Mobile analysis, and 1,831 Mobile tests; two unrelated Mobile timing tests failed in the parallel suite, then both passed when rerun individually by exact test name

Review corrections

  • fencing atomically invalidates pre-fence status receipts, preventing stale active replay
  • per-credential read receipts are capped at 64; later effect execution requires a separate durable effect ledger
  • Unix state directory/database ownership is checked against the effective UID
  • the host test suite is explicitly included in the repository unit gate; Windows dead-code portability finding is fixed

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-08T18:49:20.015523Z 37d6474 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0326537a92

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

)
.await?
{
ReceiptMatch::Replay(response) => return Ok((*response).replayed()),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid replaying stale authority status after fencing

When an authority.status response is committed while active but lost in transit, the broker contract directs callers to retry the identical request bytes. If the operator fences the generation before that retry, this branch still returns the stored Active result, allowing the retrying caller to admit a new spawn or prompt after the terminal fence. Treat status as a current lifecycle read rather than replaying its old receipt, or invalidate such receipts during fencing.

AGENTS.md reference: AGENTS.md:L11-L18

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in f80b51c. Fencing and prior status-receipt invalidation now occur in the same BEGIN IMMEDIATE transaction. The regression verifies that an identical lost pre-fence request returns a fresh fenced verdict before any later replay.

Comment on lines +303 to +307
sqlx::query(
"INSERT INTO broker_receipts
(credential_hash, request_id, request_digest, response_json)
VALUES (?, ?, ?, ?)",
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bound receipts for read-only and unsupported requests

Every fresh authenticated request, including authority.status and unsupported actions, permanently inserts a receipt with no retention or quota. Status polling with unique request IDs therefore grows SQLite continuously, and even a fenced bearer remains authenticated and can rapidly fill the host disk with new IDs. Skip durable receipts for operations without side effects, or add a bounded retention/rate-limit strategy that preserves deduplication only where it is needed.

AGENTS.md reference: AGENTS.md:L20-L24

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in f80b51c. Read-only/unsupported receipts are capped at the latest 64 per credential, with a regression proving the bound and recent replay. The README explicitly reserves a separate durable effect ledger for the later effect-host slice.

Comment thread crates/buzz-broker-host/src/store.rs Outdated
#[cfg(unix)]
fn require_private_directory(metadata: &std::fs::Metadata) -> Result<(), StoreError> {
use std::os::unix::fs::PermissionsExt as _;
if metadata.permissions().mode() & 0o077 != 0 {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Verify the Unix owner instead of only permission bits

When a privileged broker is pointed at a 0700 directory owned by another UID, this check accepts it because it examines only mode bits. That directory owner can precreate or replace the SQLite database with a valid attacker-controlled authority and known credential digest, defeating the claimed host-owned boundary. Check the directory and existing database UID against the broker's effective UID in addition to their modes.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in f80b51c. Unix state directories and existing database files now require both owner-only mode bits and metadata UID equality with geteuid(); the Windows-only dead variant is cfg-gated.

@malkovitc

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f80b51cdce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/buzz-broker-host/src/store.rs Outdated
fn is_owned_by_effective_user(metadata: &std::fs::Metadata) -> bool {
use std::os::unix::fs::MetadataExt as _;
// SAFETY: geteuid(2) has no preconditions and only reads process identity.
metadata.uid() == unsafe { libc::geteuid() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Replace the unsafe effective-UID lookup

On every Unix build, this introduces an unsafe block into production code even though the repository explicitly prohibits unsafe code. Use a safe OS abstraction for the effective UID (and remove the direct libc call) so the new broker host conforms to the repository's safety boundary.

AGENTS.md reference: AGENTS.md:L158-L160

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in 37d6474. The direct libc dependency and unsafe block are removed; Unix ownership now uses the safe nix::unistd::geteuid().as_raw() API. Local host tests and workspace clippy pass with no unsafe in the new crate.

@malkovitc

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37d64743bd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +539 to +540
fn require_private_directory(_metadata: &std::fs::Metadata) -> Result<(), StoreError> {
Ok(())

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject insecure Windows state paths

On Windows, this unconditionally accepts the state directory, while the corresponding file check only verifies is_file(). If the configured directory grants another local user write access, that user can precreate or replace the SQLite database with a canonical authority and a credential digest they know, defeating the host-owned authority boundary. Validate Windows ownership/ACLs for both paths, or fail startup on Windows until that protection is implemented.

Useful? React with 👍 / 👎.

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