{ "source": "cdd39ee07533718765a59640b58faa73f5a54135", "originalOutcome": "FAIL: missing distinct shared-cache and regression parser rejection", "originalPlanSha256": "aa4d80083dbbb80a369146c71070606db4bd0ca87b146ddcfbf53e13f723bab9", "parts": [ "### R8: Regression contract for legacyAuthFlow() parity (IRON RULE)\nFinding: T1, P1 CRITICAL, confidence 9/10, PLAN.md:23-25 \"That coverage does not exercise legacyAuthFlow() or assert compatibility with its prior behavior\" + PLAN.md:36-37 \"no regression test for the prior behavior is planned\"; reviewer: Claude\nPlan baseline: no regression coverage. D3 = A makes legacyAuthFlow() the fallback and requires \"parity proven\" before deletion, but HOW parity is proven was unapproved.\nRuntime evidence: unknown \u2014 legacyAuthFlow() not in repo; its callers and behavior must be enumerated during implementation.\nState: approved\nComparison grid:\n\n| Choice | Current | A | B | C |\n|---|---|---|---|---|\n| R8 parity proof | none | characterization suite + shadow compare: (1) record legacyAuthFlow() input\u2192outcome fixtures for every allow, deny and error class per tenant type; run both paths against them in CI; (2) with flag in \"shadow\" mode, run both paths in prod, serve legacy result, log any mismatch with tenant id + reason kind | characterization suite only (CI) | shadow compare only (prod) |\n| Behavior to preserve | unstated | allow/deny outcome, error class \u2192 response mapping, cache entries written (key + TTL), invalidation on logout/revocation/suspension | same | same, observed at runtime only |\n| Intentional differences | unstated | fail-closed on formerly swallowed errors (D7): listed explicitly as expected mismatches | same | same |\n| Deletion gate for legacy | unstated | 0 unexpected mismatches over an agreed window (proposal: 7 days, \u22651 canary tenant per tenant type) | green CI suite | 0 mismatches over the window |\n| R1/R7 | approved | fixed | fixed | fixed |\n\nQuestion D8:\nD8 \u2014 How do we prove the new path matches legacyAuthFlow() before deleting it: characterization tests plus shadow comparison, tests only, or shadow only?\nHeader: Regression\nOptions:\nA) Characterization suite + shadow-mode comparison (recommended)\nB) Characterization suite only\nC) Shadow-mode comparison only\nActual answer: A \u2014 Characterization suite + shadow-mode comparison (user answer to D8)\nAccepted scope: (1) `legacyAuthFlow.characterization.test` \u2014 fixture table of inputs \u2192 {outcome, error kind, cache writes} recorded from legacyAuthFlow(), run against both legacyAuthFlow() and AuthBroker.validateAndDispatch() in CI; covers every allow, deny and each formerly swallowed error class, per tenant type. (2) Flag gains a third state `SHADOW`: run both paths, serve legacy, emit `auth.parity.mismatch{tenant, kind}` on disagreement. (3) Expected-mismatch allowlist: D7 fail-closed cases. (4) Legacy deletion gate: 0 unexpected mismatches over 7 days with \u22651 canary tenant per tenant type. Behavior preserved: allow/deny outcome, error class \u2192 response mapping, cache entries written (key + TTL), invalidation on logout/revocation/suspension.\nHistory: none\n\n", "- [ ] **T6 (P1 CRITICAL, human: ~3 days / CC: ~45 min)** \u2014 test/characterization, auth/routing \u2014 Characterization suite from legacyAuthFlow() run against both paths; SHADOW compare + `auth.parity.mismatch` metric + D7 allowlist\n - Surfaced by: Test review T1 / D8 (PLAN.md:23-25, :36-37)\n - Files: test/characterization/legacyAuthFlow.characterization.test, auth/routing/shadowCompare\n - Verify: suite green on both paths; deliberately broken fixture emits mismatch; allowlisted case does not\n" ] }