TenantAtlas/specs/101-golden-master-baseline-governance-v1/data-model.md
ahmido a30be84084 Baseline governance UX polish + view Infolist (#123)
Summary:
- Baseline Compare landing: enterprise UI (stats grid, critical drift banner, better actions), navigation grouping under Governance, and Action Surface Contract declaration.
- Baseline Profile view page: switches from disabled form fields to proper Infolist entries for a clean read-only view.
- Fixes tenant name column usages (`display_name` → `name`) in baseline assignment flows.
- Dashboard: improved baseline governance widget with severity breakdown + last compared.

Notes:
- Filament v5 / Livewire v4 compatible.
- Destructive actions remain confirmed (`->requiresConfirmation()`).

Tests:
- `vendor/bin/sail artisan test --compact tests/Feature/Baselines`
- `vendor/bin/sail artisan test --compact tests/Feature/Guards/ActionSurfaceContractTest.php`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #123
2026-02-19 23:56:09 +00:00

143 lines
5.1 KiB
Markdown

# Phase 1 — Data Model
This is the proposed data model for **101 — Golden Master / Baseline Governance v1**.
## Ownership Model
- **Workspace-owned**
- Baseline profiles
- Baseline snapshots + snapshot items (data-minimized, reusable across tenants)
- **Tenant-owned**
- Tenant assignments (joins a tenant to the workspace baseline standard)
- Operation runs for capture/compare
- Findings produced by compares
This follows constitution SCOPE-001 conventions: tenant-owned tables include `workspace_id` + `tenant_id` NOT NULL; workspace-owned tables include `workspace_id` and do not include `tenant_id`.
## Entities
## 1) baseline_profiles (workspace-owned)
**Purpose**: Defines the baseline (“what good looks like”) and its scope.
**Fields**
- `id` (pk)
- `workspace_id` (fk workspaces, NOT NULL)
- `name` (string, NOT NULL)
- `description` (text, nullable)
- `version_label` (string, nullable)
- `status` (string enum: `draft|active|archived`, NOT NULL)
- `scope_jsonb` (jsonb, NOT NULL)
- v1 schema: `{ "policy_types": ["string", ...] }` — array of policy type keys from `InventoryPolicyTypeMeta`
- An empty array means "all types" (no filtering); each string must be a known policy type key
- Future versions may add additional filter dimensions (e.g., `platforms`, `tags`)
- `active_snapshot_id` (fk baseline_snapshots, nullable)
- `created_by_user_id` (fk users, nullable)
- timestamps
**Indexes/constraints**
- index: `(workspace_id, status)`
- uniqueness: `(workspace_id, name)` (optional but recommended if UI expects names unique per workspace)
**Validation notes**
- status transitions: `draft ↔ active → archived` (archived is terminal in v1; deactivate returns active → draft)
## 2) baseline_snapshots (workspace-owned)
**Purpose**: Immutable baseline snapshot captured from a tenant.
**Fields**
- `id` (pk)
- `workspace_id` (fk workspaces, NOT NULL)
- `baseline_profile_id` (fk baseline_profiles, NOT NULL)
- `snapshot_identity_hash` (string(64), NOT NULL)
- sha256 of normalized captured content
- `captured_at` (timestamp tz, NOT NULL)
- `summary_jsonb` (jsonb, nullable)
- counts/metadata (e.g., total items)
- timestamps
**Indexes/constraints**
- unique: `(workspace_id, baseline_profile_id, snapshot_identity_hash)` (dedupe)
- index: `(workspace_id, baseline_profile_id, captured_at desc)`
## 3) baseline_snapshot_items (workspace-owned)
**Purpose**: Immutable items within a snapshot.
**Fields**
- `id` (pk)
- `baseline_snapshot_id` (fk baseline_snapshots, NOT NULL)
- `subject_type` (string, NOT NULL) — e.g. `policy`
- `subject_external_id` (string, NOT NULL) — stable key for the policy within the tenant inventory
- `policy_type` (string, NOT NULL) — for filtering and summary
- `baseline_hash` (string(64), NOT NULL) — stable content hash for the baseline version
- `meta_jsonb` (jsonb, nullable) — minimized display metadata (no secrets)
- timestamps
**Indexes/constraints**
- unique: `(baseline_snapshot_id, subject_type, subject_external_id)`
- index: `(baseline_snapshot_id, policy_type)`
## 4) baseline_tenant_assignments (tenant-owned)
**Purpose**: Assigns exactly one baseline profile per tenant (v1), with optional scope override that can only narrow.
**Fields**
- `id` (pk)
- `workspace_id` (fk workspaces, NOT NULL)
- `tenant_id` (fk tenants, NOT NULL)
- `baseline_profile_id` (fk baseline_profiles, NOT NULL)
- `override_scope_jsonb` (jsonb, nullable)
- `assigned_by_user_id` (fk users, nullable)
- timestamps
**Indexes/constraints**
- unique: `(workspace_id, tenant_id)`
- index: `(workspace_id, baseline_profile_id)`
**Validation notes**
- Override must be subset of profile scope (enforced server-side; store the final effective scope hash in the compare run context for traceability).
## 5) findings additions (tenant-owned)
**Purpose**: Persist baseline compare drift findings using existing findings system.
**Required v1 additions**
- add `findings.source` (string, **nullable**, default `NULL`)
- baseline compare uses `source='baseline.compare'`
- existing findings receive `NULL`; legacy drift-generate findings are queried with `whereNull('source')` or unconditionally
- index: `(tenant_id, source)`
**Baseline compare finding conventions**
- `finding_type = 'drift'`
- `scope_key = 'baseline_profile:<id>'`
- `fingerprint = sha256(tenant_id|scope_key|subject_type|subject_external_id|change_type|baseline_hash|current_hash)` (using `DriftHasher`)
- `evidence_jsonb` includes:
- `source` (until DB column exists)
- `baseline.profile_id`, `baseline.snapshot_id`
- `baseline.hash`, `current.hash`
- `change_type` (missing_policy|different_version|unexpected_policy)
- any minimized diff pointers required for UI
## 6) operation_runs conventions
**Operation types**
- `baseline_capture`
- `baseline_compare`
**Run context** (json)
- capture:
- `baseline_profile_id`
- `source_tenant_id`
- `effective_scope` / `selection_hash`
- compare:
- `baseline_profile_id`
- `baseline_snapshot_id` (frozen at enqueue time)
- `effective_scope` / `selection_hash`
**Summary counts**
- compare should set a compact breakdown for dashboards:
- totals and severity breakdowns