TenantAtlas/specs/067-rbac-troubleshooting/data-model.md

65 lines
2.3 KiB
Markdown

# Data Model — RBAC Troubleshooting & Tenant UI Bugfix Pack v1
**Spec**: [spec.md](spec.md)
No new persistent tables are required for v1. Diagnostics findings are computed at runtime from existing tables.
## Entities
### Tenant (`tenants`)
**Purpose**: Tenant-plane scope boundary, lifecycle state, and tenant-scoped configuration root.
**Key fields (existing)**:
- `id` (bigint, PK)
- `tenant_id` (string GUID, external Microsoft Entra tenant identifier)
- `external_id` (string, used as Filament tenancy slug; often mirrors `tenant_id`)
- `status` (string, e.g. `active`, `archived`)
- `deleted_at` (nullable timestamp, soft delete)
- `name`, `environment`, `is_current`, `metadata` (assorted)
**Lifecycle rules (existing)**:
- Soft delete sets `status='archived'`.
- Restore sets `status='active'`.
### TenantMembership (`tenant_memberships`)
**Purpose**: Tenant membership boundary + role assignment.
**Key fields (existing)**:
- `id` (uuid, PK)
- `tenant_id` (bigint, FK → `tenants.id`)
- `user_id` (bigint, FK → `users.id`)
- `role` (enum: `owner`, `manager`, `operator`, `readonly`)
- `source` / `source_ref` (provenance)
- `created_by_user_id` (nullable FK)
**Constraints (existing)**:
- Unique `(tenant_id, user_id)`
- Index `(tenant_id, role)`
### DiagnosticsFinding (computed, not persisted)
**Purpose**: Represent a detected integrity/operational issue for the current tenant.
**Proposed shape (runtime DTO / array)**:
- `id` (string, stable key like `missing_owner`)
- `severity` (string, e.g. `warning`/`critical`)
- `title` (string)
- `description` (string)
- `repair_actions` (array of available actions given actor capabilities)
## Derived rules / invariants
- **Missing owner**: `tenant_memberships` has zero rows with `role='owner'` for the tenant.
- **Duplicate membership**: more than one membership row exists for a given `(tenant_id, user_id)` (should be prevented by DB uniqueness; diagnostics treats this as “historical/edge-case”).
- **Identifier misuse risk**: any query for membership/tenant scoping must use internal tenant key (`tenants.id`) and not the GUID.
## State transitions
- Tenant status:
- `active``archived` on soft delete
- `archived``active` on restore
- Membership role transitions:
- Allowed transitions are existing (`owner`, `manager`, `operator`, `readonly`) but last-owner demotion/removal is prohibited.