Skip to content

fix(ape): expire pending approvals and unused grants - #4350

Merged
gabsprogrammer merged 4 commits into
Osmantic:public-betafrom
tang-vu:fix/beta-ape-approval-expiration
Sep 13, 2026
Merged

gabsprogrammer merged 4 commits into
Osmantic:public-betafrom
tang-vu:fix/beta-ape-approval-expiration

Conversation

@tang-vu

@tang-vu tang-vu commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

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

  • Initial endpoint regressions failed on base: expired pending approval minted a grant; expired unused grant authorized a retry after restart.
  • python -m pytest tests -q in ods/extensions/services/ape: 52 passed under WSL.
  • Eight new HTTP cases cover 899/900-second boundaries, pending and granted stages, with/without restart, plus preserved one-shot consumption. Existing tests cover exact action scope, hard policy denials and persistence.
  • Scoped pre-commit and git diff --check passed.

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.

  • Final combined dashboard: 118 test files / 932 tests pass; ESLint 0 errors (575 warnings); production build passes.
  • Affected API suites: 292 pass. APE full suite: 52 pass. Scoped pre-commit secret/private-key/large-file checks and git diff --check pass.
  • Native Linux make gate reaches an existing CLI-update failure also reproduced on the untouched base; fix(update): keep host-agent refresh non-fatal #3159 supplies its separate fix. BATS: 419/421 pass, with the same two baseline failures (non-GNU OSTYPE fixture detects the real WSL host; skip-Docker fixture lacks production helpers). Smoke tests and installer simulation pass. These are explicit validation gaps, not a claim that the whole release gate is green.

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.

@gabsprogrammer
gabsprogrammer marked this pull request as ready for review September 13, 2026 17:19
@gabsprogrammer
gabsprogrammer merged commit 5704029 into Osmantic:public-beta Sep 13, 2026
42 checks passed
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.

2 participants