Files
support_backend/specs/009-problem-resolution/contracts/problem-resolution-contract.md
T
saqib mirandClaude Sonnet 5 9ce34d8ca4 plan: design for problem resolution feature (009)
Phase 0 research resolves module placement (problem-management/problems
confirmed dead/unwired, left untouched), Investigation's version-row-per-
attempt shape, the strict investigation->root-cause->solution->
implementation->verification existence chain, why Resolution has no
solutionId FK (matches doc06 exactly), why verification-failure
escalation reuses 003/007's plain HUMAN_ESCALATION transition instead of
adding an eleventh trigger type to 008's already-shipped escalation
rules, the customer-facing route design (reusing 002's inbound trust
boundary rather than fastify.authenticate), and the auto-close sweep
design (the already-defined-but-unused CLEANUP queue, mirroring 008's
breach-detection job).

Phase 1 adds data-model.md, the admin/customer-facing contract, and six
quickstart scenarios covering the full sequential workflow through
customer confirmation, auto-close, and reopen.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 14:37:42 +05:30

3.8 KiB

Contract: Problem Resolution

Agent-facing write routes are gated by fastify.authenticate (known limitation inherited from 002-008). Customer-facing routes are gated by fastify.authenticateProductIntegration + fastify.checkIntegrationRateLimit (002's inbound trust boundary, research.md) and additionally verify the caller's token identifies the same tenant/user as the ticket's own recorded externalTenantId/externalUserId — a 403 if they don't match.

Investigation

  • POST /admin/problems/:problemId/investigations — body { investigator, findings, evidence?, internalNotes?, status? } (status defaults to open). 404 if problemId doesn't exist.
  • GET /admin/problems/:problemId/investigations — every investigation for the problem, newest first, including internalNotes (agent-facing).
  • GET /problems/:problemId/investigations — customer/public-safe variant: same list, with internalNotes always omitted (FR-003).

Root Cause

  • POST /admin/problems/:problemId/root-causes — body { type, description }. 400 if type isn't one of the five validated values. 409 if no investigation exists yet for the problem.

Solution

  • POST /admin/problems/:problemId/solutions — body { proposed }. 409 if no root cause exists yet for the problem.
  • PATCH /admin/solutions/:solutionId/approve — sets approved: true.
  • POST /admin/solutions/:solutionId/implementation — body { notes?, implementedBy }. 409 if the solution isn't approved, or already has an implementation.
  • POST /admin/solutions/:solutionId/verification — body { method, result, evidence? }. 400 if method isn't one of the four validated values. 409 if the solution has no implementation yet, or already has a verification.

Resolution

  • POST /admin/tickets/:ticketId/resolution — body { outcome, resolvedBy }. 409 if the ticket's problem has no solution with a successful verification. Transitions the ticket to RESOLUTION_PENDING_CUSTOMER on success.
  • POST /v1/support/tickets/:ticketId/confirm-resolution — customer-facing (trust boundary above). 409 if the ticket isn't in RESOLUTION_PENDING_CUSTOMER. Transitions to RESOLVED.

Reopen

  • POST /v1/support/tickets/:ticketId/reopen — customer-facing. 409 if the ticket isn't RESOLVED or CLOSED.
  • POST /admin/tickets/:ticketId/reopen — agent-facing, same precondition.

Both reopen routes transition RESOLVED|CLOSED → REOPENED → IN_PROGRESS (research.md's two-hop decision) and touch nothing else — no new SLARun, no mutation of any prior investigation/root- cause/solution/verification/resolution record (FR-018, SC-005).

Guarantees (callable contract)

  1. Every investigation/root-cause/solution/implementation/verification/resolution record, once created, is retrievable exactly as given and is never silently overwritten by a later action in the same problem's lifecycle (SC-001).
  2. internalNotes never appears in a customer-facing investigation read, verified by a direct comparison against the agent-facing read of the same record (SC-002).
  3. A Resolution can never be recorded without a successfully verified solution already on file for the ticket's problem (SC-003).
  4. A ticket in RESOLUTION_PENDING_CUSTOMER with no explicit confirmation reaches RESOLVED within one auto-close job cycle of its configured waiting period elapsing (SC-004).
  5. Reopening a ticket leaves every prior problem-resolution record and its SLARun (008) untouched (SC-005).
  6. A verification failure choosing escalation moves the ticket to HUMAN_ESCALATION through 003's existing state machine, and 007's orchestration re-runs automatically from that transition alone — no new escalation mechanism is introduced by this feature.