<!--
  ════════════════════════════════════════════════════════════════════════════
  TEMPLATE: Technical Design Document (per-PRD, full-stack, merged)
  Used by: /generate-tech-docs
  ════════════════════════════════════════════════════════════════════════════

  SCOPE MODEL
  - ONE document per PRD (not per UC). It covers EVERY use case of the PRD in a
    single merged, full-stack design: backend (API, data model, DB) AND client
    (components, state, API-integration) side by side, joined by cross-tier
    sequence diagrams. This is the "construction blueprint" any developer opens
    to implement the whole feature.
  - INPUT is the BDD feature files of the PRD (web/ · app/ · system/), NOT the
    PRD prose. The PRD is loaded only for Overview/Goals/Actors context.

  INCREMENTAL / APPEND
  - When new BDD is added to the same PRD later, this document is EXTENDED, not
    regenerated: add the new UC's sections + sequence diagrams, update the
    UC Coverage matrix (§10) and the Changelog. Never clobber existing content
    or hand edits.

  FILLING RULES
  - Replace every {…} placeholder with real content. Delete guidance comments.
  - TERMINOLOGY: obey the project dictionary 100%
    (specs/domain-knowledge/business-dictionary.md). Status/enum values →
    core-entities.md (Enum Registry). Entities → core-entities.md.
  - Keep code/DTO/DB samples in the project's stack idiom (see the active module
    stack-profile). The C#/Angular snippets below are ILLUSTRATIVE — swap for
    the real stack.
  - A section that does not apply to this PRD: keep the heading and write
    "N/A — {reason}" rather than deleting it, so the shape stays predictable.
  - Every sequence diagram / API / rule should be traceable back to a scenario:
    reference the SC id (e.g. UC1-SC3) it serves.
-->

# {Feature Area} — {PRD Title} Technical Design Document

<!-- @trace block (PRD-level). ucs = every UC covered by this doc; append ids as UCs are added. -->
---
@trace.id: {TICKET-ID}
@trace.domain: {domain}
@trace.prd: {TICKET-ID}
@trace.ucs: {TICKET-ID}-UC1, {TICKET-ID}-UC2{, …}
@trace.service: {service — from BDD header @trace.service}
@trace.module: {module(s) involved — e.g. dotnet, angular}
@trace.platforms: {system | web | app — whichever BDD folders exist}
@trace.bdd_version: {per-platform map — e.g. system=1.5, web=1.9, app=1.7; only platforms present. Each feature carries its own bdd_version; do not flatten to one number.}
@trace.api_source: {existing | —}
@trace.revision: 1
@trace.status: draft
@trace.generated_at: {YYYY-MM-DD}
---

> **Related docs:** {link sibling PRDs / tech-designs this depends on, e.g. [OTHER-TICKET](../{other-slug}/tech-docs/{OTHER-TICKET}-tech-design.md)}. Delete if none.

## 1. Overview

<!-- 2–4 sentences: what this feature does, who uses it, the key technical shape
     (data sources, primary side effects). Name where data comes from (DB vs
     external API) and the main write. Source: PRD + system BDD. -->

{What the feature does, its main actor, and the core technical mechanism. State
which data is owned (DB) vs sourced live (external API), and the primary write.}

### Goals

<!-- Bullet the technical goals — derived from PRD goals, phrased as what the
     system must guarantee. -->

- {Goal 1}
- {Goal 2}

### Business Actors

| Actor | Description | Channel |
|-------|-------------|---------|
| {Actor} | {role & permission} | {entry path, e.g. App → Widget → Portal → API} |

---

## 2. Architecture Overview

### 2.1 High-level Architecture

<!-- ASCII (or mermaid) topology showing the systems this feature touches:
     client → gateway → service(s) → data stores / external APIs. Keep it to the
     components THIS PRD actually exercises. Source: architecture.md /
     project-context.yaml (services, stack). -->

```
{ASCII or mermaid diagram of the components this feature touches}
```

> **Note:** {call out which data is fetched live from an external API vs stored in the owned DB, and any cache layer + TTL.}

### 2.2 Communication Patterns

| Pattern | Usage | Scope (UC/SC) |
|---------|-------|---------------|
| {Client → Gateway → API} | {auth / action} | {UC1} |
| {API → External API} | {what it fetches, cache TTL} | {UC1-SC…} |

---

## 3. Data Model

<!-- Source: core-entities.md (owned entities) + BDD Then-clauses (state) + PRD.
     Distinguish OWNED entities (in the DB) from API-SOURCED models (fetched
     live, not persisted). List only fields this PRD reads or writes. -->

### 3.1 Entity Design

#### {EntityName} ({DB entity | API-sourced POCO})

{One line: what it represents, and whether it is persisted or fetched live.}

| Field | Type | Usage in {TICKET-ID} |
|-------|------|----------------------|
| `{field}` | `{type}` | {how this feature uses it — read/write, which SC} |

<!-- Repeat per entity. If the feature has meaningful state transitions, add a
     small state table/diagram like below. -->

**State transitions (if any):**

```
{state A}:  {condition}  → {outcome / UI signal}
{state B}:  {condition}  → {outcome}
```

**Constraints:**
- {invariant enforced in application/DB logic, e.g. exactly one primary per tenant}

### 3.2 Entity Relationships

```
{relationship diagram — cardinalities, join keys, which fields are read-only vs owned}
```

### 3.3 Data Source Boundaries

<!-- Crisp statement of what THIS PRD reads vs writes, and what is delegated
     elsewhere. Prevents scope bleed. -->

**{TICKET-ID} scope: {READ … / WRITE …}.**

| Responsibility | In scope? | Handled by |
|----------------|-----------|-----------|
| {read merged list} | ✅ Yes | {endpoint / service} |
| {write X flag} | ✅ Yes | {service} |
| {base data} | ❌ Read-only | {external API + cache} |
| {other module concern} | ❌ No | {module/team} |

### 3.4 Multi-tenant & Sharding

<!-- Only if the project is multi-tenant. Else write "N/A — single tenant". -->

- {tenant key on entities, query-filter isolation, shard resolution — from architecture.md}

---

## 4. API Contracts

<!-- Backend contract. For greenfield: design endpoints from BDD scenarios. For
     brownfield (@trace.api_source = existing): reverse-document the live API
     as-is and note gaps vs BDD expectations. Mark REUSE vs NEW explicitly.
     CLIENT-ONLY PRD (no system/ BDD — this feature owns no backend): do NOT
     fabricate a BE contract. §4.1 then lists the endpoints the client CONSUMES
     (external / third-party / another team's / existing), marked "consumed
     (external)", reverse-documented from the client BDD Then-clauses + PRD;
     fill §4.2/§4.3 only if the shape is known. If the feature makes no network
     calls at all → write "N/A — client-only, no backend". §4.5.4 maps client
     methods to whatever §4.1 lists (or none). -->


### 4.1 Endpoints

```
{METHOD} {/path}          # NEW | REUSE ({source}) — {one-line purpose}
```

### 4.2 Request/Response Models

<!-- Show DTO shapes in the stack's idiom. Note which fields come from DB vs
     external API. -->

```{lang}
{DTO definitions with per-field source comments}
```

### 4.3 Validation & Error Codes

**Validation rules:**

```{lang}
{validation rules, in the stack's idiom (e.g. FluentValidation / class-validator)}
```

| Code | HTTP Status | Description | Trace |
|------|-------------|-------------|-------|
| `{ERROR_CODE}` | {4xx/5xx} | {when it fires} | {UC1-SC…} |

### 4.4 Handler Logic (key endpoints)

<!-- For non-trivial writes, spell out the ordered steps (validation →
     transaction → commit/rollback → return). Keeps the sequence diagram and
     the code aligned. -->

**{HandlerName}:**
1. {step}
2. {step — transaction boundary if any}

### 4.5 UI Component Mapping — {platform} ({framework})

<!-- CLIENT design, GROUPED BY PLATFORM: one "### 4.5 … — {platform}" section per
     client platform present in the BDD (a web group, an app group). Do NOT title
     this heading by screen — screens/UCs live in the sub-blocks below.
     Inside a platform group:
       • §4.5.1 Component Hierarchy — repeat the sub-block per screen/UC:
         "#### 4.5.1.x {Screen} — {UC}". A PRD with many screens/UCs → many sub-blocks
         in the SAME platform group (never a second 4.5 group for the same platform).
       • §4.5.2–§4.5.5 — likewise per screen/UC where they differ.
       • §4.5.6 Test Selectors — ONE shared table for the whole platform group; its
         "Serves SC" column carries (UC · SC) so per-UC consumers filter their rows.
     Append: new platform → new "### 4.5 — {platform}" group; new screen/UC in an
     existing platform → add a sub-block + rows to §4.5.6 (don't duplicate the group).
     Omit §4.5 entirely for a backend-only PRD. -->

> **Source:** {Figma file + node id, from design-spec}
> **Stack:** {framework, state primitive, component library}
> <!-- @figma.url: {node-level figma url} -->

#### 4.5.1 Component Hierarchy — {Screen} ({UC})

<!-- Repeat this sub-block per screen/UC in this platform group (4.5.1.a, 4.5.1.b …). -->

```
{component tree — container vs presentational, conditional children}
```

#### 4.5.2 Component File Mapping

| Component | Path | Type | Purpose |
|-----------|------|------|---------|
| `{Component}` | `{path}` | {Feature/Child} | {responsibility} |

#### 4.5.3 State Management ({state primitive})

<!-- State shape derived from System BDD Then-clauses + response shapes from §4.2.
     Show derived/computed values and their inputs. -->

```{lang}
{state declarations with source comments (which BDD field / BE field each maps to)}
```

#### 4.5.4 API Integration Layer (port/adapter)

<!-- Modal/route config + API-integration map: each client service method → a
     REAL endpoint from §4.1 (do not invent endpoints). Error → UI state per SC.
     This table is what /generate-code --phase=integration reads to wire the real adapter. -->

| Client method | Endpoint (§4.1) | Request map | Response → model | Error → UI |
|---------------|-----------------|-------------|------------------|-----------|
| {svc.getX()} | {GET /…} | {params} | {DTO → ViewModel} | {4xx → state/toast} |

#### 4.5.5 Figma → Design System Mapping

| Figma element | Design system class/token | Notes |
|---------------|---------------------------|-------|
| {element} | {class / token} | {size, color, state} |

#### 4.5.6 Test Selectors — element IDs for actionable elements (QC contract)

<!-- Stable test-id per interactive element so QC locates directly (no runtime
     scan). Convention: {uc-lower}-{screen}-{element}-{type}; DO NOT embed
     scenario numbers. Attribute per platform: web data-testid · RN testID ·
     Flutter Key/Semantics · iOS accessibilityIdentifier. Reuse the same id
     VALUE across web/app for the same logical element.
     ONE shared table for the whole platform group (covers every screen/UC of this
     platform). The "Serves SC" column carries (UC · SC) so a per-UC consumer
     (generate-code / qc) filters to its own rows via §10. This §4.5 group is
     already platform-scoped, so the platform is implicit (web block → web · SC). -->

| Test-ID | Element | Component (§4.5.1.x) | Action | Serves SC (UC · SC) |
|---------|---------|----------------------|--------|---------------------|
| `{uc}-{screen}-{element}-{type}` | {Submit button} | {Component} | {submit} | {UC1 · SC1, UC1 · SC3} |

---

## 5. Key Flows (Sequence Diagrams)

<!-- ONE mermaid sequence diagram per meaningful scenario. Participants span tiers:
     client component → service → API → external API → DB.
     ⚠ SC ids are unique only within (UC × platform): `{UC}-SC1` on `system` and
     `{UC}-SC1` on `web` are DIFFERENT scenarios. So group flows into PLATFORM LANES
     (5.A system · 5.B web · 5.C app) and ALWAYS pair the SC with its platform,
     e.g. "(web · UC1-SC1)". Never write a bare "UC1-SC1" here — it is ambiguous.
     Only include the lanes whose BDD exists in this PRD. -->

### 5.A System flows

<!-- One diagram per system-BDD scenario. Skip this lane if no system/ BDD. -->

#### 5.A.1 {name} (system · {UC}-SC…)

```mermaid
sequenceDiagram
    participant {A} as {Actor}
    {…}
```

### 5.B Web flows

<!-- One diagram per web-BDD scenario. Skip this lane if no web/ BDD. -->

#### 5.B.1 {name} (web · {UC}-SC…)

```mermaid
sequenceDiagram
    {…}
```

### 5.C App flows

<!-- One diagram per app-BDD scenario. Skip this lane if no app/ BDD. -->

#### 5.C.1 {name} (app · {UC}-SC…)

```mermaid
sequenceDiagram
    {…}
```

<!-- Number within each lane: 5.A.1, 5.A.2 … / 5.B.1 … / 5.C.1 …. For a scenario
     whose effect crosses into another module, note "(covered by {OTHER-UC})". -->

**Key integration points (optional table per flow):**

| Step | State transition | Verified by (platform · SC) |
|------|------------------|-----------------------------|
| {step} | {before → after} | {web · UC1-SC…} |

---

## 6. Integration Points

| Integration | Direction | Method | Description |
|-------------|-----------|--------|-------------|
| {Client → API} | Outbound (client) | {REST/Bearer} | {what} |
| {API → External} | Outbound (server) | {REST + header} | {what, cache TTL} |

### 6.1 Event Bus / Messaging

<!-- Kafka/queue events produced/consumed by this feature. "N/A — no events" if none. -->

{events, or N/A}

### 6.2 Cross-Service Dependencies

| Dependent service | What's needed | Contract | Status |
|-------------------|---------------|----------|--------|
| {service} | {need} | {endpoint} | {✅ Exists / ⚠️ pending} |

---

## 7. Security & Authorization

### 7.1 Authentication

{Auth flow + token type/TTL. Source: PRD auth + project rules.}

### 7.2 Authorization Rules

| Action | Required role/permission | Description | Trace |
|--------|--------------------------|-------------|-------|
| {action} | {role} | {how enforced, where} | {UC1-SC… / out of scope} |

---

## 8. Error Handling & Edge Cases

<!-- One row per error / edge / negative scenario in the BDD. This must line up
     with §4.3 error codes and the §5 error sequence diagrams. -->

| Scenario | Strategy | Details | Trace |
|----------|----------|---------|-------|
| {condition} | {approach} | {behavior, message, side effect} | {UC1-SC…, BR…} |

---

## 9. Design Decisions

<!-- The "why" behind non-obvious choices, with alternatives considered. Source:
     PRD alternatives/assumptions + reasoning during generation. This is what lets
     a reviewer trust the design. -->

| # | Decision | Rationale | Alternatives considered |
|---|----------|-----------|-------------------------|
| 1 | **{decision}** | {why} | {alt — why rejected} |

### NFR-to-Design Mapping

| NFR category | PRD requirement | Design decision |
|--------------|-----------------|-----------------|
| {e.g. Multi-tenant isolation} | {requirement} | {mechanism} |

---

## 10. UC Coverage

<!-- THE APPEND ANCHOR **and the INDEX for per-UC consumers**. Every UC of the PRD
     gets a row; every scenario maps to the section(s) that design it.
     - /generate-tech-docs uses it to detect what is already covered vs missing.
     - /generate-code, /map-testids, /qc-* work on ONE UC of a PRD-level doc — they
       look this UC up HERE first to locate its scenarios → the sections/§5-lanes
       (and thus the §4.1 endpoints its §5 flows call) that belong to it. Don't
       pull another UC's endpoints/sections.
     ⚠ Scenario coverage is keyed by (platform, SC) because SC ids repeat across
     platforms — the Platform column disambiguates. -->

| UC | Feature | Platforms | Sections covered | Status |
|----|---------|-----------|------------------|--------|
| {TICKET-ID}-UC1 | {title} | {system, web, app} | §… | ✅ Covered |

### UC1 Scenario Coverage

<!-- One row per (platform, SC). Same SC number on different platforms = different
     scenarios → separate rows. -->

| Platform | Scenario | Section | Business rule |
|----------|----------|---------|---------------|
| system | {UC}-SC1: {name} | §5.A.1 | {BR…} |
| web | {UC}-SC1: {name} | §4.5 (web), §5.B.1 | {BR…} |

<!-- Repeat a scenario-coverage block per UC. -->

---

## 11. Cross-cutting & Assumptions (Out-of-Scope Reference)

<!-- Upstream concerns this PRD DEPENDS ON but does not implement (admin gate,
     downstream UI in another module, order snapshotting…). Keep for cross-team
     context. Reference the owning UC/team + doc. Source: PRD out-of-scope +
     BDD BR "out of scope" notes. -->

### 11.1 {Concern}

> {Quote the BDD/PRD line that scopes it out.}

{Explanation of the boundary + a reference sequence diagram if useful.}

**Owned by:** {team / module}. See {link}.

---

## 12. GAP Register — ẩn số thiết kế chưa chốt

<!--
  Mọi [GAP: Gn] / [ASSUMPTION: An] đánh dấu inline trong doc PHẢI có đúng MỘT dòng ở đây
  (và ngược lại — không marker mồ côi, không dòng thừa). Đây là sổ quản lý vòng đời ẩn số.

  - Loại:
      • nội tại      — BE tự quyết (đóng: BE điền giá trị, thay marker)
      • cross-service — cần team/partner khác (đóng: qua T7 sign-off của owner)
      • spec-defect  — BDD/PRD sai/thiếu (KHÔNG tự đóng: escalate PO sửa .feature/PRD → regen; xem §9 Conflict)
  - Severity:
      • 🔴 blocker    — code BẮT BUỘC phải có mới đúng → CHẶN approve
      • 🟢 non-blocker — đoán tạm chạy được, chỉ cần confirm → không chặn
    (Nhãn GAP/ASSUMPTION KHÔNG tự quyết severity — một ASSUMPTION vẫn có thể là blocker nếu đoán sai sẽ vỡ.)
  - Status: open → resolved (owner điền giá trị thật → thay marker inline → bump @trace.revision).

  GATE: còn ≥1 🔴 blocker ở trạng thái `open` → @trace.status KHÔNG được lên `approved`
        (giữ `in-review`) → generate-code bị chặn. Cùng pattern design-spec giữ `draft` khi còn ❌ Missing.
-->

| id | Dùng ở (§) | Điều chưa biết | Loại | Owner confirm | Severity | Status | Đóng thế nào |
|----|-----------|----------------|------|---------------|----------|--------|--------------|
| G1 | {§4.3} | {shape lỗi khi partner từ chối} | cross-service | {team-payment} | 🔴 blocker | open | {T7 sign-off — owner cung cấp contract} |
| A1 | {§4.1} | {timeout mặc định 30s} | nội tại | {BE lead} | 🟢 non-blocker | open | {BE xác nhận, thay giá trị} |

> Nếu doc **không có** ẩn số nào → ghi "Không có — mọi thiết kế đều có nguồn." **KHÔNG** bịa dòng để lấp trống.

---

## Figma Design References

<!-- @figma.url: {node-level figma url per screen} -->
- {Screen}: [Figma — {frame}]({url})
- Exported: {YYYY-MM-DD}

---

## Changelog

| Revision | Date | Changes |
|----------|------|---------|
| 1 | {YYYY-MM-DD} | Initial generation from {TICKET-ID} BDD (v{bdd_version}): {list UCs covered} |
<!-- On append: add a row per extension, e.g. "2 | {date} | Added UC3 (§5.9, §10) from new BDD v{n}" -->
