Repository navigation
fix(ape): expire pending approvals and unused grants - #4350
Merged
gabsprogrammer merged 4 commits intoSep 13, 2026
Merged
gabsprogrammer merged 4 commits into
gabsprogrammer merged 4 commits into
Conversation
…val-expiry-review-20260913
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.
Why this matters
APE persisted pending approval tokens and unused one-shot grants without an age limit. An old /verify escalation could be approved much later, and an old approved grant could bypass an exhausted window indefinitely, including after process restart. This confirms #4187 through actual authenticated endpoints.
Pending tokens now expire 15 minutes after issued_at; unused grants expire 15 minutes after granted_at. The exact boundary is exclusive (899 seconds valid, 900 expired). Missing, nonnumeric, nonfinite or future timestamps authorize nothing. Restart retains timestamps and cannot renew the window. Expired pending tokens are consumed and their rejection persisted; expired grants are consumed without bypass, so /verify evaluates the ordinary policy again. Startup also prunes stale approval state.
Overlap check
Searched open/closed APE main.py and approval/expiry/governance PRs. #2012 prunes state on save but has no approval lifetime; #2975 bounds audit reads; #3174 provisions API keys; #3987/#4200 redact tokens; #4171 changes advisory defaults. None expires either authorization stage. Both stages are intentionally fixed together so one cannot retain an indefinite bypass after the other is bounded.
Validation
python -m pytest tests -qin ods/extensions/services/ape: 52 passed under WSL.Review and compatibility
Kept draft: independent human review is required for this authorization-policy change and the fixed 15-minute choice. Clients waiting longer must re-verify and obtain fresh approval. Existing records use their saved issued_at/granted_at, so no state migration is needed. Clock rollback rejects future-dated grants. A delayed human approval does not extend a prior grant; it creates a separately bounded retry window.
No live agent/tool action was executed; tests use an always-allowed read intent behind an exhausted daily window. Windows/Linux container behavior shares this code; only WSL Python was executed locally. Reverting removes the expiration guard and can re-enable retained old state: rollback should clear pending approvals/grants under an operator-controlled maintenance stop, without discarding audit history.
Fixes #4187.
Batch integration receipt
Validated with the other 19 public-beta PRs on integration commit ce0d0132, based on upstream f5f49b7. All 20 patches compose without conflicts in creation order; no new PR requires another to fix its own behavior. For shared files, use #4325 before #4327 and #4339 before #4356 as the tested order.
CI follow-up b3ca5b0 reuses the exact procfs exit-race repair already present in #4255, after this PR's real CI run raised ProcessLookupError while observing an exiting process. All 6 process-lifecycle cases pass locally. This is a reused CI prerequisite, not another counted PR.
Latest candidate CI: 32 successful checks, 4 skipped. Draft status on filesystem/authorization changes is retained for independent human review despite green CI.