{
  "document": {
    "id": "PRD-REQUEST-TRACKER",
    "version": "1.0.0",
    "status": "accepted",
    "productOwner": "Operations lead",
    "technicalOwner": "Application owner",
    "reviewers": ["Support lead", "Privacy owner"],
    "reviewedAt": "2026-08-01",
    "replacesVersion": null
  },
  "problem": {
    "user": "Internal operations coordinator",
    "situation": "Requests arrive through several channels and lose a stable owner, state, and follow-up history.",
    "currentWorkaround": "A shared spreadsheet plus direct messages.",
    "statement": "The coordinator needs one durable request record and explicit ownership so the team can see what requires action without treating a message as the source of truth.",
    "evidenceAvailable": [
      "Five fictional walkthroughs reproduce missing owner and duplicate follow-up states."
    ],
    "evidenceMissing": [
      "Real-team observation and baseline cycle-time measurement are still required."
    ]
  },
  "outcome": {
    "intendedUserOutcome": "The coordinator can identify the current owner and next action for every active request.",
    "primarySignal": {
      "name": "active requests with an owner and next action",
      "definition": "Count of nonterminal request records with both ownerId and nextActionAt divided by all nonterminal request records.",
      "baseline": null,
      "window": "First 14 days after the controlled pilot begins",
      "owner": "Operations lead"
    },
    "guardrailSignals": [
      "unauthorized request reads",
      "duplicate request records",
      "notification dead letters"
    ],
    "decisionRule": "Continue only after every pilot request remains attributable and access tests have zero cross-account reads. This is a pilot gate, not a business-outcome guarantee."
  },
  "scope": {
    "in": [
      "Create a request",
      "Assign or reassign an owner",
      "Move through explicit states",
      "Record next action",
      "View bounded audit history",
      "Export authorized request rows"
    ],
    "nonGoals": [
      "Automatic prioritization",
      "Native email or chat integration",
      "Customer billing",
      "SLA guarantee",
      "Company-wide analytics"
    ]
  },
  "records": [
    {
      "name": "Request",
      "idField": "requestId",
      "requiredFields": [
        "requestId",
        "workspaceId",
        "createdBy",
        "title",
        "state",
        "ownerId",
        "version",
        "createdAt",
        "updatedAt"
      ],
      "states": ["new", "triaged", "in-progress", "waiting", "resolved", "closed"],
      "owner": "Operations lead",
      "retention": "Pilot records retained for 30 days, then reviewed for deletion or an approved longer policy."
    },
    {
      "name": "AuditEvent",
      "idField": "eventId",
      "requiredFields": [
        "eventId",
        "requestId",
        "actorId",
        "action",
        "fromState",
        "toState",
        "recordVersion",
        "createdAt"
      ],
      "states": ["recorded"],
      "owner": "Application owner",
      "retention": "Follows the request retention decision unless an incident hold is recorded."
    },
    {
      "name": "NotificationAttempt",
      "idField": "attemptId",
      "requiredFields": [
        "attemptId",
        "requestId",
        "channel",
        "status",
        "attemptCount",
        "nextAttemptAt"
      ],
      "states": ["pending", "retry-scheduled", "delivered", "dead-letter"],
      "owner": "Application owner",
      "retention": "Bounded delivery metadata only; message bodies are excluded from routine logs."
    }
  ],
  "requirements": [
    {
      "id": "REQ-001",
      "text": "An authenticated workspace member can create one request with a stable requestId after authoritative server validation.",
      "priority": "must",
      "owner": "Application owner",
      "source": "Problem walkthrough",
      "acceptanceIds": ["AC-001", "AC-002"]
    },
    {
      "id": "REQ-002",
      "text": "The server derives workspace scope and rejects list, detail, update, and export access from another workspace.",
      "priority": "must",
      "owner": "Privacy owner",
      "source": "Access boundary",
      "acceptanceIds": ["AC-003"]
    },
    {
      "id": "REQ-003",
      "text": "An assigned coordinator can transition a current-version request only through the declared state table.",
      "priority": "must",
      "owner": "Operations lead",
      "source": "Operating policy",
      "acceptanceIds": ["AC-004", "AC-005"]
    },
    {
      "id": "REQ-004",
      "text": "The same technical create or transition attempt returns the existing result and changed reuse is rejected.",
      "priority": "must",
      "owner": "Application owner",
      "source": "Retry boundary",
      "acceptanceIds": ["AC-006"]
    },
    {
      "id": "REQ-005",
      "text": "A saved request remains authoritative when a notification attempt fails, and only the delivery attempt retries.",
      "priority": "must",
      "owner": "Application owner",
      "source": "Partial failure boundary",
      "acceptanceIds": ["AC-007"]
    },
    {
      "id": "REQ-006",
      "text": "The published private route exposes one current owner, next action, and bounded audit history without private payloads in routine logs.",
      "priority": "must",
      "owner": "Operations lead",
      "source": "Pilot smoke",
      "acceptanceIds": ["AC-008"]
    }
  ],
  "acceptanceCriteria": [
    {
      "id": "AC-001",
      "requirementId": "REQ-001",
      "given": "an authenticated member with valid required fields",
      "when": "the member creates a request",
      "then": "one durable request returns a stable requestId",
      "testId": "TEST-001"
    },
    {
      "id": "AC-002",
      "requirementId": "REQ-001",
      "given": "an authenticated member with an empty title",
      "when": "the member creates a request",
      "then": "validation fails and no request or success state is created",
      "testId": "TEST-002"
    },
    {
      "id": "AC-003",
      "requirementId": "REQ-002",
      "given": "a known requestId from another workspace",
      "when": "a member reads or updates it directly",
      "then": "the server denies access without returning request fields",
      "testId": "TEST-003"
    },
    {
      "id": "AC-004",
      "requirementId": "REQ-003",
      "given": "a triaged request and its current version",
      "when": "the assigned coordinator starts work",
      "then": "the request moves to in-progress and records one audit event",
      "testId": "TEST-004"
    },
    {
      "id": "AC-005",
      "requirementId": "REQ-003",
      "given": "a stale request version",
      "when": "a coordinator attempts a transition",
      "then": "the server returns a conflict and preserves the current state",
      "testId": "TEST-005"
    },
    {
      "id": "AC-006",
      "requirementId": "REQ-004",
      "given": "one completed create attempt",
      "when": "the exact attempt repeats and changed input reuses its key",
      "then": "the exact retry returns the requestId and changed reuse conflicts",
      "testId": "TEST-006"
    },
    {
      "id": "AC-007",
      "requirementId": "REQ-005",
      "given": "a durably saved request and a failing notification adapter",
      "when": "delivery is attempted",
      "then": "the request remains single and only its notification attempt becomes retryable",
      "testId": "TEST-007"
    },
    {
      "id": "AC-008",
      "requirementId": "REQ-006",
      "given": "the controlled private pilot is published",
      "when": "the intended member opens list and detail routes",
      "then": "the expected owner, next action, and audit events render with no cross-workspace access",
      "testId": "TEST-008"
    }
  ],
  "experienceStates": {
    "loading": "Request skeleton with controls disabled.",
    "empty": "No requests yet, with a create action for authorized members.",
    "validationError": "Field-level message plus retained safe input.",
    "readError": "Bounded retry without showing cached private data from another account.",
    "writeError": "Current record stays visible and the action can be retried with the same key.",
    "staleConflict": "Show the newer version and require a fresh decision.",
    "partialFailure": "Saved request remains visible while notification status is retry-scheduled.",
    "success": "Stable requestId, current owner, state, and next action are visible.",
    "recovery": "Authorized bounded repair is preferred; whole-app recovery is a separate incident decision."
  },
  "dependencies": [
    {
      "name": "Authentication service",
      "why": "Resolve current member identity and session state.",
      "accountOrPlan": "Application-owned boundary",
      "credential": "Server-side session signing and storage configuration",
      "minimumAccess": "Current session only",
      "failureBehavior": "Deny private routes",
      "owner": "Application owner"
    },
    {
      "name": "Optional notification provider",
      "why": "Send a follow-up after the request is saved.",
      "accountOrPlan": "Selected only after the core workflow passes",
      "credential": "Server-side API or SMTP credential",
      "minimumAccess": "Single approved sender and delivery operation",
      "failureBehavior": "Keep request durable and retry only the outbox intent",
      "owner": "Application owner"
    }
  ],
  "securityPrivacyOperations": {
    "authentication": "Private routes require a current server-validated session.",
    "authorization": [
      "Derive workspace from membership",
      "Check list, detail, transition, export, and audit access on the server",
      "Deny by default"
    ],
    "sensitiveFields": [
      "request description is minimized and length-bounded",
      "no secrets or regulated attachments in the pilot"
    ],
    "logExclusions": [
      "request descriptions",
      "session values",
      "credentials",
      "notification bodies"
    ],
    "retention": "Operations lead reviews pilot deletion at day 30.",
    "monitoring": [
      "request create errors",
      "denied cross-workspace access",
      "version conflicts",
      "idempotency conflicts",
      "notification dead letters"
    ],
    "repair": "Authorized record-level correction with an appended audit event.",
    "export": "Workspace-scoped CSV with explicit allowlisted fields.",
    "wholeAppRecoveryBoundary": "A saved-point restore can move later valid request data backward and requires a separate incident decision."
  },
  "releaseGates": [
    {
      "id": "GATE-LOCAL",
      "name": "Deterministic local tests",
      "evidence": "TEST-001 through TEST-007 pass against fictional data",
      "evidenceIds": [
        "TEST-001",
        "TEST-002",
        "TEST-003",
        "TEST-004",
        "TEST-005",
        "TEST-006",
        "TEST-007"
      ],
      "owner": "Application owner",
      "status": "pending",
      "stopCondition": "Any authority, retry, transition, or partial-failure test fails"
    },
    {
      "id": "GATE-REVIEW",
      "name": "Policy and privacy review",
      "evidence": "Named reviewers accept the state table, fields, retention, and non-goals",
      "evidenceIds": ["DEC-001", "DEC-002", "DEC-003"],
      "owner": "Product owner",
      "status": "pending",
      "stopCondition": "An owner or policy decision is missing"
    },
    {
      "id": "GATE-SMOKE",
      "name": "Published private smoke",
      "evidence": "TEST-008 passes with two ordinary workspaces",
      "evidenceIds": ["TEST-008"],
      "owner": "Application owner",
      "status": "pending",
      "stopCondition": "Wrong version, missing owner, or any cross-workspace read"
    },
    {
      "id": "GATE-PILOT",
      "name": "Fourteen-day observation",
      "evidence": "Predeclared signal and guardrails reviewed with exact record counts",
      "evidenceIds": ["REQ-006"],
      "owner": "Operations lead",
      "status": "pending",
      "stopCondition": "Unowned active request, unexplained duplicate, or privacy incident"
    }
  ],
  "risks": [
    {
      "id": "RISK-001",
      "description": "Users may put unnecessary sensitive data in request descriptions.",
      "owner": "Privacy owner",
      "mitigation": "Minimize fields, bound text, add guidance, exclude content from routine logs, and review retention."
    },
    {
      "id": "RISK-002",
      "description": "Notification delivery can be mistaken for request creation.",
      "owner": "Application owner",
      "mitigation": "Save first, model delivery separately, and show independent statuses."
    },
    {
      "id": "RISK-003",
      "description": "A broad restore can erase valid requests created after the snapshot.",
      "owner": "Application owner",
      "mitigation": "Prefer bounded repair and require an incident-specific restore and data-handoff plan."
    }
  ],
  "openQuestions": [
    {
      "id": "Q-001",
      "question": "Which request categories need different state transitions?",
      "owner": "Operations lead",
      "due": "Before pilot",
      "blocking": true
    },
    {
      "id": "Q-002",
      "question": "Which notification provider, if any, is required for the pilot?",
      "owner": "Application owner",
      "due": "After core workflow tests",
      "blocking": false
    },
    {
      "id": "Q-003",
      "question": "Which allowlisted fields belong in the authorized export?",
      "owner": "Privacy owner",
      "due": "Before published smoke",
      "blocking": true
    }
  ],
  "decisions": [
    {
      "id": "DEC-001",
      "date": "2026-08-01",
      "decision": "Use one Request record with explicit state and version.",
      "rationale": "A stable identity and version make ownership, retries, conflicts, and audit history testable.",
      "decider": "Operations lead",
      "changesRequirements": ["REQ-001", "REQ-003", "REQ-004"]
    },
    {
      "id": "DEC-002",
      "date": "2026-08-01",
      "decision": "Keep notification attempts outside the request transaction result.",
      "rationale": "A provider outage must not lose or duplicate a durable request.",
      "decider": "Application owner",
      "changesRequirements": ["REQ-005"]
    },
    {
      "id": "DEC-003",
      "date": "2026-08-01",
      "decision": "Keep automatic prioritization and native provider connections out of the pilot.",
      "rationale": "The first release tests record ownership and lifecycle before adding external systems or inferred decisions.",
      "decider": "Product owner",
      "changesRequirements": []
    }
  ]
}
