Tested against: origin/main @ a178aa5b6b0b260d105962c928f07304360b7b30 (fetched 2026-05-20)
Severity: HIGH (silently misnames load-bearing identity records; persists across restart)
CREATE TENANT IF NOT EXISTS <name> silently creates a tenant named 'IF', not <name>. The parser appears to consume IF NOT EXISTS as a tenant name + ignore the trailing tokens. Same parser-bug family as CREATE ROLE IF NOT EXISTS (filed separately).
Reproduction (from audit log on a fresh deployment)
The DDL run during Phase 0 bootstrap was:
CREATE TENANT IF NOT EXISTS mae8 WITH ADMIN admin_user;
The audit log records what actually happened:
seq 5: TenantCreated
tenant_id 2
source: nodedb
detail: "created tenant 'IF' (id tenant:2) with admin 'IF_admin'"
Both artifacts were silently named after 'IF':
- Tenant 2 has internal name
'IF', not 'mae8'
- The auto-created admin user is
'IF_admin', not 'admin_user'
SHOW USERS confirms the phantom IF_admin user. The tenant naming can only be observed by reading the audit log; SHOW TENANTS shows just the tenant_id (the name field is empty due to a separate serialization bug).
Operational impact
For mae8 v2's Phase 0: tenant id=2 is internally named 'IF', not 'mae8'. Every SHOW TENANT USAGE FOR mae8 ... style query will miss this tenant by name. The workaround is to use tenant_id exclusively in SQL and never reference by name — which decouples the application from NodeDB's tenant-naming entirely.
There is no RENAME TENANT DDL to recover, and DROP TENANT 'IF' + CREATE TENANT mae8 would orphan all users on tenant_id=2 (and trip the DROP+CREATE phantom-burn bug too).
Suggested fix
- Add
IF NOT EXISTS to the CREATE TENANT grammar (same pattern as the CREATE ROLE bug). This is a standard PostgreSQL idiom and a common DDL convention.
- Make
CREATE USER ... TENANT '<name>' work alongside TENANT <id> (currently only the numeric ID form works), so admins don't have to look up tenant_id from SHOW TENANTS every time.
- Improve the audit log so an admin can grep for "expected name vs actual name" mismatches — would have caught this immediately.
Context
Caught during mae8 v2 Phase 0 bootstrap (2026-05-20). Full bug catalog: /home/system/rnd/mae8/docs/origin_bugs_2026-05-20.md (this is Bug 14 + Bug 8 from that file).
Tested against:
origin/main @ a178aa5b6b0b260d105962c928f07304360b7b30(fetched 2026-05-20)Severity: HIGH (silently misnames load-bearing identity records; persists across restart)
CREATE TENANT IF NOT EXISTS <name>silently creates a tenant named'IF', not<name>. The parser appears to consumeIF NOT EXISTSas a tenant name + ignore the trailing tokens. Same parser-bug family asCREATE ROLE IF NOT EXISTS(filed separately).Reproduction (from audit log on a fresh deployment)
The DDL run during Phase 0 bootstrap was:
The audit log records what actually happened:
Both artifacts were silently named after
'IF':'IF', not'mae8''IF_admin', not'admin_user'SHOW USERSconfirms the phantomIF_adminuser. The tenant naming can only be observed by reading the audit log;SHOW TENANTSshows just the tenant_id (the name field is empty due to a separate serialization bug).Operational impact
For mae8 v2's Phase 0: tenant id=2 is internally named
'IF', not'mae8'. EverySHOW TENANT USAGE FOR mae8 ...style query will miss this tenant by name. The workaround is to usetenant_idexclusively in SQL and never reference by name — which decouples the application from NodeDB's tenant-naming entirely.There is no
RENAME TENANTDDL to recover, andDROP TENANT 'IF' + CREATE TENANT mae8would orphan all users on tenant_id=2 (and trip the DROP+CREATE phantom-burn bug too).Suggested fix
IF NOT EXISTSto the CREATE TENANT grammar (same pattern as the CREATE ROLE bug). This is a standard PostgreSQL idiom and a common DDL convention.CREATE USER ... TENANT '<name>'work alongsideTENANT <id>(currently only the numeric ID form works), so admins don't have to look uptenant_idfromSHOW TENANTSevery time.Context
Caught during mae8 v2 Phase 0 bootstrap (2026-05-20). Full bug catalog:
/home/system/rnd/mae8/docs/origin_bugs_2026-05-20.md(this is Bug 14 + Bug 8 from that file).