Data Model: Problem Resolution
Every model below matches docs/06-database-schema.md "Domain: Problem Resolution" field-for-
field — no new columns invented (research.md explains the two places this was deliberately
considered and rejected: Resolution.solutionId, Investigation.isCurrent).
Investigation
| Field |
Type |
Notes |
id |
String @id @default(cuid()) |
|
problemId |
String |
FK to Problem.id (the existing ticketing/tickets one) |
investigator |
String |
agentId — same non-FK free-text convention as TicketMessage.authorRef |
findings |
Json |
structured, not free text (doc 04 §4) |
evidence |
Json? |
|
internalNotes |
String? |
never exposed on any customer-facing read (FR-003) |
status |
String |
open | complete |
createdAt |
DateTime @default(now()) |
ordering field for "most recent investigation" (research.md — no isCurrent flag) |
RootCause
| Field |
Type |
Notes |
id |
String @id @default(cuid()) |
|
problemId |
String |
FK to Problem.id |
type |
String |
technical | configuration | external_dependency | business | contributing_factor — validated, not free text (FR-005) |
description |
String |
|
createdAt |
DateTime @default(now()) |
|
Solution
| Field |
Type |
Notes |
id |
String @id @default(cuid()) |
|
problemId |
String |
FK to Problem.id |
proposed |
String |
|
approved |
Boolean @default(false) |
explicit approval action (FR-007) |
createdAt |
DateTime @default(now()) |
|
implementation |
SolutionImplementation? |
inverse of the 1:1 below |
verification |
SolutionVerification? |
inverse of the 1:1 below |
SolutionImplementation
| Field |
Type |
Notes |
id |
String @id @default(cuid()) |
|
solutionId |
String @unique |
1:1 with Solution — a second implementation attempt is rejected (FR-007 Edge Cases), not overwritten |
notes |
String? |
|
implementedBy |
String |
agentId |
implementedAt |
DateTime @default(now()) |
|
SolutionVerification
| Field |
Type |
Notes |
id |
String @id @default(cuid()) |
|
solutionId |
String @unique |
1:1 with Solution — at most one verification per solution (data-model note in Edge Cases) |
method |
String |
automated | technical_test | customer_confirmation | agent_confirmation — validated (FR-011) |
result |
String |
success | failed |
evidence |
Json? |
|
verifiedAt |
DateTime @default(now()) |
|
Resolution
| Field |
Type |
Notes |
id |
String @id @default(cuid()) |
|
ticketId |
String @unique |
one resolution per ticket |
outcome |
String |
|
resolvedBy |
String |
"ai" or agentId |
resolvedAt |
DateTime @default(now()) |
|
No solutionId FK here (research.md) — the "a successfully verified solution exists for this
ticket's problem" precondition (FR-014) is enforced by the service layer at write time via a
join through Ticket.problemId → Solution.problemId → Solution.verification.result, not stored.
Relations added to existing models
Problem.investigations Investigation[], Problem.rootCauses RootCause[],
Problem.solutions Solution[] (all on the existing ticketing/tickets-owned Problem model)
Ticket.resolution Resolution? (inverse of Resolution.ticketId @unique)
Validation chain (service layer, not DB constraints — matches 003's own state-machine convention)
RootCause create → Problem must have at least one Investigation (FR-006).
Solution create → Problem must have at least one RootCause (FR-009).
SolutionImplementation create → the Solution must have approved: true (FR-008), and must
not already have an implementation (unique constraint surfaces this as a conflict).
SolutionVerification create → the Solution must already have a SolutionImplementation
(verification is of something implemented, doc 04 §7).
Resolution create → the Ticket's Problem must have at least one Solution whose
verification.result === 'success' (FR-014).
Out of scope for this data model (per spec.md Assumptions)
- No new
EscalationRule.triggerType value for verification failure (research.md — reuses the
plain HUMAN_ESCALATION status transition instead).
- No
ResolutionPolicy/scoped auto-close configuration entity — one system-wide config value
(research.md).