basquetWi + New ticket
enamel ENAMEL-56

Historia clinica ships behind a gate no identity can pass: zero admin:enamel grants exist fleet-wide

Done normal cecoder02-enamel-cc

MECHANISM (confirmed live 2026-09-12): the first admin:enamel grant is a plain data INSERT into "userGroups", never DDL and never a Postgres GRANT. The app's own grantGroup path (usuarios/actions.ts) cannot create it because that INSERT is itself gated on ADMIN_OF_ROW(appKey) - granting admin on enamel requires already holding admin on enamel. Zero admin:enamel rows exist (confirmed live just now), so this is a bootstrap circularity, not a bug: no in-app action can produce enamel's first admin. EXACT INSERT (mirrors grantGroup's own statement, usuarios/actions.ts:660-676), run out-of-band, once: insert into "userGroups" ("userId", "groupId", "appKey", "grantedBy") values ('<ELAZAR_PICKS_ONE_OF_THE_TWO_ROW_IDS_BELOW>', 'd2a96c96-4176-4cff-be36-7ff9acae51d6', 'enamel', '<same row id, self-granted, or another admin row id>'); Columns, confirmed live: - userId: the users.id row that should hold the grant. MUST be a BOUND row (supabaseAuthId is not null) or the grant is invisible - an unbound row still cannot sign in even after granting (project_enamel_grant_and_identity_model.md). - groupId: fixed value d2a96c96-4176-4cff-be36-7ff9acae51d6 (groups.value='admin', isActive=true, confirmed live) - not a lookup Elazar has to do, already resolved here. - appKey: literal 'enamel'. - grantedBy: any users.id (bound or not - it is attribution only, not gated). THE ONLY OPEN QUESTION, and it is a WHO not a HOW: which bound row gets it. Live query just re-confirmed exactly two Elazar rows are bound and are the plausible admin: 8157954d-7a79-48c2-a67b-87a37970d688 (elazar.pimentel@pensanta.com, already holds admin:terra) and 4ce4ed1e-2de5-450a-b582-2e4d3ec20dd2 (elazar.pimentel@gmail.com, holds alumno:terra). No other bound row in the users table is a plausible enamel admin candidate. Elazar's answer needed is ONE of: (a) 8157954d-... (institutional, matches his existing admin:terra pattern), (b) 4ce4ed1e-... (gmail), or (c) a different bound row entirely if he wants a distinct enamel-only identity. Once he names the row id, the INSERT above is a single out-of-band statement - not app code, not a migration, not a widened gate. Not self-granted by any enamel agent per standing instruction.

Sub-tickets

No sub-tickets.
+ Add sub-ticket

Activity

  • wi-cli-venus created · 5w ago
  • wi-cli-venus assigned · 5w ago
    coder02-enamel-cc
  • wi-cli-venus statusChanged · 5w ago
  • wi-cli-venus blocked · 5w ago
    Answered: it is a plain userGroups INSERT (data, not DDL, not a Postgres GRANT) - enamel_029's own header states it explicitly: 'creating the first enamel admin grant is Elazar's call, not a DB or app decision,' filed there 2026-08-10 when the same zero-admin state was first measured. The app's own grantGroup action cannot bootstrap it: grantGroup is ADMIN_OF_ROW('enamel')-gated, so creating the first admin:enamel grant through the UI requires an existing admin:enamel, which is circular. enamel_029's guard (>=1 live admin after any mutation) only blocks the transition TO zero - it never blocked FROM zero, so it has been sitting vacuously true since 2026-08-10, 33 days, unnoticed until ENAMEL-24 made it visible as a rendered blank screen instead of an absent feature. Per project_enamel_grant_and_identity_model.md, the grant must land on a BOUND users row (unbound = invisible even after granting), so the open question is WHO, which is a client identity decision, not a mechanism question - mechanism is answered. No DDL/grant needed from db-enamel-cc; the write itself (one INSERT into userGroups) needs whoever has DB write reach to execute it once Elazar names the row. Not widening the gate, not self-granting, not granting a test identity - routing the WHO decision to Elazar.
  • wi-cli-venus descriptionChanged · 5w ago
    was: ENAMEL-24 shipped at d21720b gated on admin:enamel specifically rather than ADMIN_OF_ANY, which is the correct gate. Measured by coder02-enamel-cc in the same breath: zero admin:enamel grants exist, so /historia-clinica and /historia-clinica/[id] render empty for every identity that exists today. The surface is shipped, tested (21 whitebox tests, 279 total, tsc clean) and unreachable. This is not a defect in ENAMEL-24 and must not be fixed by widening the gate - relaxing an auth gate to make a page render is a security regression, and ADMIN_OF_ANY is exactly the cross-tenant read the keyed-lookup design was built to avoid. The open question is WHO holds admin:enamel and by what path it is granted, which nobody has answered. First action is to establish where that grant lives: if it is an app-side group/role value on users or appKeys, it is a coder question; if issuing it is DDL or a database grant, it stops here and goes to db-enamel-cc. Do not issue a grant to yourself or to a test identity to make the page render - that manufactures the very reachability the acceptance is supposed to prove. Related: ENAMEL-50 (create-flow blocked on ENAMEL-34), ENAMEL-28 (shared support tables have no DB-side access control at all), ENAMEL-19. Until this is answered, treat every ENAMEL-24 coverage claim as what coder02-enamel-cc already said plainly: trigger firing, gate filtering a real row, and any live admin:enamel identity are all NOT exercised, and pacientes is 0 rows fleet-wide.
  • wi-cli-venus note · 3w ago
    First enamel admin granted per Elazar CLI 2026-09-22: userGroups dd1edea1, user 8157954d, admin, appKey=enamel. enamel_069, pushed 1627dbe, audit PASS audit-general-cc-mucydxga9h51.
  • wi-cli-venus unblocked · 3w ago
    cleared: Answered: it is a plain userGroups INSERT (data, not DDL, not a Postgres GRANT) - enamel_029's own header states it explicitly: 'creating the first enamel admin grant is Elazar's call, not a DB or app decision,' filed there 2026-08-10 when the same zero-admin state was first measured. The app's own grantGroup action cannot bootstrap it: grantGroup is ADMIN_OF_ROW('enamel')-gated, so creating the first admin:enamel grant through the UI requires an existing admin:enamel, which is circular. enamel_029's guard (>=1 live admin after any mutation) only blocks the transition TO zero - it never blocked FROM zero, so it has been sitting vacuously true since 2026-08-10, 33 days, unnoticed until ENAMEL-24 made it visible as a rendered blank screen instead of an absent feature. Per project_enamel_grant_and_identity_model.md, the grant must land on a BOUND users row (unbound = invisible even after granting), so the open question is WHO, which is a client identity decision, not a mechanism question - mechanism is answered. No DDL/grant needed from db-enamel-cc; the write itself (one INSERT into userGroups) needs whoever has DB write reach to execute it once Elazar names the row. Not widening the gate, not self-granting, not granting a test identity - routing the WHO decision to Elazar.
  • wi-cli-venus completed · 3w ago
    8157954d admin grant live (enamel_069, 1627dbe)
bug
5w ago by wi-cli-venus
3w ago
2026-09-22 17:34