TenantAtlas/specs/241-support-diagnostic-pack/data-model.md
ahmido 17d3ca8313
Some checks failed
Main Confidence / confidence (push) Failing after 45s
feat(support-diagnostics): guardrail refactor and UI polish (agent) (#278)
Implements support diagnostics bundle, moves audit writes to action mountUsing to avoid side-effects during render, replaces custom slide-over with Filament-native schema, updates tests and adds spec docs.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #278
2026-04-25 23:32:30 +00:00

294 lines
8.5 KiB
Markdown

# Data Model — Support Diagnostic Pack
**Spec**: [spec.md](spec.md)
No new persistent tables are required for the first support-diagnostics slice. The bundle is computed at request time from existing canonical records.
## Existing Canonical Entities Reused
### Workspace (`workspaces`)
**Purpose**: Primary admin-plane isolation boundary and audit scope for every support-diagnostic bundle.
**Key fields (existing)**:
- `id`
- `name`
**Bundle use**:
- Supplies the workspace scope label.
- Anchors workspace-membership checks.
- Owns audit-log scope for bundle-open activity.
### Tenant (`tenants`)
**Purpose**: Tenant-plane scope boundary and the canonical subject for tenant-context support diagnostics.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `external_id`
- `name`
- `status`
**Bundle use**:
- Acts as the primary subject for tenant-context bundles.
- Supplies tenant identity and tenant authorization scope.
### OperationRun (`operation_runs`)
**Purpose**: Canonical execution truth and the primary subject for operation-context support diagnostics.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id` (nullable)
- `type`
- `status`
- `outcome`
- `summary_counts`
- `context`
- `started_at`
- `completed_at`
**Relationships (existing)**:
- `tenant()`
- `workspace()`
- `user()`
**Bundle use**:
- Supplies the primary execution summary.
- Carries run-bound reference ids such as `provider_connection_id` and artifact references in `context`.
- Reuses existing humanized run explanation and canonical run URLs.
### ProviderConnection (`provider_connections`)
**Purpose**: Canonical provider readiness and connection state for the tenant or run context.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id`
- `provider`
- `connection_type`
- `consent_status`
- `verification_status`
- `last_error_reason_code`
- `last_error_message`
- `is_default`
- `is_enabled`
- `last_health_check_at`
**Relationships (existing)**:
- `tenant()`
- `workspace()`
- `credential()`
**Bundle use**:
- Supplies provider readiness summary, translated provider failure reasons, and target-scope detail.
- Never contributes raw credential payloads or secrets to the bundle.
### Finding (`findings`)
**Purpose**: Canonical drift or permission posture issues that may explain current support pressure.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id`
- `type`
- `severity`
- `status`
- `baseline_operation_run_id`
- `current_operation_run_id`
- `due_at`
- `last_seen_at`
**Relationships (existing)**:
- `tenant()`
- `baselineRun()`
- `currentRun()`
- `findingException()`
**Bundle use**:
- Supplies prioritized open or recent findings relevant to the current tenant or run.
- Contributes summary and freshness cues only; finding detail remains on canonical pages.
### StoredReport (`stored_reports`)
**Purpose**: Canonical report/evidence truth for report identity and freshness.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id`
- `report_type`
- `fingerprint`
- `previous_fingerprint`
- `payload`
**Relationships (existing)**:
- `workspace()`
- `tenant()`
**Bundle use**:
- Supplies report identity, report type, and freshness/continuity cues.
- The bundle must not expose the full stored report payload by default.
### TenantReview (`tenant_reviews`)
**Purpose**: Canonical tenant review state and review-level summary for governance follow-up.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id`
- `operation_run_id`
- `status`
- `completeness_state`
- `summary`
- `generated_at`
- `current_export_review_pack_id`
**Relationships (existing)**:
- `workspace()`
- `tenant()`
- `operationRun()`
- `reviewPacks()`
**Bundle use**:
- Supplies current review status, completeness, blockers, and canonical review references when review truth is relevant.
### ReviewPack (`review_packs`)
**Purpose**: Canonical review export/package truth when a tenant review already has a pack.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id`
- `operation_run_id`
- `tenant_review_id`
- `status`
- `summary`
- `generated_at`
- `expires_at`
- `file_size`
**Relationships (existing)**:
- `workspace()`
- `tenant()`
- `operationRun()`
- `tenantReview()`
**Bundle use**:
- Supplies pack availability, readiness, and expiry cues.
- The bundle links to the canonical pack viewer instead of reproducing pack content.
### AuditLog (`audit_logs`)
**Purpose**: Canonical audit trail for workspace-, tenant-, and operation-related events.
**Key fields (existing)**:
- `id`
- `workspace_id`
- `tenant_id`
- `action`
- `resource_type`
- `resource_id`
- `target_label`
- `metadata`
- `outcome`
- `operation_run_id`
- `recorded_at`
**Relationships (existing)**:
- `tenant()`
- `workspace()`
- `operationRun()`
**Bundle use**:
- Supplies the most relevant authorized audit references for the current tenant or run.
- Also records bundle-open activity with redacted metadata only.
## Derived Runtime Entities
### SupportDiagnosticBundle (computed, not persisted)
**Purpose**: One machine-readable, redacted support-safe envelope for either a tenant context or an operation-run context.
**Proposed shape (runtime array / view-model)**:
- `context_type``tenant` or `operation_run`
- `workspace` — workspace reference and label
- `tenant` — tenant reference when applicable
- `operation_run` — primary run reference when applicable
- `headline` — dominant support summary
- `dominant_issue` — translated blocker or issue statement
- `freshness_state` — derived cue such as `fresh`, `stale`, `mixed`, or `missing_context`
- `redaction_mode` — fixed first-slice mode: default-redacted
- `sections` — ordered list of section payloads
- `notes` — explicit redaction, completeness, or degradation notes
**Relationships**:
- 1 workspace
- 0..1 tenant
- 0..1 primary operation run
- 0..1 provider connection section
- 0..n finding references
- 0..n stored report references
- 0..1 tenant review reference
- 0..1 review pack reference
- 0..n audit references
### SupportDiagnosticSection (computed, not persisted)
**Purpose**: One deterministic section inside the bundle.
**Proposed shape**:
- `key` — fixed section key such as `provider_connection`, `operation_context`, `findings`, `stored_reports`, `tenant_review`, `review_pack`, `audit_history`
- `label`
- `availability` — derived local status (`available`, `missing`, `stale`, `inaccessible`, `redacted`)
- `summary`
- `freshness_at` or `freshness_note`
- `references` — ordered support references for that section
- `redaction_markers` — explicit markers when detail is intentionally excluded
**Note**: these are presentation-contract values only, not new persisted domain state.
### SupportDiagnosticReference (computed, not persisted)
**Purpose**: Stable canonical link/reference metadata for one related record.
**Proposed shape**:
- `type``tenant`, `operation_run`, `provider_connection`, `finding`, `stored_report`, `tenant_review`, `review_pack`, or `audit_log`
- `record_id`
- `label`
- `action_label`
- `url` (nullable when inaccessible or no viewer exists)
- `availability`
- `freshness_note` (nullable)
- `access_reason` or `missing_reason` (nullable)
### RedactionMarker (computed, not persisted)
**Purpose**: Make exclusion deterministic and explicit.
**Proposed shape**:
- `path` (nullable)
- `reason``secret`, `credential`, `raw_payload`, `restricted_log_excerpt`, or `inaccessible_record`
- `replacement_text`
## Derived Rules and Validation
- Bundle generation requires established workspace membership first.
- Tenant-context bundle generation requires tenant entitlement before any tenant-owned section resolves.
- Operation-context bundle generation must first pass `OperationRunPolicy::view(...)`; if the run points at a tenant, tenant entitlement still applies before tenant-owned related records resolve.
- After membership/entitlement is established, missing `support_diagnostics.view` is a `403` capability denial.
- The bundle must never include secrets, tokens, credentials, unrestricted provider response bodies, or unrestricted stored-report payloads.
- Missing or inaccessible related records must degrade into explicit placeholders or unavailable references, not hard-fail the whole bundle.
- For unchanged authorized input, section order, reference order, and redaction output must remain stable.
## Lifecycle and Audit Behavior
- `SupportDiagnosticBundle` has no persisted lifecycle.
- Opening the bundle writes one audit event with redacted metadata only.
- Opening linked canonical records follows their own existing authorization and audit behavior.