PROVENANCE BOUND AT ORIGIN. Evidence, 28 July 2026, migration 0081. THE SHARPENING: provenance must be stamped by the subsystem that creates the data, immutable, carried with the record, and the egress decision must derive from the STORED provenance of every element, never a call time declaration. WAS IT ALREADY BUILT THIS WAY: NO. The first implementation took provenance as a call time argument and the one external call site passed the literal scrub.ProvenancePublicCache. That is a control a single mistake defeats, because the only thing between a tenant document and OpenAI was a constant somebody typed. It has been removed. HOW IT IS BOUND NOW, migration 0081. For each source table: a DEFAULT supplies the value, a CHECK pins it to exactly one value, and a BEFORE INSERT OR UPDATE trigger OVERWRITES whatever a writer supplied on insert and RAISES on any change. A default alone was not enough, because a default only applies when the column is omitted and an INSERT naming the column would still let a writer choose. sam_opportunities born public_cache opportunity_records born public_cache opportunity_documents born tenant_upload opportunity_document_chunks born tenant_upload opportunity_scope_items born tenant_record candidates born tenant_record PROVEN AGAINST THE LIVE STAGING DATABASE, not by reading the migration: 1. A writer that ASKED for tenant_upload on a sam_opportunities insert got a row stamped public_cache. The trigger overrode the writer. 2. Laundering by UPDATE raises: "provenance is immutable: public_cache cannot become tenant_upload" 3. candidates carries DEFAULT 'tenant_record', so the workforce table is born private without anyone electing it. 4. All six binding sites carry the column, the CHECK, and the trigger: candidates col=1 check=2 trigger=1 opportunity_document_chunks col=1 check=1 trigger=1 opportunity_documents col=1 check=1 trigger=1 opportunity_records col=1 check=1 trigger=1 opportunity_scope_items col=1 check=1 trigger=1 sam_opportunities col=1 check=1 trigger=1 THE EGRESS DECISION NOW DERIVES FROM STORED VALUES. AllowEgress takes the SET of provenance values read from the rows a payload was composed from. The normalize command SELECTs s.provenance and passes what the database returned; it names no constant. Four conditions, all failing closed: a non empty set, every element permitted, a permitted class, and the marker backstop. ONE TENANT ELEMENT POISONS THE WHOLE PAYLOAD, proven by test. A public notice with one paragraph of a customer's PWS folded in IS a customer's PWS. AN EMPTY SET IS REFUSED, proven by test. Silence is not permission, and before this an empty set would have passed every loop vacuously. THE BINDING SITE INVENTORY, internal/platform/scrub/binding_sites_test.go, is what makes "fabricating provenance requires touching a named location" checkable rather than aspirational: every site in the inventory is asserted bound by the migration, column, CHECK, trigger, and stamped value the migration may not bind a table ABSENT from the inventory, so a silent addition fails the suite NO provenance constant may appear in application code outside the scrub package. A future call time declaration fails the day it is written. POSITIVE CONTROL on the detector itself: it must SEE a planted declaration and must NOT flag a call that correctly reads provenance from the row. Without this the regression test would pass an empty repository.