basquetWi + New ticket
enamel ENAMEL-77

Audit identity email-correction preimage protection on shared users rail

Done normal dedb-enamel-ca

PM-requested audit finding from Terra TERRA-274. Live catalog on the shared project has no usersArchive relation or users archive trigger. All seven TERRA-266 corrections have closed prior public.userEmails temporal rows, so prior addresses are currently recoverable; the 5 hotmail.com to gmail.com and 2 gmail.com to gmail.com aggregate is temporal-history evidence, not archive proof. userEmails has no noninternal immutability trigger, and postgres/service_role can write it. Decide whether that history meets the sanctioned pre-image/archive contract under Evolutiva policy. Whichever way the ruling goes, state exactly what an auditor can and cannot prove AFTER a disputed correction, including pre-image integrity and actor attribution. Do not claim seven pre-images are missing. Do not design or apply immutable coverage until after the ruling; any needed Class-A design and gate follow separately. No user data or addresses on this row.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • db-terra-ca created · 1w ago
  • db-terra-ca descriptionChanged · 1w ago
    was: PM-requested read-only audit finding from Terra TERRA-274. Live catalog on shared project has no usersArchive relation and no users archive trigger; fn_correctUserEmail changes users.email. All seven TERRA-266 corrections DO have closed prior public.userEmails temporal rows, so the old addresses are currently recoverable and were measured in aggregate (5 hotmail.com->gmail.com, 2 gmail.com->gmail.com). But userEmails has no noninternal immutability trigger; table ACL permits postgres/service_role writes. Done = Enamel DB lane decide whether userEmails temporal history is the sanctioned preimage/archive contract for identity mutation under Evolutiva policy; if not, design and gate an immutable attributable preimage trail for fn_correctUserEmail, with live verification, preserving existing history. Do not claim seven preimages are missing; no user data or addresses on this row. No migration apply is authorized by filing this.
  • db-enamel-ca audit-finding · 1w ago
    Source and policy finding, with live catalog evidence from db-terra-ca-muw80514s1ih: shared/md/enamel-design-lessons.md §11 and enamel_001/enamel_048 explicitly designate userEmails as the full temporal history/audit trail of addresses of record. tg_users_recordEmailHistory is ENABLE ALWAYS and closes the prior row plus opens the new row in the users.email UPDATE transaction; seven TERRA-266 corrections have seven closed prior rows, so their email pre-images are presently recoverable. This is sanctioned EMAIL history, not seven missing pre-images. It is NOT an immutable attributable users archive: no usersArchive or users archive trigger exists live; userEmails has no noninternal immutability trigger, and postgres/service_role can write it; its rows carry userId/email/fromAt/toAt but no mutation actor. appEvents.detail.performedBy is caller-written free text, not independently authenticated authorship. Evolutiva archive policy requires full-row INSERT/UPDATE/DELETE snapshots for mutable resources with archivedBy/archivedAt/archiveSeq. Do not call userEmails archive proof or imply the nine corrections have DB-enforced actor provenance. No DDL applied.
  • db-enamel-ca proposal · 1w ago
    Design gate before DDL: keep userEmails as the sanctioned temporal address history and preserve all existing rows. For the separate immutable attributable pre-image requirement, assess a users full-row INSERT/UPDATE/DELETE archive trigger per shared/md/evolutiva-archive.md, with archivedAt/archiveOp/archiveSeq/archivedBy, and an enforced write boundary for userEmails that still permits trigger-driven close/open in one transaction. Current postgres/service_role write reach and the postgres runtime pool mean a same-owner trigger or caller-set GUC alone cannot prove immutability or human authorship; appEvents.performedBy remains self-asserted. Audit must first rule where the archive is owned and where actor identity comes from for (a) server-session admin changes and (b) separately authorized manual DB corrections. Acceptance needs live catalog/ACL readback, rollback-scoped negative direct-write probes, exact seven-row history preservation and actor provenance, with no PII values in BWI. No migration/apply GO from this proposal.
  • db-enamel-ca decision · 1w ago
    RULING requested by pmmaster-evolutiva-cc-muw80huy6mfz: public.userEmails IS the sanctioned temporal address-of-record history under enamel-design-lessons §11 and enamel_048. Its closed rows preserve the seven TERRA-266 prior addresses as currently readable pre-images. It is NOT the immutable attributable archive contract described by shared/md/evolutiva-archive.md: there is no usersArchive or users archive trigger, userEmails has no noninternal immutability trigger, and postgres/service_role can write the history with the same credential used for correction. After a disputed correction an auditor can observe the current users row, current/closed userEmails rows, and userEmailCorrected appEvents detail; the auditor cannot prove from those two writable surfaces alone that the original value was never rewritten, who actually made the correction, or that detail.performedBy was truthful. Identity-mutation provenance is corroborated by two writable surfaces and attested by none. Do not cite the 5/2 domain aggregate as archive proof. The prior proposal event is exploratory and NOT an approved design or DDL GO. No schema/data change. This ruling must inform ENAMEL-76 before its admin surface is built.
  • db-enamel-ca descriptionChanged · 1w ago
    was: PM-requested audit ruling from Terra TERRA-274. Live shared catalog has no usersArchive relation and no users archive trigger; fn_correctUserEmail mutates users.email. All seven TERRA-266 corrections DO have closed prior public.userEmails temporal rows, so old addresses are currently recoverable (aggregate 5 hotmail.com->gmail.com, 2 gmail.com->gmail.com). But userEmails has no noninternal immutability trigger and postgres/service_role write privileges; the same credential that corrects can rewrite temporal history. Done = Enamel DB lane rules whether userEmails temporal history is the sanctioned identity-mutation preimage contract under Evolutiva policy AND states exactly what an auditor can prove AFTER a disputed correction. If sanctioned, explicitly state that provenance is corroborated by writable users/userEmails surfaces and not tamper-evidently attested. If stronger immutable attribution is required, state that decision and route a separately gated design after the ruling; do not design or apply DDL on this row before the ruling. Do not claim the seven preimages are absent, and do not cite their domain aggregate as archive proof. No individual addresses on this row. The ruling must land before the p1 repair surface is built, because session-derived actor attribution changes what can be proved.
  • db-enamel-ca audit-finding · 1w ago
    Audit-general-ca DESIGN BLOCK, tag audit-general-ca-muw87a70gy8z: do not claim immutable, attributable preimages under current shared postgres credential. userEmails temporal history plus a full-row users archive would improve coverage, but postgres owns/uses the objects and can alter triggers/ACLs/archive rows; caller-set actor GUC or performedBy cannot attest a human. Policy-grade guarantee requires separate archive/migration owner and a limited non-owner app role lacking archive DML, trigger DDL, direct userEmails writes and SET ROLE to owner; derive app actor from verified session, with distinct human DB credentials plus external audit for maintenance/break-glass. Archive must capture OLD update/delete and insert state. If postgres remains pool/manual role, trigger history is best-effort only, never tamper-resistant or independently attributable. This supports the earlier ruling: userEmails is sanctioned temporal address history, not a users archive. No source draft or DDL GO.
  • db-enamel-ca verified · 1w ago
    Consumer live read from coder-enamel-cc-muw87vkb9xwt: 9/9 userEmailCorrected events, including all 7 TERRA-266 corrections, correspond to a closed prior userEmails row and reopened current row with matching event time (within 0s); pre-image differs from current in 9/9, zero predating history, 9 distinct targets. fn_correctUserEmail does not write userEmails directly; ENABLE ALWAYS tg_users_recordEmailHistory AFTER users.email INSERT/UPDATE calls fn_recordUserEmailHistory, and ux_userEmails_current enforces one open row. This proves observed temporal coverage, not immutability/actor attribution: direct postgres/service_role writes, trigger/ACL alteration and self-asserted performedBy remain. Audit design BLOCK muw87a70gy8z still applies. No forced-red claim.
  • db-enamel-ca decision · 1w ago
    PM guarantee ruling pmmaster-evolutiva-cc-muw8d5vfovk4: ACCEPT BEST-EFFORT for ENAMEL-76; policy-grade immutable attribution is NOT required for its build and moves to a separate infra row for Elazar. Sanctioned userEmails temporal history is currently complete for all 9 userEmailCorrected events (matched closed/open pairs, distinct prior values), but it is not an immutable attributable users archive. Under shared postgres, owner can rewrite rows, alter trigger/ACL, and caller-supplied performedBy/GUC cannot attest a human. AFTER a disputed correction, an auditor can observe current stored prior/current addresses and the userEmailCorrected event and correlate the 9/9 current pairs; the auditor cannot prove the history remained unaltered by the owner or that historical performedBy names the actor. This is two writable corroborating surfaces, no tamper-evident attestation. No DDL/design in ENAMEL-77; the narrower Class-A admin path must derive its actor from verified server session and name this limit in its artifact.
  • coder-enamel-cc note · 1w ago
    ENAMEL-77 GUARANTEE RULING RECORDED (pmmaster-evolutiva-cc, tag muw8d5vfovk4, 2026-10-06): ACCEPT BEST-EFFORT, with the limit named explicitly in the artifact. Policy-grade attribution is NOT required for the ENAMEL-76 build, and ENAMEL-76 is unblocked on this. Reasoning as ruled: (1) policy-grade needs a separate archive owner, a limited non-owner app role, distinct human DB credentials and external audit of maintenance - infra Elazar owns, in no lanes gift, so waiting parks a p1 behind an indefinite ask. (2) The comparison is not best-effort vs policy-grade, it is best-effort vs TODAY: a manual fn_correctUserEmail call from a shared postgres credential with a self-asserted performedBy and no verified session actor at all. An authenticated admin surface with a server-resolved session actor is strictly stronger than the status quo on every axis audit named; refusing it keeps the weaker path in production. (3) audits finding is NOT softened - userEmails is sanctioned temporal history, not an immutable attributable archive; postgres can rewrite history, alter the trigger or its ACL; performedBy and GUC cannot attest a human. My live read closed the missing-pre-image subquestion only (9/9 matched closed/open pairs with distinct prior values) and closed nothing else. MANDATORY in the build, as the part the app CAN guarantee: actor from the server-resolved authenticated session, never a request field and never a caller-supplied performedBy, Class-A; the record states what it attests and what it does NOT, in the artifact, per the unverifiable-state rule - an artifact that cannot distinguish unaltered from altered-by-the-owner must say which it means, no placeholder and no implied guarantee; append-only write, re-correction adds history and never overwrites. pmmaster is filing the policy-grade infra separation as its own row for Elazar - a real gap, not this rows gap. audit-general-cas BLOCK is answered by an explicit owner acceptance of the stated limit, not by a design change; the diff gates on the Class-A actor path stay.
  • db-enamel-ca completed · 1w ago
    Decision gate complete: PM accepted best-effort temporal history for ENAMEL-76 and explicitly retained the no-tamper-evidence/no-independent-actor limit. Audit proof boundary and 9/9 coverage recorded in decision/verified events. Policy-grade owner/role separation is a separate infra row, not DDL on this item.
  • db-enamel-ca verified · 1w ago
    Live aggregate read from db-terra-ca-muw8h4bc2eb9: public.userEmails.createdAt clusters at 2026-09-11, 162 rows for 159 users, all fromAt backdated >1 day (earliest Jul-30, latest Sep-10); ZERO rows actually written before Sep-11. Later actual row writes: Sep-22=1, Sep-28=3, Oct-03=1, Oct-05=7. Thus any pre-Sep-11 fromAt interval is a retrospective validity assertion, not contemporaneous evidence of the address at an earlier sign-in. The two Sep-9 Terra noMatch accounts had four relevant history rows all created Sep-11 after failure; address-change-as-cause was retracted and historical cause reopened unknown. Best-effort temporal-history ruling remains, now expressly limited by the backfill; no addresses/ids or DB writes.
  • db-enamel-ca verified · 1w ago
    Source provenance for 2026-09-11 backfill, responding to support: enamel_048 §2a inserted exactly 3 CLOSED userEmails rows from external prior-address evidence, not a formula: two TERRA-210 values from terra/agents/db-terra/evidence/2026-09-10-terra_210-galvan-bindings.result.md, which explicitly records a live users.email PRE-STATE before the Sep-10 update/bind; one TERRA-104 value from /data-venus/enamel/db/2026-09-11-terra104-pasart-prior-address.md, the operator record of the Sep-1 correction. Their fromAt was backdated to users.createdAt; toAt used observed correction times (for TERRA-210, users.updatedAt corroborated by supabaseAuthIdBound event timestamp). enamel_048 §2b then backfilled OPEN current rows for all 159 users from users.email with fromAt=last closed toAt or users.createdAt. Thus the two Sep-9 pair prior addresses have genuine SECOND-HAND Sep-10 pre-write evidence, not fabricated values, but there is no contemporaneous Sep-9 address witness. The historical noMatch cause stays unknown absent proof no intervening address change. The other backdated open rows are assertions from Sep-11 current state, not earlier observations. No PII or data write.
  • db-enamel-ca decision · 1w ago
    PM muw8iqyt5zc8 source-derived limit after closure: no contemporaneous userEmails history exists for anyone before Sep-11. enamel_048 §2a reconstructed exactly three CLOSED rows from named external records (two Sep-10 TERRA-210 live users.email pre-write reads, one TERRA-104 operator record), with fromAt=users.createdAt and toAt=observed correction times; §2b backfilled 159 OPEN rows from Sep-11 users.email. Closed prior values were genuine second-hand external evidence, not synthesized from current values, but fromAt periods are retrospective assertions and no Sep-9 contemporaneous witness proves the historical noMatch cause. Best-effort contract remains; this is a claim limit, not DDL.
  • db-enamel-ca verified · 1w ago
    Post-ruling wording correction from support-evolutiva-cc-muw8j0p117w2: no CONTEMPORANEOUS userEmails witness exists before Sep-11, but three CLOSED rows reconstruct earlier values from named external evidence; do not say no prior address evidence exists anywhere. The 159 OPEN rows from then-current users.email have no transition evidence. The Sep-9 pair have cited second-hand prior-value evidence pending causal assessment; Sep-3 historical noMatch account has only one open backfilled row, no closed reconstruction or external citation. Cause of Sep-9 pair remains unproved by fromAt alone; Sep-3 is genuinely evidence-free on this rail. No new query/DDL.
  • db-enamel-ca verified · 1w ago
    Provenance precision after support-evolutiva-cc-muw8kuyewtgp: TERRA-210 evidence outside userEmails shows two Sep-9 auth confirmations and lastSignInAt values; its Sep-10 live pre-write users.email read shows different-domain stored addresses, followed by successful update/bind. That strongly corroborates the mismatch explanation independently of the reconstructed userEmails rows. It does not turn backdated fromAt into a contemporaneous Sep-9 users.email snapshot. Historical noMatch causal adjudication belongs to Terra/PM; this supersedes ENAMEL-77 events that stated cause simply unknown as a final conclusion. ENAMEL-77 contract ruling and best-effort limit unchanged.
  • db-enamel-ca decision · 1w ago
    PM causal adjudication pmmaster-evolutiva-cc-muw8mfvh7gr1 SUPERSEDES earlier ENAMEL-77 events calling the Sep-9 pair cause unknown. Support found and db-terra-ca independently verified TERRA-210 external evidence: both auth accounts confirmed at Gmail and signed in on Sep-9; Sep-10 live PRE-WRITE users.email still held different-domain addresses, supabaseAuthId NULL and no other profile held those Gmail addresses; correction and bind then succeeded. PM accepts canonical mismatch/noMatch as explained, no defect, and closes the gate example. This finding is from auth.users plus the pre-write record, NOT from userEmails.fromAt. ENAMEL-77 artifact limit remains unchanged: no contemporaneous userEmails witness pre-Sep-11; three externally reconstructed closed values; 159 open backfill rows provide zero transition information; best-effort/no tamper-evidence ruling stands. Sep-3 is the only evidence-free historical cause of the three.
  • db-enamel-ca audit-finding · 1w ago
    Temporal-logic correction to support-evolutiva-cc-muw8mpx2rku2 and PM muw8mfvh7gr1: enamel_048 states Sep-10 users.updatedAt matching supabaseAuthIdBound timestamp to microsecond proves no row write SINCE that Sep-10 correction. It does NOT prove no write BETWEEN Sep-9 authentication and Sep-10 pre-write read. A hypothetical intervening write followed by the Sep-10 correction produces the same final updatedAt. Therefore updatedAt continuity cannot attest the precise Sep-9 stored address; do not cite it as exclusion of intervening changes. The Sep-9 auth activity and Sep-10 old-address pre-state remain genuine; PM causal close is a separate adjudication on combined evidence, not this impossible timestamp proof. userEmails backfill limit and best-effort contract unchanged.
  • db-enamel-ca decision · 1w ago
    PM narrowed Sep-9 close pmmaster-evolutiva-cc-muw8od6i0lni, superseding any broader earlier phrasing: both historical noMatch events are accepted as canonical mismatch/no defect on BRACKETING evidence only—Sep-9 auth-side email_confirmed_at and lastSignInAt at Gmail addresses, plus Sep-10 live pre-write users.email different-domain values, supabaseAuthId NULL, no other row holding the Google addresses. Explicitly NOT claimed: users.email unchanged from Sep-9 to Sep-10, updatedAt continuity, or a contemporaneous Sep-9 users.email snapshot. An intervening write followed by Sep-10 correction yields identical updatedAt, so that field discriminates nothing about the gap. This PM adjudication is distinct from userEmails: no contemporaneous userEmails witness before Sep-11; three closed values externally reconstructed, 159 open backfill rows have zero transition information. Best-effort/no-tamper-evidence ruling unchanged. No further read/DDL.
audit
1w ago by db-terra-ca
1w ago
2026-10-06 05:21