Implement external support desk handoff (spec 256). Created and pushed branch `256-external-support-desk-handoff`. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #301
6.6 KiB
Data Model — External Support Desk / PSA Handoff
Spec: spec.md
Spec 256 extends the existing support-request truth. No new support-ticket table, resource, or queue artifact is introduced.
Existing Canonical Entity Extended
SupportRequest (support_requests)
Purpose: Canonical tenant-owned support-request truth. Spec 256 extends it so the same row can carry one-way external handoff continuity.
Existing key fields (already in repo):
idworkspace_idtenant_idoperation_run_idinitiated_by_user_idinternal_referenceprimary_context_typeattachment_modeseveritysummaryreproduction_notescontact_namecontact_emailcontext_envelopecreated_atupdated_at
New fields (planned):
external_handoff_mode- type: string
- required: yes
- default:
internal_only - allowed values:
internal_onlycreate_external_ticketlink_existing_ticket
external_ticket_reference- type: nullable string
- stored when an external ticket was created or linked successfully
external_ticket_url- type: nullable text
- stored only when the target returns or the operator provides a valid URL
external_handoff_failure_summary- type: nullable text
- bounded human-readable failure summary for the current request only
Relationships (unchanged):
- belongs to
Workspace - belongs to
Tenant - optionally belongs to
OperationRun - optionally belongs to initiator
User
Behavioral rules:
internal_referenceremains the canonical TenantPilot support identifier even when an external ticket exists.external_handoff_moderecords the operator’s chosen path and replaces the need for a second persisted status family.- Spec 256 explicitly narrows Spec 246 immutability in one bounded way: after the internal request is created, the same row may receive exactly one synchronous finalization write limited to
external_handoff_mode,external_ticket_reference,external_ticket_url, andexternal_handoff_failure_summary. No later edit, reopen, merge, or status workflow is introduced. external_ticket_referenceandexternal_ticket_urlremain null forinternal_onlyand for failed create attempts.external_handoff_failure_summaryremains null on successful create, successful link, and internal-only submissions.- On a failed external create, the row persists with:
external_handoff_mode = create_external_ticketexternal_ticket_reference = nullexternal_ticket_url = nullexternal_handoff_failure_summarypopulated
- When the failed external create was caused by timeout,
external_handoff_failure_summarystores the same bounded timeout-oriented message that the UI and audit path use. Raw transport detail is never persisted.
Latest-summary query rules:
- Tenant dashboard summary queries the latest support request for the current entitled tenant where
primary_context_type = tenant. - Operation-run summary queries the latest support request for the current run where
primary_context_type = operation_runandoperation_run_idmatches the viewed run. - Existing indexes on
(tenant_id, created_at)and(operation_run_id, created_at)are sufficient. No new lookup path by external reference is planned.
Validation rules:
external_handoff_modemust be one of the three allowed values.external_ticket_referenceis required whenexternal_handoff_mode = link_existing_ticket.external_ticket_urlis optional but must be a valid URL when present.- When no external target is configured for the application, the form must force or constrain the effective mode to
internal_only.
Application-Configured External Target (Config Contract In Scope, Not New Persisted Truth)
External Support Desk Target
Purpose: Supplies the one configured outbound target for create or link normalization.
Status in Spec 256:
- minimal application config contract in scope
- not a new persisted entity in this slice
- not a workspace settings domain or UI surface in this slice
Repo-grounded note:
- The repo has no existing
supportsettings domain, so Spec 256 makes the target seam explicit through one application config file:apps/platform/config/support_desk.phpwith environment-backed values for the single supported target. - This config contract may define availability, create endpoint settings, reference-link normalization defaults, and the five-second outbound timeout budget.
- Per-workspace target selection, settings UI, or a second target remain follow-up scope.
Derived Runtime Entities
SupportRequestHandoffOutcome (computed, not persisted)
Purpose: Gives the Filament page actions one normalized outcome for notification copy and tests after submission completes.
Expected shape:
support_request_idinternal_referenceprimary_context_typehandoff_modehandoff_outcomeinternal_onlyexternal_ticket_createdexternal_ticket_linkedexternal_handoff_failed
external_ticket_referenceexternal_ticket_urlfailure_summary
Why derived only:
- The outcome is an execution summary for one request cycle.
- Persisting it separately would duplicate the support-request truth and audit log.
- The bounded synchronous finalization write on
SupportRequestremains the only allowed post-create mutation for this slice.
LatestSupportRequestHandoffSummary (computed, not persisted)
Purpose: Supplies the existing tenant and run support actions with one scoped summary of the latest linkage for the current primary context.
Expected shape:
internal_referenceprimary_context_typeprimary_context_idsubmitted_atexternal_handoff_modeexternal_ticket_referenceexternal_ticket_urlexternal_handoff_failure_summaryhas_external_linkhas_failure
Why derived only:
- It is a read model over the latest
support_requestsrow for one context. - A separate table or persisted summary would violate
PERSIST-001without solving a distinct lifecycle problem.
Audit Events (Persistent Audit Truth, Not Product Truth)
The implementation should add these stable audit actions in addition to the existing support_request.created event:
support_request.external_ticket_createdsupport_request.external_ticket_linkedsupport_request.external_handoff_failed
Audit context should include:
workspace_idtenant_idinternal_referenceprimary_context_typeprimary_context_idexternal_handoff_modeexternal_ticket_referencewhen present
Audit context should not include:
- raw provider request payloads
- secrets or credentials
- unrestricted provider response bodies