TenantAtlas/specs/246-support-request-context/spec.md
ahmido 6e3736a53f
Some checks failed
Main Confidence / confidence (push) Failing after 1m29s
Add in-app support request with context (#285)
## Summary
- add the first in-app support request flow with an immutable `SupportRequest` record, canonical context builder, submission service, and generated internal reference
- expose contextual support-request actions from the tenant dashboard and operation run surfaces, including audit logging and support-safe diagnostic capture rules
- add Pest coverage plus the `specs/246-support-request-context` artifacts for the new support-request slice

## Testing
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/SupportRequests/OperationRunSupportRequestActionTest.php tests/Feature/SupportRequests/SupportRequestAuditTest.php tests/Feature/SupportRequests/SupportRequestAuthorizationTest.php tests/Feature/SupportRequests/TenantSupportRequestActionTest.php tests/Unit/Support/SupportRequests/SupportRequestContextBuilderTest.php tests/Unit/Support/SupportRequests/SupportRequestReferenceTest.php`

## Notes
- this PR supersedes the earlier session-branch PR opened from `246-support-request-context-session-1777289015`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #285
2026-04-27 12:51:39 +00:00

282 lines
35 KiB
Markdown

# Feature Specification: In-App Support Request with Context
**Feature Branch**: `246-support-request-context`
**Created**: 2026-04-27
**Status**: Ready for implementation
**Input**: User description: "Promote the roadmap-fit candidate In-App Support Request with Context as a narrow, implementation-ready slice that adds structured support-request creation from existing support-aware product surfaces. The slice should reuse Support Diagnostic Pack, product knowledge, existing tenant and operation context resolution, and audit patterns to capture one support request with redacted diagnostic references and operator-entered severity/message fields, without building a full helpdesk, ticket sync engine, or CRM workflow."
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
- **Problem**: Generic support email or an external ticket link discards the most important product context at the moment help is requested: workspace, tenant, current run, related findings, recent reports, review artifacts, and the current diagnostic state.
- **Today's failure**: Operators must manually copy context from several product surfaces into an ad hoc support note, which creates avoidable back-and-forth, invites oversharing of raw diagnostics, and leaves no reliable internal support reference inside TenantPilot.
- **User-visible improvement**: A tenant-scoped or run-scoped operator can submit one structured support request from the current product surface, capture severity plus summary and note fields, attach safe context automatically, and immediately receive an internal support reference.
- **Smallest enterprise-capable version**: Add one immutable internal `SupportRequest` record with a generated reference, two first-slice entry actions on existing tenant and run surfaces, automatic canonical context attachment, optional redacted support-diagnostic snapshot attachment when the creator is allowed to view it, and audit logging for request creation.
- **Explicit non-goals**: No full helpdesk product, no support inbox or triage board, no two-way ticket sync, no SLA engine, no file-upload pipeline, no customer-facing portal, no AI support bot, no background notification workflow, and no external ticket provider coupling in v1.
- **Permanent complexity imported**: One new persisted `SupportRequest` truth, one small support-request severity family, one bounded context-builder path, one generated internal reference format, one new tenant capability, two read-only context-aware create actions, and focused unit plus feature coverage.
- **Why now**: The repo already has the support-diagnostics bundle, contextual help, tenant and run context resolution, and audit seams. This is the narrowest next slice that turns those support foundations into structured intake instead of leaving support creation as manual copy-paste.
- **Why not local**: A page-local note field, mailto link, or generic modal would still duplicate context assembly, drift redaction behavior, and lose canonical references. The support request needs one reusable capture contract because both tenant and run surfaces already depend on the same support truth.
- **Approval class**: Workflow Compression
- **Red flags triggered**: New persistence, new severity semantics, and multi-surface workflow touchpoint. Defense: the slice stores one immutable request record only, avoids status workflow or external sync, and is limited to two already support-aware surfaces that can reuse the existing diagnostic bundle.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 1 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 10/12**
- **Decision**: approve
## Spec Scope Fields *(mandatory)*
- **Scope**: workspace, tenant
- **Primary Routes**:
- `/admin/t/{tenant}` existing tenant dashboard as the first tenant-context support-request entry point
- `/admin/operations/{run}` existing canonical operation detail surface as the first run-context support-request entry point
- **Data Ownership**: `support_requests` becomes new tenant-owned product truth with required `workspace_id` and `tenant_id`, both stored as not-null fields. `workspace_id` is still derived from the tenant relationship for correctness, but it remains persisted because tenant-owned truth in this repo carries both anchors. Canonical source truth for attached references remains on existing `Tenant`, `OperationRun`, `ProviderConnection`, `Finding`, `StoredReport`, `TenantReview`, `ReviewPack`, and `AuditLog` records. Any attached support-diagnostic snapshot is a redacted immutable capture owned by the support request, not a replacement for those source records.
- **RBAC**: Workspace membership and tenant entitlement remain mandatory. A new tenant-role capability `support_requests.create` gates request creation. When a request includes the redacted support-diagnostic snapshot, the creator must also pass the existing `support_diagnostics.view` check; otherwise the request stores only the safe canonical context reference set and an explicit note that diagnostic evidence was omitted.
For canonical-view specs, the spec MUST define:
- **Default filter behavior when tenant-context is active**: N/A - the first slice adds contextual create actions only and does not introduce a support-request registry page.
- **Explicit entitlement checks preventing cross-tenant leakage**: Non-members and non-entitled users receive 404 semantics before any tenant-owned context is assembled. The operation entry point is in scope only when the run resolves to an entitled tenant.
## Cross-Cutting / Shared Pattern Reuse *(mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write `N/A - no shared interaction family touched`)*
- **Cross-cutting feature?**: yes
- **Interaction class(es)**: header actions, contextual support capture, success notifications, support-safe context summaries, audit events
- **Systems touched**: existing tenant dashboard and canonical operation detail action surfaces, the support-diagnostics bundle builder, contextual-help content, tenant capability mapping, and workspace audit logging
- **Existing pattern(s) to extend**: existing support-diagnostics entry points, existing Filament header action patterns, existing support-diagnostics redaction rules, and existing audit logging conventions
- **Shared contract / presenter / builder / renderer to reuse**: `SupportDiagnosticBundleBuilder`, `WorkspaceAuditLogger`, existing contextual-help resolver or catalog patterns where copy is needed, and existing support-safe route and label vocabulary already used on tenant and run surfaces
- **Why the existing shared path is sufficient or insufficient**: The current shared support paths already produce deterministic, redacted context and the right canonical references. They are insufficient because the product still lacks a persisted support-request truth and a structured create flow that can capture that context safely.
- **Allowed deviation and why**: One bounded `SupportRequests` support namespace is allowed to assemble immutable request context and generate an internal support reference. No generic ticket adapter, no local page-only context mappers, and no second support-summary dialect are allowed.
- **Consistency impact**: `Request support`, `Support reference`, redaction wording, severity labels, and attached-context copy must remain consistent across tenant and run entry points so the same support concept is visible regardless of where the request originates.
- **Review focus**: Reviewers must verify that context capture reuses the shared support-diagnostics bundle rather than rebuilding record selection locally, and that no raw provider payloads or unrestricted diagnostics are persisted in the request.
## OperationRun UX Impact *(mandatory when the feature creates, queues, deduplicates, resumes, blocks, completes, or deep-links to an `OperationRun`; otherwise write `N/A - no OperationRun start or link semantics touched`)*
- **Touches OperationRun start/completion/link UX?**: no
- **Shared OperationRun UX contract/layer reused**: N/A
- **Delegated start/completion UX behaviors**: N/A
- **Local surface-owned behavior that remains**: The run-context request action reads the current run as context only; it does not queue, resume, or complete any `OperationRun`.
- **Queued DB-notification policy**: N/A
- **Terminal notification path**: N/A
- **Exception required?**: none
## Provider Boundary / Platform Core Check *(mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write `N/A - no shared provider/platform boundary touched`)*
- **Shared provider/platform boundary touched?**: yes
- **Boundary classification**: mixed
- **Seams affected**: provider-connection health excerpts that may appear inside an attached redacted support-diagnostic snapshot, provider-owned reason translation, and support-request context labels
- **Neutral platform terms preserved or introduced**: support request, support reference, primary context, attached context, redacted diagnostic snapshot, canonical reference set
- **Provider-specific semantics retained and why**: Microsoft-specific provider errors or consent states remain provider-owned diagnostic inputs and may only appear through the already redacted support-diagnostics bundle.
- **Why this does not deepen provider coupling accidentally**: The new request record stores provider-neutral context metadata plus canonical references. Provider-specific semantics enter only through the existing support-diagnostics bundle, which is already bounded and redacted.
- **Follow-up path**: Later PSA or ticketing integration remains a separate follow-up spec and must consume the neutral support-request truth instead of reshaping it.
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed; otherwise write `N/A`)*
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|---|---|---|---|---|---|---|
| Tenant dashboard request support action | yes | Native Filament + shared support primitives | header actions, support capture, support diagnostics | page, action, form | yes | Existing tenant dashboard action-surface exemption remains; this slice adds one bounded create action beside the current support-diagnostics action |
| Canonical operation detail request support action | yes | Native Filament + shared support primitives | header actions, monitoring-state diagnostics, support capture | detail, action, form | no | Extends an already support-aware operation surface instead of creating a new support page |
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Tenant dashboard request support action | Secondary Context Surface | The operator decides the current tenant issue needs escalation or structured support intake | Tenant identity, context summary, severity selection, message fields, and whether redacted diagnostics will be attached | Redacted support diagnostics and canonical related records remain secondary evidence | Not primary because support creation follows tenant troubleshooting rather than replacing it | Follows tenant troubleshooting and escalation | Eliminates manual copy-paste from provider, run, findings, and audit surfaces |
| Canonical operation detail request support action | Secondary Context Surface | The operator is already inspecting one run and decides support intake should begin from that run context | Run identity, context summary, severity selection, message fields, and whether redacted diagnostics will be attached | Redacted support diagnostics and canonical related records remain secondary evidence | Not primary because the main work is still understanding and acting on the run | Follows monitoring drill-in workflow | Removes ad hoc support notes that would otherwise rebuild run context manually |
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Tenant dashboard request support action | operator-MSP, support-platform | Scope summary, severity, message fields, contact defaults, attachment note, redaction note | Existing support-diagnostics bundle and canonical links | Raw payloads and unrestricted provider diagnostics are never stored here | `Submit support request` | Diagnostic snapshot attachment is omitted unless `support_diagnostics.view` is allowed | The action reuses the shared support-diagnostics bundle summary instead of restating provider or run truth locally |
| Canonical operation detail request support action | operator-MSP, support-platform | Run identity, severity, message fields, contact defaults, attachment note, redaction note | Existing run-context support diagnostics and canonical links | Raw payloads and unrestricted provider diagnostics are never stored here | `Submit support request` | Diagnostic snapshot attachment is omitted unless `support_diagnostics.view` is allowed | The action reuses the shared run-context support summary instead of inventing a second run explanation path |
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Tenant dashboard request support action | Dashboard / Overview / Actions | Tenant support escalation entry point | Submit a structured support request | Explicit header action opens a slide-over or modal form | forbidden | Existing support diagnostics remains a neighboring secondary action | none | `/admin/t/{tenant}` | `/admin/t/{tenant}` | Active workspace, active tenant, and attached-context note | Support request / Support reference | Primary context, required message fields, severity, and redaction note | dashboard_exception - existing tenant dashboard action-surface exemption remains bounded and read-only apart from the create mutation |
| Canonical operation detail request support action | Record / Detail / Actions | Run-centered support escalation entry point | Submit a structured support request from the current run | Existing detail page plus grouped secondary support actions | forbidden | `Open support diagnostics` and `Request support` are grouped together under the detail action group | none | `/admin/operations` | `/admin/operations/{run}` | Workspace context, entitled tenant context, and operation identifier | Support request / Support reference | Primary run context, required summary fields, severity, and redaction note | none |
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Tenant dashboard request support action | Workspace manager or support-capable tenant operator | Submit one tenant-scoped support request with safe context | Dashboard action + contextual form | How do I ask for help on this tenant without manually rebuilding the case? | Tenant label, severity, summary, reproduction-notes field, contact defaults, context-attachment note, redaction note | Full support diagnostics stay on the neighboring support-diagnostics action and canonical linked pages | support-request severity, attachment completeness | TenantPilot only | Submit support request | none |
| Canonical operation detail request support action | Workspace manager or support-capable operator | Submit one run-scoped support request with safe context | Detail action + contextual form | How do I escalate this run with the right context and without copying raw diagnostics? | Operation identifier, severity, summary, reproduction-notes field, contact defaults, context-attachment note, redaction note | Full support diagnostics stay on the neighboring support-diagnostics action and canonical linked pages | support-request severity, attachment completeness | TenantPilot only | Submit support request | none |
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: yes
- **New persisted entity/table/artifact?**: yes
- **New abstraction?**: yes
- **New enum/state/reason family?**: yes - one bounded support-request severity family
- **New cross-domain UI framework/taxonomy?**: no
- **Current operator problem**: The product can already explain support context, but it still cannot capture a structured support request at the moment the operator needs help.
- **Existing structure is insufficient because**: Support diagnostics is read-only and generic support channels lose context. Without a persisted request record, there is no internal support reference or safe immutable request payload.
- **Narrowest correct implementation**: Add one immutable `SupportRequest` truth with a small severity family and one bounded context-builder path that reuses the existing support-diagnostics bundle when allowed.
- **Ownership cost**: One migration, one model and factory, one support-request context builder or submission service, one capability, one audit action, and focused unit plus feature coverage.
- **Alternative intentionally rejected**: Outbound-only ticket adapters and a broader helpdesk workflow were rejected because the repo has no concrete ticket-provider foundation yet and the first release does not need a support queue, lifecycle engine, or external sync.
- **Release truth**: current-release truth
### Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical replacement is preferred over preservation.
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
- **Test purpose / classification**: Unit, Feature
- **Validation lane(s)**: fast-feedback, confidence
- **Why this classification and these lanes are sufficient**: Unit tests can prove internal reference generation, immutable context-shape rules, and redaction-aware attachment behavior. Feature tests can prove tenant and run entry actions, 404 versus 403 boundaries, persisted request creation, and audit logging without browser automation.
- **New or expanded test families**: One focused `SupportRequests` unit family and a small set of tenant plus run feature tests
- **Fixture / helper cost impact**: Moderate. Reuse existing workspace, tenant, run, provider, finding, stored-report, review, audit, and support-diagnostics fixtures. Add one `SupportRequest` factory and keep helpers local to the support-request test namespace.
- **Heavy-family visibility / justification**: none
- **Special surface test profile**: standard-native-filament, monitoring-state-page
- **Standard-native relief or required special coverage**: Ordinary Filament feature coverage is sufficient for the tenant dashboard action. The run-context action must also preserve the canonical monitoring-state-page constraints already used on the existing operation viewer.
- **Reviewer handoff**: Reviewers must confirm that request creation persists only redacted context, never triggers outbound HTTP or a new `OperationRun`, returns the internal support reference in success feedback, and keeps non-member access as 404.
- **Budget / baseline / trend impact**: Low-to-moderate increase in narrow unit plus feature coverage only
- **Escalation needed**: none
- **Active feature PR close-out entry**: Guardrail
- **Planned validation commands**:
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/SupportRequests/SupportRequestContextBuilderTest.php tests/Unit/Support/SupportRequests/SupportRequestReferenceTest.php`
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/SupportRequests/TenantSupportRequestActionTest.php tests/Feature/SupportRequests/OperationRunSupportRequestActionTest.php tests/Feature/SupportRequests/SupportRequestAuthorizationTest.php tests/Feature/SupportRequests/SupportRequestAuditTest.php`
## Support-Request Severity Contract
The first slice uses one fixed severity family and does not infer or automate downstream workflow from it.
| Stored Value | UI Label | Meaning In V1 |
|---|---|---|
| `low` | Low | Question or minor issue; work can continue and no current blocker exists |
| `normal` | Normal | Ordinary support needed; work can continue with friction |
| `high` | High | Time-sensitive issue or material degradation that needs prompt attention |
| `blocking` | Blocking | Current work cannot proceed or access is effectively blocked |
Validation rules for v1:
- Exactly one severity value is required on every support request.
- The action form defaults to `normal` unless the operator selects a different value.
- Severity affects persisted request truth and UI labels only in v1; it does not start a queue, SLA, or notification workflow.
## Internal Support Reference Contract
- Every created support request receives a reference formatted as `SR-<ULID>`.
- The `SR-` prefix is fixed and uppercase in v1.
- The ULID portion is uppercase, generated once at creation time, and remains immutable afterward.
- Success feedback and audit context must show the exact stored value rather than reformatting it locally.
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Submit a tenant-scoped support request with safe context (Priority: P1)
As a workspace manager or support-capable tenant operator, I want to request support from the current tenant surface so I do not have to manually rebuild the case.
**Why this priority**: Tenant-context support intake is the broadest first-response path and benefits immediately from the existing support-diagnostics foundation.
**Independent Test**: Seed a tenant with provider, run, finding, review, report, and audit truth, submit a support request from the tenant dashboard, and verify that the request is persisted with an internal reference and only safe attached context.
**Acceptance Scenarios**:
1. **Given** an entitled operator opens the tenant dashboard for a tenant with current support context, **When** they submit a support request with severity and summary, **Then** the system creates one immutable support request with a generated internal reference, tenant and workspace context, and canonical references to the current case.
2. **Given** the creator also has `support_diagnostics.view`, **When** they submit the tenant-scoped request, **Then** the request stores the redacted support-diagnostics snapshot or reference set instead of requiring manual copy-paste.
3. **Given** the creator lacks `support_diagnostics.view` but still has `support_requests.create`, **When** they submit the request, **Then** the request stores the safe canonical context set only and records that diagnostic evidence was omitted.
---
### User Story 2 - Submit a run-scoped support request from monitoring (Priority: P1)
As an operator already inspecting one run, I want to request support from the canonical run detail surface so the support request starts from the exact failing or degraded run.
**Why this priority**: A large share of support work starts from one run, and the operation viewer already has the right support-aware context and authorization boundaries.
**Independent Test**: Seed a failed or degraded run with related canonical truth, submit a support request from the operation viewer, and verify that the saved request is run-scoped, tenant-safe, and auditable.
**Acceptance Scenarios**:
1. **Given** an entitled operator is viewing a run that resolves to an entitled tenant, **When** they submit a support request from that run surface, **Then** the system persists one immutable support request whose primary context is that run and whose canonical references stay tenant-safe.
2. **Given** the run does not resolve to an entitled tenant for the current user, **When** they try to create a run-scoped support request, **Then** the system responds as not found and does not reveal whether additional support context exists.
---
### User Story 3 - Keep support intake redacted, auditable, and bounded (Priority: P2)
As the product owner, I want the first support-request slice to stay immutable and provider-neutral so it can be trusted and extended later without accidentally becoming a helpdesk framework.
**Why this priority**: Structured intake adds value only if it stays safe, deterministic, and free of premature helpdesk complexity.
**Independent Test**: Verify that repeated request creation uses the same reference format and context-shape rules, that audit entries are written, and that no outbound helpdesk work or `OperationRun` side effects occur.
**Acceptance Scenarios**:
1. **Given** the same authorized tenant or run input and the same creator capability set, **When** a support request is generated, **Then** the attached context shape follows the same deterministic rules every time.
2. **Given** support request creation succeeds, **When** the request is persisted, **Then** an audit entry records the actor, primary context, internal reference, and redaction mode without storing raw provider payloads.
3. **Given** an operator submits the same issue twice, **When** both requests are accepted, **Then** each submission receives its own immutable internal reference because v1 intentionally does not deduplicate or merge requests.
### Edge Cases
- A tenant may have no provider connection, no recent run, or no active findings. The support request must still persist with explicit `missing` or `not observed` context markers rather than failing or inventing placeholder truth.
- A run may reference related records that have since been deleted or are no longer accessible. The saved request must keep safe missing or inaccessible markers without leaking details from those records.
- A creator may have `support_requests.create` without `support_diagnostics.view`. The request must still be creatable with the reduced safe context set and explicit omission semantics.
- Context may change after request creation. The request must preserve the immutable submitted context snapshot or reference envelope and must not silently mutate with later diagnostic state.
## Requirements *(mandatory)*
**Constitution alignment (required):** This feature introduces a DB-only write and no new Microsoft Graph calls, no scheduled work, and no queued workflow. Because the request is security-relevant and intentionally skips `OperationRun`, successful request creation MUST write an `AuditLog` entry with redacted metadata.
**Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001):** This feature introduces one new persisted support-request truth, one bounded support-request context builder or submission service, and one small support-request severity family because existing support diagnostics is read-only and generic ticket links lose context. A narrower solution is insufficient because it would still fail to preserve immutable submitted context or return a trustworthy in-product support reference.
**Constitution alignment (XCUT-001):** Support-request capture MUST extend the existing support-diagnostics bundle and audit paths rather than duplicating page-local context assembly or provider wording.
**Constitution alignment (PROV-001):** The support-request model and labels remain provider-neutral. Provider-specific semantics may appear only inside the already redacted support-diagnostic snapshot when that attachment is allowed.
**Constitution alignment (TEST-GOV-001):** Proof stays in focused unit plus feature lanes only. Browser and heavy-governance lanes are out of scope for the first slice.
**Constitution alignment (OPS-UX / OPS-UX-START-001):** No new `OperationRun` is created, resumed, or linked as a started workflow. Request creation is a synchronous DB-only support action.
**Constitution alignment (RBAC-UX):** The affected authorization plane is the tenant-admin `/admin` plane. Non-members and non-entitled users receive 404. Entitled members lacking `support_requests.create` receive 403. The run-context action must only render after the viewer resolves an entitled tenant scope.
**Constitution alignment (UI-FIL-001):** The feature must use native Filament actions and action forms. No custom standalone support page or ad hoc support form shell is allowed in v1.
**Constitution alignment (UI-NAMING-001):** Primary operator labels remain `Request support` and `Support reference`. Implementation-first terms such as payload snapshot, JSON blob, or ticket adapter must not appear in the primary UI.
**Constitution alignment (DECIDE-001 / OPSURF-001):** The affected surfaces remain secondary context surfaces. Support creation must not compete with the primary tenant or operation investigation workflow and must not expose raw diagnostics by default.
### Functional Requirements
- **FR-246-001 Entry points**: The system MUST allow support-request creation from exactly two first-slice contexts: the existing tenant dashboard and the existing canonical operation detail surface.
- **FR-246-002 Immutable internal reference**: Every created support request MUST receive a generated internal support reference that is unique, stable, and shown back to the creator immediately after submission.
- **FR-246-003 Captured fields**: A support request MUST capture workspace, tenant, initiating user, primary context type, optional run reference when applicable, severity chosen from `low`, `normal`, `high`, or `blocking`, a required summary field, optional reproduction notes, and optional contact name and contact email defaults derived from the creator.
- **FR-246-004 Canonical context attachment**: The request MUST automatically attach the safe canonical context set for the current tenant or run instead of requiring manual copy-paste of record identifiers.
- **FR-246-005 Diagnostic snapshot attachment**: When the creator can view support diagnostics for the current scope, the request MUST attach a redacted support-diagnostic snapshot or structured reference envelope derived from the existing bundle contract.
- **FR-246-006 Reduced attachment mode**: When the creator cannot view support diagnostics but can create a support request, the request MUST omit the diagnostic snapshot and persist only the safe canonical context set together with an explicit omission marker.
- **FR-246-007 Authorization boundaries**: Non-members and non-entitled users MUST receive 404 semantics. Entitled users lacking `support_requests.create` MUST receive 403. Cross-tenant or unrelated run context MUST never attach accidentally.
- **FR-246-008 No external dependency**: The first slice MUST NOT require an external ticket provider, outbound HTTP call, or external ticket reference to create a support request.
- **FR-246-009 Auditability**: Support-request creation MUST write an audit event that records the actor, support reference, primary context, attachment mode, and redaction mode without storing excluded raw payload content.
- **FR-246-010 Provider-safe persistence**: Persisted support-request context MUST NOT include raw provider payloads, secrets, tokens, or unrestricted diagnostic bodies.
- **FR-246-011 Immutability**: The first slice MUST treat the support request as immutable after creation. No edit, status workflow, reopen, or merge behavior may be introduced in v1.
- **FR-246-012 Duplicate submissions**: The first slice MUST allow repeated submissions and create a new internal support reference each time rather than attempting hidden deduplication or merge logic.
- **FR-246-013 Machine-readable context**: The attached context envelope MUST remain machine-readable and deterministic so later ticketing or AI-assisted follow-up can reuse it without redefining support-request truth.
## UI Action Matrix *(mandatory when Filament is changed)*
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Tenant dashboard support actions | `App\Filament\Pages\TenantDashboard` | Existing `Open support diagnostics` plus new `Request support` | n/a | none | none | none added | `Request support` on the tenant dashboard action surface only | action-form submit plus cancel | yes | Existing tenant dashboard exemption remains bounded to two support-aware actions only |
| Canonical operation detail support actions | `App\Filament\Pages\Operations\TenantlessOperationRunViewer` | `Open support diagnostics` and `Request support` are grouped under `More` | Existing operation detail page remains the primary inspect model | none | none | n/a | Both support actions are grouped under the run detail action group instead of competing with the page's primary navigation and utility actions | action-form submit plus cancel | yes | Keeps support tooling secondary on the detail page while preserving structured escalation and diagnostics access |
### Key Entities *(include if feature involves data)*
- **SupportRequest**: The new immutable product truth that records one submitted support intake event together with its generated internal reference and safe attached context.
- **SupportRequest Context Envelope**: The redacted, machine-readable set of canonical references and optional diagnostic snapshot attached to a support request.
- **Support Reference**: The generated internal identifier shown back to the creator immediately after submission.
- **Attachment Mode**: The persisted marker that distinguishes between `diagnostic_snapshot_attached` and `canonical_context_only` based on creator capability and safe context rules.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-246-001**: A support request created from either approved surface is persisted with a unique internal support reference and the expected primary context every time in focused feature coverage.
- **SC-246-002**: Focused authorization tests prove that unrelated tenant or run context cannot be attached accidentally and that 404 versus 403 boundaries remain correct.
- **SC-246-003**: Focused audit tests prove that support-request creation writes one redacted audit event and performs no outbound HTTP or `OperationRun` side effect.
- **SC-246-004**: Focused unit coverage proves that the attached context envelope remains deterministic and excludes raw provider payload content.