TenantAtlas/specs/114-system-console-control-tower/data-model.md
ahmido 0cf612826f feat(114): system console control tower (merged) (#139)
Feature branch PR for Spec 114.

This branch contains the merged agent session work (see merge commit on branch).

Tests
- `vendor/bin/sail artisan test --compact tests/Feature/System/Spec114/`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #139
2026-02-28 00:15:31 +00:00

86 lines
3.7 KiB
Markdown

# Phase 1 — Data Model (Spec 114: System Console Control Tower)
This feature is primarily **read-only UI** over existing platform/ops metadata.
## Entities (existing)
### Workspace (`workspaces`)
- Purpose: group tenants; scope boundary for tenant plane.
- Relevant fields: `id`, `name`, `slug`, timestamps.
- Relationships:
- `Workspace::tenants()`
- `Workspace::memberships()`
### Tenant (`tenants`)
- Purpose: customer tenant inventory + onboarding/health metadata.
- Relevant fields (high level):
- `id`, `external_id`, `name`, `workspace_id`, `status`, `environment`
- RBAC signals: `rbac_last_checked_at`, `rbac_last_setup_at`, `rbac_canary_results`, `rbac_last_warnings`
- `metadata` (array)
- Relationships:
- `Tenant::providerConnections()``provider_connections`
- `Tenant::permissions()``tenant_permissions`
- `Tenant::auditLogs()``audit_logs`
### ProviderConnection (`provider_connections`)
- Purpose: connectivity + health-check metadata for external provider.
- Relevant fields: `provider`, `is_default`, `scopes_granted`, `last_health_check_at`, `metadata`.
### TenantPermission (`tenant_permissions`)
- Purpose: cached/recorded permission checks.
- Relevant fields: `key` (permission name), `status`, `details`, `last_checked_at`.
### OperationRun (`operation_runs`)
- Purpose: canonical operations observability record (non-negotiable per constitution).
- Relevant fields:
- identity/scope: `workspace_id` (NOT NULL), `tenant_id` (nullable), `user_id` (nullable), `initiator_name`
- lifecycle: `type`, `status` (`queued|running|completed`), `outcome` (`pending|succeeded|failed|canceled|…`)
- audit UX: `summary_counts` (numeric-only keys), `failure_summary` (sanitized bounded array), `context` (sanitized/limited)
- timing: `created_at`, `started_at`, `completed_at`
### AuditLog (`audit_logs`)
- Purpose: security/audit trail.
- Relevant fields: `workspace_id`, `tenant_id` (nullable), `actor_*`, `action`, `status`, `metadata` (sanitized), `recorded_at`.
- System console relevant actions (already emitted):
- `platform.auth.login`
- `platform.break_glass.enter|exit|expired`
## Derived/Computed concepts (new, no new table)
### Time window
- Enumerated: `1h`, `24h` (default), `7d`.
- Used for Control Tower and for failures/stuck scoping.
### “Stuck” run classification
- Definition: a run is “stuck” when:
- `status=queued` and `created_at <= now() - queued_threshold_minutes` AND `started_at IS NULL`, OR
- `status=running` and `started_at <= now() - running_threshold_minutes`
- Thresholds are configurable (v1):
- `system_console.stuck_thresholds.queued_minutes`
- `system_console.stuck_thresholds.running_minutes`
### Tenant/workspace health badge
- “Worst wins” aggregation over signals:
- Tenant status (active/onboarding/archived)
- Provider connection health/status
- Permission status
- Recent failed/stuck runs within the time window
- Display-only; does not mutate state.
## Validation rules
- Any operator-provided reason/note (break-glass, mark investigated): min length 5, max length 500.
- Filters: only allow known enum values (time window, run status/outcome).
## Storage/indexing plan (Phase 2 tasks will implement)
- `operation_runs`:
- Indexes to support windowed queries and grouping:
- `(workspace_id, created_at)`
- `(tenant_id, created_at)`
- optional: `(status, outcome, created_at)` and `(type, created_at)` depending on explain plans
- `audit_logs`:
- `(action, recorded_at)` and `(actor_id, recorded_at)` for Access Logs filters
## Notes on data minimization
- Use `RunFailureSanitizer` + `SummaryCountsNormalizer` contracts.
- Avoid rendering raw `context` by default; when displayed, cap size and redact sensitive keys.