fix(errors): 403 auth rejections no longer read as policy blocks#197
Open
saurabhjain1592 wants to merge 1 commit into
Open
fix(errors): 403 auth rejections no longer read as policy blocks#197saurabhjain1592 wants to merge 1 commit into
saurabhjain1592 wants to merge 1 commit into
Conversation
Release-gate smoke for getaxonflow/axonflow-enterprise#2861 found that every agent error envelope carries a literal "blocked" JSON key (a tenant-mismatch rejection is {"success":false,"error":"Tenant mismatch","blocked":false}), so handleErrorResponse's body.contains("policy") || body.contains("blocked") substring heuristic classified EVERY 403 authorization rejection as PolicyViolationException. Callers following the documented pattern of treating policy blocks as an expected, non-fatal outcome silently swallowed real auth failures (wrong client-id/user-token tenant pairing) with exit 0. The 403 branch now parses the JSON body and treats a present "blocked" boolean as authoritative: true -> PolicyViolationException, false -> AuthenticationException. Only unparseable or blocked-less bodies fall back to the policy-phrase heuristic (policy / block_reason; the bare "blocked" substring no longer counts). This is the only substring classification site in the method — 401 always maps to AuthenticationException and the remaining branches key on status code alone. Tests: exact live tenant-mismatch envelope -> AuthenticationException; blocked:true envelope -> PolicyViolationException; unparseable-body fallback both ways (1316 unit tests green). New live-stack leg runtime-e2e/error_classification_403/ asserts both directions through proxyLLMCall against a real enterprise agent; it fails against the 8.5.1 jar and passes against this build. Release prep for 8.5.2: pom.xml bumped, CHANGELOG [Unreleased] renamed to [8.5.2] - 2026-07-10 with the fix noted, example poms pinned to 8.5.2 per the 8.5.1 release convention (CI re-syncs them to the parent version at run time). Signed-off-by: Saurabh Jain <saurabh.jain@getaxonflow.com>
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.
Release-blocking library fix from the getaxonflow/axonflow-enterprise#2861 release-readiness gate. Makes 8.5.2 cut-ready (operator cuts the tag).
Bug
Every agent error envelope carries a literal
"blocked"JSON key — a tenant-mismatch rejection is:{"success":false,"error":"Tenant mismatch","blocked":false} // HTTP 403so
handleErrorResponse's substring heuristicclassified every 403 authorization rejection as
PolicyViolationException. Callers following the documented pattern (policy block = expected, non-fatal outcome) silently swallowed real auth failures with exit 0 — exactly howexamples/basicpassed the smoke with a wrong client-id/user-token tenant pairing.Fix
The 403 branch parses the JSON body (Jackson, already in use) and treats a present
blockedboolean as authoritative:"blocked":true→PolicyViolationException"blocked":false→AuthenticationException(HTTP 403)blockedboolean → legacy policy-phrase fallback (policy/block_reason; the bareblockedsubstring no longer counts)Audited the rest of the method: this was the only substring-classification site — 401 always maps to
AuthenticationException; 402/409/429/408/504 key on status code alone.Tests
AuthenticationExceptionwith message intact;blocked:trueenvelope →PolicyViolationException; unparseable-body fallback in both directions. Full suite: 1316 tests, 0 failures.runtime-e2e/error_classification_403/(no skip hatch) asserting both directions throughproxyLLMCall.Live runtime-e2e evidence (enterprise stack, platform v9.6.1, agent :8080)
Against this build (8.5.2 jar):
Same leg against the released 8.5.1 jar (proves the bug + the leg's sensitivity):
Release prep (same PR, per the version-alignment gate)
pom.xml8.5.1 → 8.5.2[Unreleased]→[8.5.2] - 2026-07-10(keeps the fix(examples): basic reads AXONFLOW_USER_TOKEN; async parity e2e #194 example/runtime-e2e content, adds the 403-classification### Fixedbullet).github/scripts/validate-version-alignment.shgreen locallyRefs getaxonflow/axonflow-enterprise#2861.