Skip to content

fix(ape): fail closed on unknown policy modes - #2994

Open
tang-vu wants to merge 1 commit into
Osmantic:mainfrom
tang-vu:fix/ape-fail-closed-unknown-mode
Open

fix(ape): fail closed on unknown policy modes#2994
tang-vu wants to merge 1 commit into
Osmantic:mainfrom
tang-vu:fix/ape-fail-closed-unknown-mode

Conversation

@tang-vu

@tang-vu tang-vu commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Why this matters

APE is the production authorization boundary for agent tool actions. A typo or newly introduced policy mode currently evaluates as allowed, so malformed operator policy silently weakens enforcement exactly when APE cannot understand the requested rule.

Root cause and invariant

The evaluator handled known modes explicitly, then allowed every other value. The invariant is fail-closed policy interpretation: only a recognized allow rule may authorize an action; unknown configuration must produce an auditable denial.

Unknown modes now return a normal policy denial. Existing non-strict deployments receive the established 200 decision envelope with allowed=false; strict mode continues converting policy denials to 403.

Overlap check

Searched open and closed PRs for APE unknown policy mode, defaulting to allow, and ods/extensions/services/ape/main.py. Open same-file PRs #2974 and #2975 correct decision totals and audit query bounds. Existing APE PRs around path guards, rate-limit storage, breakers, and state pruning do not change unknown-mode evaluation.

Regression coverage

A /verify boundary test loads a realistic policy with the misspelled mode alow, calls a classified ReadFile action, and asserts a deny decision plus the explicit reason. This exercises policy loading, intent classification, evaluation, and the public response together.

Validation

  • pytest -q ods/extensions/services/ape/tests/test_main.py -x ? 29 passed
  • python -m py_compile ods/extensions/services/ape/main.py ods/extensions/services/ape/tests/test_main.py
  • git diff --check

Tradeoffs and rollback

A malformed policy that previously failed open will now block affected actions until corrected; that operator-visible interruption is intentional. Valid allow, deny, allowlist, and path_guard behavior is unchanged. Revert restores fail-open behavior with no state migration.

@tang-vu

tang-vu commented Aug 22, 2026

Copy link
Copy Markdown
Contributor Author

Batch compatibility receipt (2026-08-23)

Validated merge order: #2989 ? #2990 ? #2993 ? #2991 ? #2992 ? #2994 ? #2995 ? #2996 ? #2997 ? #2998. The changes are independently useful; this order only reconciles shared model-router and magic-link files.

Synthetic integration head: origin/batch/quality-ten-20260822-round2-integration at 91eb730d. The only textual conflict was the two model-router tests inserting at the same class boundary; the integration resolution retains both contracts. Magic-link changes merged cleanly.

Combined validation on that exact head:

  • remote-provider egress contract: 16 passed
  • Token Spy suites: 22 passed, 1 skipped (live PostgreSQL availability)
  • model-router suite: 55 passed
  • APE suite: 29 passed
  • dashboard OAuth + magic-link suites: 118 passed, 2 platform skips
  • Brave Search loopback E2E: all checks passed
  • git diff --check: passed

All required GitHub checks are green across the batch. #2992 initially hit a transient openSUSE repository/mirror failure while installing rsync; a clearly labeled empty retry commit reran the unchanged tree, and openSUSE plus the full matrix 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.

1 participant