Delete can terminate the system tenant
Table of Contents
This page is a capture in the inbox bucket of the product backlog — a pre-sprint idea, not yet pulled into a sprint as a story.
1. What
The generic entity delete can terminate the system tenant. Every dedicated lifecycle function refuses that explicitly; the delete rule the generic path actually uses does not.
2. Why
Found on 2026-09-23 while documenting User Journey: Retire or reset a tenant.
The system tenant holds the shared reference data and the system administration for the whole installation, so terminating it is close to unrecoverable.
Evidence:
- Every dedicated function refuses it and demands system context.
projects/ores.sql/create/iam/iam_tenant_terminator_create.sql:51raises "Cannot terminate the system tenant" when the id is the system tenant, and line 56 raises unless the caller is in system tenant context.iam_tenant_deprovisioner_create.sql:65and :70 do the same, and the purger follows the same shape. The generic path does not go through them. The generated entity delete issues a plain
DELETEonores_iam_tenants_tbl, andprojects/ores.sql/create/iam/iam_tenants_create.sql:150-157is the rule that catches it:create or replace rule ores_iam_tenants_delete_rule as on delete to "ores_iam_tenants_tbl" do instead ( update "ores_iam_tenants_tbl" set valid_to = clock_timestamp(), status = 'terminated' where id = OLD.id and valid_to = ores_utility_infinity_timestamp_fn(); );
No system-tenant guard, and no system-context check.
iam.v1.tenants.deletereaches that rule and checks onlyiam::tenants:delete. The dedicatediam::tenants:terminatepermission is seeded and held bySuperAdmin, but no operation uses it.
So the guard exists, but in the wrong place: inside the functions the generic path does not call.
The fix is to add the same guard to the delete rule — refuse when OLD.id is
ores_utility_system_tenant_id_fn(). The check constraint at line 60
(id <> max_uuid or code = 'system') is a consistency rule about the row, not a
deletion guard, and does not prevent this.
3. References
projects/ores.sql/create/iam/iam_tenants_create.sql:150-157— the unguarded delete rule.projects/ores.sql/create/iam/iam_tenant_terminator_create.sql:51-57— the guard that exists elsewhere.projects/ores.sql/create/iam/iam_tenant_deprovisioner_create.sql:65-71— the same guard.