# 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.