Phase 3: golden contract corpus recorded from the current stack (red suite)#143
Merged
Conversation
…116) Phase 3 red suite for the Goodbye-gRPC rewrite (PRD #112): - contract/goldens/: 69 canonicalized goldens covering all 16 surviving public routes x happy/edge/error/auth cases, both enum path forms, repeated filters and dual-spelling query keys on tickets - canonicalizer + semantic JSON differ (parse -> canonicalize -> diff; number form, array order, null-vs-empty-vs-absent all contractual; byte output informational only) - single documented transform: StripKeycloakID (field dies at cutover); keycloak lookup route deliberately unrecorded - in-process harness: real gateway handler -> real gRPC server with the production interceptor chain -> seeded deterministic fake datastore; no MySQL/Redis/docker, plain go test, sub-second replay - re-record procedure documented in contract/README.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… surface Canonicalize/MarshalCanonical/StripKeycloakID/Diff become canonicalize/ marshalCanonical/stripKeycloakID/diff. Public surface is exactly Cases, Case, Auth (+constants), Golden, RunCase, CompareGolden, SaveGolden, LoadGolden. README documents the deep-module rationale. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…with a watchdog Review finding (silent-failure): srv.Serve's error was discarded and gateway.Service.Server() dials with WithBlock on Background — a startup failure hung go test for 10 minutes with zero diagnostics. Serve now reports through a channel; the mount selects on completion / serve error / 10s timeout and fails fast with the serve error in the message. Mid-run serve death surfaces per-test via currentStack. Sabotage- verified: closed listener fails in 1.1s, dead dial port at 10.0s, both with descriptive messages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, body XOR Recorded case/method/path/auth now diff instead of being write-only; recorded header keys outside the contractHeaders allowlist are flagged; a golden carrying both or neither of body/bodyText is a diff. Mutation tests tamper each field and assert the specific diff fires. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add WWW-Authenticate to the contractHeaders allowlist. #106 froze the 401 tiers as challenge-free; RunCase skips empty headers so committed goldens are unchanged (verified: zero diff), and a rewrite whose auth middleware adds the header now produces a red ""-vs-set diff — empirically proven by TestWWWAuthenticateAbsenceIsPinned. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
strings.HasPrefix let /api/v1/tickets be satisfied by any tickets case and /tickets/42 by the messages cases. Each case path (query stripped) now classifies to the first of 16 anchored patterns, most-specific first; deleting all cases for one route fails the guard (proven red by temporarily removing the ticket-by-id cases). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
LoadGolden rejects goldens violating the body/bodyText XOR or carrying an undefined auth tier (new Auth.Valid()). goldenPath rejects empty names and names that are not filepath.IsLocal after FromSlash, with the error surfaced from both SaveGolden and LoadGolden. A rejection test covers each case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.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.
Closes #116. Part of #112 (PRD: Goodbye gRPC) — the red suite for the whole rewrite.
What
contract/— 69 committed goldens across all 16 surviving public routes, plus the replay harness that makes them executable against anyhttp.Handler:gateway.Service.Server()(auth → sentry → cache → compression, incl. the tickets bypass) over a real loopback gRPC server with the production interceptor order, seeded deterministic fake datastore, always-erroring RESP stub for deterministic cache misses. No docker; full corpus replays in ~0.1s.{}vs absent are contractual; bytes informational only (protojson isn't byte-stable). Status + allowlisted headers (Content-Type,X-Content-Type-Options, andWWW-Authenticate— whose absence on the 401 tiers is pinned per fix(auth): two-tier 401 distinguishing bad Bearer scheme from key failure #106) are part of every golden.keycloakIdstripped symmetrically at record and replay (the field dies at cutover; goldens record truth, the transform documents the break). The keycloak lookup route is deliberately unrecorded and its absence test-enforced.strconv.ParseUinttext, JSON 404, enum name+number path forms (bodies verified identical pairwise), snake/camel dual spellings, repeated filters, unknown-params-ignored,{"profiles":{}}empty search (Position search returns empty profiles for plausible queries - bug or expected? #137), read vs read:tickets scopes.Cases,RunCase,CompareGolden,SaveGolden,LoadGolden(+Case/Auth/Golden). Canon machinery is internal — deep module, small replay-facing interface.Review hardening (multi-agent review applied, each fix red-proven)
CompareGoldenself-checks: request metadata (case/method/path/auth), non-allowlisted recorded headers, body/bodyText XOR — golden↔battery de-sync now diffs loudlyLoadGoldenvalidation +goldenPathtraversal guardTest plan
-count=2/-count=3stable$.pathdiffs (6 tamper classes)contract/;go.moduntouched🤖 Generated with Claude Code