← back to Homesonspec
TK-11125: e2e-proof evidence bundle for the payload guard (R3, scratch DB)
6a1800df962c433f1bdfd9da06955e68c47b40eb · 2026-09-02 13:53:14 -0700 · Steve Abrams
Verdict PASS. 5 data-boundary cases + unit tests, all green on
homesonspec_test. Records the no-migration design divergence + gates
respected (no prod write/deploy/push).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JRL7REtkaBnRrfHk42iYm
Files touched
A verification/TK-11125-payload-guard-e2e-proof.json
Diff
commit 6a1800df962c433f1bdfd9da06955e68c47b40eb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Sep 2 13:53:14 2026 -0700
TK-11125: e2e-proof evidence bundle for the payload guard (R3, scratch DB)
Verdict PASS. 5 data-boundary cases + unit tests, all green on
homesonspec_test. Records the no-migration design divergence + gates
respected (no prod write/deploy/push).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016JRL7REtkaBnRrfHk42iYm
---
verification/TK-11125-payload-guard-e2e-proof.json | 89 ++++++++++++++++++++++
1 file changed, 89 insertions(+)
diff --git a/verification/TK-11125-payload-guard-e2e-proof.json b/verification/TK-11125-payload-guard-e2e-proof.json
new file mode 100644
index 00000000..c3dab7b4
--- /dev/null
+++ b/verification/TK-11125-payload-guard-e2e-proof.json
@@ -0,0 +1,89 @@
+{
+ "ticket": "TK-11125",
+ "parentTicket": "TK-10878",
+ "intent": "Forward-only guard that skips minting a spurious StagedRecord generation + SourceEvidence set when a new raw snapshot carries byte-identical extracted property data (only volatile page bytes changed). History-preserving, no deletion, no schema migration.",
+ "spec": ".claude/yolo-queue/verification/TK-10878/TK-11125-impl-spec-2026-09-02.md",
+ "riskTier": "R3 (local user-facing data-pipeline flow; data-layer boundary). Prod deploy separately GATED — not performed here.",
+ "environment": {
+ "machine": "Mac2 (local)",
+ "node": "v26.4.0",
+ "database": "homesonspec_test (scratch; harness refuses any non-*_test DB)",
+ "prodDbTouched": false
+ },
+ "build": {
+ "repo": "/Users/macstudio3/Projects/homesonspec",
+ "branch": "master",
+ "headCommit": "319168ad20f88b70ecd2db7ad06d9a191a02a298",
+ "commits": [
+ "671fbb26 TK-11125: add stableStringify + payloadHash canonical hash helper (shared)",
+ "319168ad TK-11125: forward-only spurious-generation guard in extractStage"
+ ]
+ },
+ "timestamp": "2026-09-02T20:52:33Z",
+ "designDivergenceFromSpec": {
+ "spec": "Add a nullable column StagedRecord.payloadHash to persist the hash.",
+ "implemented": "NO column, NO migration. StagedRecord.payload already stores normalized.fields verbatim (schema.prisma:449), so the latest generation's payloadHash is recomputed on read via one findFirst(orderBy createdAt desc) using the existing @@index([canonicalKey]).",
+ "why": "Honors the hard 'no migrations' task constraint, is pure-code reversible, matches the spec's exact semantics sha256(stableStringify(normalized.fields)), and works on all 170M existing rows immediately (no NULL-first-miss). The column was a read-avoidance optimization; the data is already present.",
+ "safety": "Guard skips ONLY when the latest generation is a DIFFERENT (prior) snapshot AND its canonical payload hash equals the new one. Any canonical-form difference (incl. a float reformat through JSONB) falls through to create a generation = current behavior. The guard can therefore only ever SKIP an exact duplicate, never suppress a real change (no history loss possible).",
+ "sameSnapshotReextract": "latest.snapshotId !== snapshotId escape preserves today's FORCE_REEXTRACT update-in-place semantics."
+ },
+ "baseline": "Working tree clean on master @ c97856c6 before work; existing integration suite 7/7 green pre-change.",
+ "commandsRun": [
+ "pnpm --filter @homesonspec/shared test (32 passed, incl. 11 new payload-hash unit tests)",
+ "pnpm --filter @homesonspec/shared typecheck (clean)",
+ "pnpm --filter @homesonspec/workers typecheck (clean)",
+ "pnpm --filter @homesonspec/workers test:integration (12 passed: 7 baseline + 5 new guard cases)"
+ ],
+ "assertions": [
+ {
+ "boundary": "unit (pure hash)",
+ "check": "stableStringify is key-order independent across a JSONB round-trip; a real field change / changed provenance envelope yields a different payloadHash; 64-char sha256 hex.",
+ "verdict": "PASS"
+ },
+ {
+ "boundary": "data (StagedRecord + SourceEvidence)",
+ "case": "4a — brand-new home",
+ "check": "1 StagedRecord generation + 2 SourceEvidence rows.",
+ "verdict": "PASS"
+ },
+ {
+ "boundary": "data (StagedRecord + SourceEvidence)",
+ "case": "2 — new snapshot, byte-identical fields (THE FIX)",
+ "check": "extractStage returns 0 stagedIds; generation count stays 1; NO fresh evidence set minted. (Pre-fix this was 1 new generation.)",
+ "verdict": "PASS"
+ },
+ {
+ "boundary": "data (StagedRecord + SourceEvidence)",
+ "case": "3 — new snapshot, real field change (phone changed)",
+ "check": "exactly 1 new generation (count 1 -> 2); evidence 2 -> 4. History preserved.",
+ "verdict": "PASS"
+ },
+ {
+ "boundary": "data (StagedRecord)",
+ "case": "2b — re-seeing settled data on yet another snapshot",
+ "check": "0 new generations (no drift once data settles).",
+ "verdict": "PASS"
+ },
+ {
+ "boundary": "data (StagedRecord + SourceEvidence)",
+ "case": "4b — FORCE_REEXTRACT same snapshot adding a field",
+ "check": "same row updated in place (returned id == latest.id), no new generation; evidence replaced to 3 rows. FORCE_REEXTRACT backfill semantics preserved.",
+ "verdict": "PASS"
+ }
+ ],
+ "negativeChecks": [
+ "Guard never skips a real change — proven by case 3 (real change -> new generation) and the unit test 'gives a DIFFERENT hash for a real field change'.",
+ "Fail-safe direction: any hash mismatch (including provenance-envelope-only changes) falls through to create a generation."
+ ],
+ "cleanup": "Integration test cleans only its own (canonicalKey-scoped) rows in beforeAll and co-exists with the existing pipeline.itest; scratch DB only, no prod state changed.",
+ "gatesRespected": [
+ "No production DB writes or migrations (recompute-from-payload => zero schema change).",
+ "No deletes / pruning / history collapse.",
+ "No deploy / restart.",
+ "No external actions, no remote push.",
+ "Prod deploy remains separately GATED (spec Gate section) — awaiting Steve GO."
+ ],
+ "verdict": "PASS",
+ "status": "complete (local); prod deploy GATED",
+ "safestNextAction": "Parent (iterm-tk10878-readonly-v2) independently inspects the diff + reruns test:integration; then draft the prod-deploy memo to pending-approval for Steve's GO (deploy = pipeline runs via tsx on source; no migration to apply)."
+}
← 319168ad TK-11125: forward-only spurious-generation guard in extractS
·
back to Homesonspec
·
HoS mobile: block GTM/GA4/Facebook trackers in Browse WebVie 9e884ed1 →