Repository navigation
Conversation
Add an end-to-end test asserting that a pending approval left by an earlier version cannot be approved in a later launch but can be denied, and that the denial persists across restarts. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Human verification now accepts a pending orphan from a previous launch when the choice is a denial, matching the row as listed rather than requiring it to be pending in this process. Orphan rows under review are held in a bounded map so the module can verify the denial byte for byte. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Introduce a module that detects and cleans up approval engine instances left orphaned after their owning task ends. This prevents stale engines from accumulating and holding resources. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Adds a dismiss_orphan method to the ApprovalEngine trait that denies a pending orphan request as a person's decision, returning NotPending when the request is not one. The native engine implements it behind the legacy-import feature by delegating to its existing orphan dismissal, which was renamed to avoid clashing with the new trait method. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
…ovals Decision validation now returns the parked approval so the gate can tell a missing request from an orphan, and the default tenant may resolve orphaned pending approvals that are otherwise listed but undismissable. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Wrapped long lines and collapsed a multi-line signature in the native approval callbacks and orphan engine so the files match rustfmt output. No behaviour changes. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Pending requests left over from an earlier launch are now recorded as orphans so they can be listed separately and only ever denied, since no host instance owns them and a decision cannot reach them. Added an orphans listing and a dismiss path that marks such requests denied with a label. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Wire the new gate_orphan_tests.rs file into the approval gate test suite so its orphan-handling cases are compiled and run alongside the existing gate tests. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
The orphan test no longer asserts on the result of naming an agent when denying an orphan, since the agent path's answer is irrelevant to the invariant that the orphan stays pending. Module declarations were also reordered alphabetically and a call was reformatted. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a test asserting that an orphan row under review verifies only a denial of the exact listed row, that a second concurrent review is refused, and that verification fails before the review begins and after it ends. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Added a row to the native approval module's file table describing engine_orphans.rs, which denies pending orphans left behind by an earlier launch, so the module overview reflects the file's role. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Explain how the legacy import carries undecided requests into TinySecurity as pending orphans owned by no host instance, and note that such rows can only be denied, never approved, until they are denied or their window closes. Auto-committed-on: cuttlefish Co-authored-by: Medulla <medulla@tinyhumans.ai>
Tiny Sweeper reviewVerdict: Incomplete · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): fix(approval): let a person deny a request an earlier launch left waiting. Tiny Sweeper completed its review; deterministic results follow. Unreviewed paths
Partial review reasons
Review snapshot
Completeness: Incomplete Features
Tests
FindingsNo active actionable findings. Before merge
Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
Codex Review Summary: ✅ CompletedThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
🟡 Changes recommended
The orphan test reuses a request ID left in the process-wide map by another test, causing order-dependent failures; it needs a distinct request ID.
1 open issue
What changed in this PR
Following #8657, this PR lets users dismiss pending approval requests imported from an earlier launch. It preserves the deny-only restriction because the original call cannot run in the current process.
Changes:
- Adds default-tenant orphan dismissal through the approval gate and native engine.
- Verifies denial tickets against the exact orphan row.
- Adds gate, callback, and restart-persistence tests, plus supporting documentation.
| File | Description |
|---|---|
tests/storage_default_import_e2e.rs |
Tests approval refusal and durable dismissal across restarts. |
crates/openhuman-core/src/security/approval/README.md |
Documents deny-only orphan handling. |
crates/openhuman-core/src/security/approval/native/state.rs |
Tracks orphan rows under review. |
crates/openhuman-core/src/security/approval/native/mod.rs |
Documents the orphan engine module. |
crates/openhuman-core/src/security/approval/native/engine.rs |
Registers the legacy-import orphan module. |
crates/openhuman-core/src/security/approval/native/engine_orphans.rs |
Implements audited, deny-only native dismissal. |
crates/openhuman-core/src/security/approval/native/engine_impl.rs |
Connects the engine trait to native dismissal. |
crates/openhuman-core/src/security/approval/native/callbacks.rs |
Verifies orphan denials against the reviewed row. |
crates/openhuman-core/src/security/approval/native/callbacks_tests.rs |
Tests denial-only verification and row matching. |
crates/openhuman-core/src/security/approval/gate.rs |
Includes orphan decision handling. |
crates/openhuman-core/src/security/approval/gate_tests.rs |
Registers orphan gate tests. |
crates/openhuman-core/src/security/approval/gate_state.rs |
Routes eligible default-tenant decisions to orphan handling. |
crates/openhuman-core/src/security/approval/gate_orphans.rs |
Handles dismissal and publishes the decision event. |
crates/openhuman-core/src/security/approval/gate_orphan_tests.rs |
Tests dismissal, tenant restrictions, and expiry. |
crates/openhuman-core/src/security/approval/engine.rs |
Adds the orphan dismissal trait method. |
crates/openhuman-core/src/security/approval/engine_stub.rs |
Models orphan listing and dismissal for tests. |
Review effort: Balanced
| /// is ever verified for one. | ||
| #[tokio::test] | ||
| async fn an_orphan_under_review_verifies_only_a_denial_of_the_listed_row() { | ||
| let orphan = row("verify-orphan", "a", "abcd000a", "shell"); |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d931950c9f
ℹ️ 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".
| let proxy = self.proxy().await?; | ||
| // The import files every legacy row under the default tenant's | ||
| // standard subject, so that is the only scope an orphan lives in. | ||
| let scope = self.history_scope(&proxy, &Tenant::default()).await?; |
There was a problem hiding this comment.
Preserve the live posture when locating an orphan's scope
When a default-tenant tool check with auto_approve_all enabled runs concurrently with an orphan denial, this scope lookup can overwrite the check's configured posture. history_scope() calls scopes::ensure() with require_approval=true and auto_approve_all=false, and ScopeEntry::register() replaces the existing standard scope when that differs from its current posture. NativeEngine::check() registers its intended posture before acquiring scope.stream, so the denial can replace it between registration and EvaluateApproval2, causing an unrelated call to prompt or be refused unexpectedly. Reuse the existing scope without changing its posture, registering the conservative posture only when the scope is new.
Useful? React with 👍 / 👎.

Summary
Follow-up to #8657. That PR carried requests an earlier version left waiting into TinySecurity as pending orphans and listed them in
approval_list_pending, but nothing could clear one:approval_decideanswered "no pending approval ever registered", so an orphan stayed on the list until its window closed.This PR lets a person deny (dismiss) an orphan. Approving one is still refused: nothing in this launch can run the call it was for, and TinySecurity's
Decide2accepts only a denial for a row another host instance owns.Changes
security/approval/gate_orphans.rs, hooked intoApprovalGate::decide_as):ApprovalDecidedand returns the row.dismiss_orphan. Its default answersNotPending.native/engine_orphans.rs):legacy_history_json, and be inside its window.Decide2on that scope's audit stream.denylabel, and reports a lost race asNotPending.native/callbacks.rs,native/state.rs):verify_humanaccepts only an orphan currently under review.Deny.leave_orphan,orphans,dismiss_orphan). Itsdeciderefuses an orphan, as the native engine does.README.mdand thenative/mod.rslayout table.Tests (RED → GREEN)
tests/storage_default_import_e2e.rs::a_request_an_earlier_version_left_waiting_can_be_denied_but_never_approvedno pending approval ever registered for request_id '…'. GREEN after.security/approval/gate_orphan_tests.rs(4 tests): deny dismisses; the approve decisions are refused; another profile or a named agent cannot dismiss; an expired orphan and an unknown id are not dismissed.decide_ashook disabled.native/callbacks_tests.rs::an_orphan_under_review_verifies_only_a_denial_of_the_listed_rowcargo test -p openhuman --lib -- security::approvalpasses: 223 tests, plus the new callbacks test.Notes
legacy_history_jsonback to the id from the earlier version.Summary by CodeRabbit