---
artifact-status: draft   # draft | approved — approval state of this generated file (gate reads this)
---
# Solution Architecture Document (SAD)

> **Version:** 1.0  ·  **Last Updated:** [Date]  ·  **Author:** [SE name]
> **PRD:** [Product Requirements Document](prd.md) — FRs, NFRs, modules, and the data model live there (single source of truth). This SAD references the PRD by ID and does not restate requirements.

---

<!-- Sections marked "(framing — not a proposal sub-artifact)" are kept for readability/sign-off. The ten governed sub-artifacts run §2 Architecture Principle → §12 Deployment Topology, in proposal order, each its own numbered ## heading with no wrapper. Numbers are stable cross-reference anchors used by the rules/commands. -->

## 1. Executive Summary

<!-- Framing — not a proposal sub-artifact. Kept for readers without technical background. Short prose, max 1 page.
  - Purpose: why this SAD exists, what problem it solves
  - Scope: which systems / boundaries are (and aren't) covered
  - Key Objectives: 3-5 specific, measurable architecture objectives -->

### 1.1 Purpose
### 1.2 Scope
### 1.3 Key Objectives

---

## 2. Architecture Principle

<!-- Proposal sub-artifact (from PRD.NFR). 4-8 principles that guide every architecture decision.
  e.g. API-first (all business logic exposed via API); Stateless services (no server-side session); Defense in depth; Fail fast. Bullet list. -->

- [Principle 1]
- [Principle 2]

---

## 3. Constraints & Assumptions

<!-- Framing — not a proposal sub-artifact (the governed constraints live in BRD.Constraint & Assumption). Kept here for the technical/organizational constraints and accepted assumptions that bound this architecture. Bullet list. -->

- [e.g. Must deploy on Azure; must integrate with existing SAP]
- [Assumption: customer provides their own server infrastructure]

---

## 4. Technology Stack

<!-- Proposal sub-artifact (from PRD.NFR + SE). Technology, version, and rationale per layer.
  **Current State (brownfield):** if modernizing an existing system, note the current stack + migration deltas here, and add a current-state diagram. Greenfield → state "greenfield".
  External services / third-party APIs / shared platforms appear in §5 System Context (as externals) and §9 Integration Contract (as contracts) — not duplicated here. -->

| Layer | Technology | Version | Rationale |
|-------|------------|---------|-----------|
| Frontend | [e.g. Next.js] | [14] | [SSR, team expertise] |
| Backend | [e.g. .NET] | [8] | [team expertise] |
| Database | [e.g. PostgreSQL] | [16] | [relational, ACID] |
| Cache | [e.g. Redis] | [7] | [session, cart] |
| Infrastructure | [e.g. AWS ECS] | — | [managed containers] |

---

## 5. System Context (C4 Level 1)

<!-- Proposal sub-artifact (from PRD.FR + PRD.NFR + BRD.Actor). Answers: "Where does this system sit in the ecosystem?"
  - Mermaid flowchart: system in the center, users and external systems around it
  - **External actors come from BRD.Actor** — take every `AT-NNN` of type "External system" and place it here as an external; do not invent externals not traceable to a BRD Actor. (Human actors are represented via their PRD Persona, not enumerated here.)
  - Annotate each external system: name (with its `AT-NNN`), role, communication protocol
  - Not here: internal system details (that is §6 Container View)
  Mermaid rules: :::mermaid wrapper, no bare () in node labels (use [] or quote the label); no () in edge labels between `|...|`; for line breaks in a label use `<br />`, not `\n`.

  Example:
  :::mermaid
  flowchart TD
    U[fa:fa-user End User] -->|HTTPS| SYS[Your System]
    SYS -->|REST| EXT1[Payment Gateway]
    SYS -->|SMTP| EXT2[Email Service]
    ADMIN[fa:fa-user Admin] -->|HTTPS| SYS
  ::: -->

---

## 6. Container View (C4 Level 2)

<!-- Proposal sub-artifact (from PRD.FR). Answers: "What containers does this system consist of?"
  - Mermaid flowchart: all containers (web app, API, DB, cache, queue, ...)
  - Each container: name, technology, main role
  - Interaction flows between containers with protocol/label
  - Group by bounded context (subgraph) if large
  Example node: WebApp["Web App<br />Next.js / Vercel"] -->

---

## 7. Module & Component (C4 Level 3)

<!-- Proposal sub-artifact (from PRD.FR + PRD.M). This is where PRD (WHAT) becomes HOW. Hierarchy is Container ⊃ Module ⊃ Component.
  Module (`MOD-NN`) = a cohesive, logical grouping of components INSIDE a container. Maps 1-to-1 to a PRD.Module; carries the FR mapping; sized roughly like one Feature. It is a grouping, not a deployable/runnable thing (the Container is). Stable global ID, never reused.
  Component (`MOD-NN.C#`) = an architecturally significant building block WITH a defined interface (e.g. a controller, service, adapter, repository, gateway) — NOT every class/file. This is the **buildable leaf and the coverage unit**: a Feature builds components, and the done-time coverage check verifies every component is built. Keep the list to significant blocks (typically 2-6 per module); do not enumerate trivial helpers. Component IDs are module-prefixed and stable: `MOD-03.C1`, `MOD-03.C2`, …
  An FR is realized by Modules/Components (not mapped 1-to-1): logically a Feature builds one Module's components and may interact with others.
  Organize BY container (one ### subsection per container). Each subsection MUST have: (A) the module table, (B) the component table, (C) a mandatory zoom diagram whose nodes are labelled with component IDs.
  **Coverage rule (the "never missed" guarantee):** every component (`MOD-NN.C#`) must be claimed by ≥1 Feature (via Feature-Technical `## Modules > Builds`); every component belongs to a module → an FR (or is justified `infra`). An FR realized by no component is a design hole; a component built by no Feature is a missing Feature; a module must own ≥1 component. Feature breakdown and done-time coverage check against the component list.
  Do NOT split into separate files — keep all tables in this document so coverage is checkable in one place. -->

### 7.1 [Container Name] (from §6)

<!-- Brief role of this container + its stack. Then ALL THREE: (A) module table, (B) component table, (C) a MANDATORY zoom diagram.
  Module table columns:
  - Provides: interface(s) the module exposes (endpoint, event, screen, "—" if none)
  - Depends on: other MOD-IDs it calls, or other containers / external systems by name, + protocol (e.g. "MOD-03 (in-proc)", "Postgres (SQL)", "Stripe (HTTPS)"). Datastores / queues / external systems are containers or externals, not modules — reference them by name, they get no MOD-ID.
  - FRs: which FR-xxx this module helps realize (or "infra — reason" if it serves no single FR) -->

**Modules**

| MOD-ID | Module | Responsibility | Provides | Depends on (→MOD / container, protocol) | FRs |
|--------|--------|----------------|----------|------------------------------------------|-----|
| MOD-02 | {Order} | {order lifecycle} | {REST /orders} | MOD-03 (in-proc), Postgres (SQL) | FR-003 |
| MOD-03 | {Payment} | {charge / refund} | {internal API} | Stripe (HTTPS) | FR-003 |

<!-- Component table: the buildable leaves, one row per significant building block (2-6 per module). `Component ID` is module-prefixed (`MOD-02.C1`). `Interface` = what it exposes/owns (endpoint, class responsibility, "—"). `FRs` = which FR-xxx it helps realize (or "infra — reason"). Every row here must be claimed by ≥1 Feature at breakdown time. -->

**Components**

| Component ID | Component | Responsibility / Interface | FRs |
|--------------|-----------|----------------------------|-----|
| MOD-02.C1 | {OrderController} | {REST /orders endpoints} | FR-003 |
| MOD-02.C2 | {OrderService} | {order lifecycle logic} | FR-003 |
| MOD-02.C3 | {OrderRepository} | {order persistence} | FR-003 |
| MOD-03.C1 | {PaymentService} | {charge / refund via Stripe} | FR-003 |

<!-- MANDATORY zoom diagram. Must show all four:
  1. MODULES of this container as subgraphs, with their internal component nodes
  2. INTERNAL wiring (between components, and cross-module calls)
  3. INBOUND — who calls INTO this container (external actors / other containers' MOD-IDs)
  4. OUTBOUND — what it calls OUT to (other containers, datastores, external systems) + protocol on each edge
  Mermaid rules: :::mermaid wrapper, no bare () in node labels (use [] or quote the label); no () in edge labels between `|...|`; for line breaks in a label use `<br />`, not `\n`. -->

:::mermaid
flowchart LR
  web["Web App — MOD-01"]
  subgraph C2["Order API container"]
    subgraph M2["MOD-02 Order"]
      ctrl["MOD-02.C1 OrderController"] --> svc["MOD-02.C2 OrderService"] --> repo["MOD-02.C3 OrderRepository"]
    end
    subgraph M3["MOD-03 Payment"]
      pay["MOD-03.C1 PaymentService"]
    end
    svc --> pay
  end
  db[("Postgres DB")]
  stripe["Stripe"]
  web -->|REST| ctrl
  repo -->|SQL| db
  pay -->|HTTPS| stripe
:::

### 7.2 [Container Name] (from §6)

<!-- Next container — same shape: module table + component table + its own MANDATORY zoom diagram.
  Add one subsection per container that holds modules.
  Simple containers (proxy, static files, thin wrapper) → a one-module / one-component table + a minimal in/out diagram is fine. -->

**Modules**

| MOD-ID | Module | Responsibility | Provides | Depends on (→MOD / container, protocol) | FRs |
|--------|--------|----------------|----------|------------------------------------------|-----|
| MOD-01 | {Checkout UI} | {checkout screen} | — | MOD-02 (REST) | FR-003 |

**Components**

| Component ID | Component | Responsibility / Interface | FRs |
|--------------|-----------|----------------------------|-----|
| MOD-01.C1 | {CheckoutPage} | {checkout screen UI} | FR-003 |
| MOD-01.C2 | {OrderApiClient} | {calls Order API} | FR-003 |

:::mermaid
flowchart LR
  user["End User"]
  subgraph W["Web App container"]
    subgraph M1["MOD-01 Checkout"]
      page["MOD-01.C1 CheckoutPage"] --> client["MOD-01.C2 OrderApiClient"]
    end
  end
  api["Order API — MOD-02"]
  user -->|HTTPS| page
  client -->|REST| api
:::

---

## 8. Data Architecture

<!-- Proposal sub-artifact (from PRD.DM + PRD.NFR + BRD.ES). Four parts. Use the `E-NNN` codes from PRD.Product Data Model so the entity chain stays traceable (BRD.Entity → PRD.DM → here → Feature Technical Plan ERD Delta).
  STOP at schema level — indexes, partitions, and per-feature column additions belong in Feature Technical Plan.ERD Delta, not here.
  Mermaid rules: erDiagram for the ERD; :::mermaid wrapper, no () in labels. -->

### 8.1 Domain Model

<!-- Technical model of the business entities: attributes (key fields) + accurate cardinality. This is PRD.Product Data Model (relationships only) made technical. Reference each entity by its E-NNN code.
  **Coverage (tracked):** every persisted `E-NNN` is a tracked design item. Exactly one Feature is its **owner** (creates its schema/table); other Features only use it. The `/tas-master-plan` break gate asserts every E-NNN here has an owner Feature, and `/tas-status` asserts it was built — so no designed entity is left without a table. -->

| Entity | Attributes (key fields) | Relationships (cardinality) |
|--------|-------------------------|-----------------------------|
| E-003 Order | id, status, total, customer_id | E-003 Order ||--o{ E-006 OrderItem; E-003 Order }o--|| E-001 Customer |
| E-006 OrderItem | id, qty, unit_price, product_id | E-006 OrderItem }o--|| E-002 Product |

### 8.2 ERD

:::mermaid
erDiagram
  CUSTOMER ||--o{ ORDER : places
  ORDER ||--o{ ORDER_ITEM : contains
  PRODUCT ||--o{ ORDER_ITEM : referenced_by
:::

### 8.3 Data Classification

<!-- PII / Sensitive / Internal / Public per entity (or per field where it matters). -->

| Entity / Field | Classification |
|----------------|----------------|
| E-001 Customer.email | PII |
| E-003 Order.total | Internal |

### 8.4 Retention Policy

<!-- Only if a compliance/business requirement exists. -->

| Entity | Retention |
|--------|-----------|
| E-003 Order | 7 years |

---

## 9. Integration Contract

<!-- Proposal sub-artifact (from PRD.FR). The stable contracts between modules and external systems. API Design Principles are folded in here as the lead-in, then the contract registry itself. -->

### 9.1 API Design Principles

<!-- Folded in from the old standalone section. Fill only if the system exposes an API (internal or external).
  Required:
  - API Style: REST / GraphQL / gRPC / Event-driven — and rationale
  - Versioning strategy: URL path (/v1/) vs header vs query param
  - Authentication scheme: Bearer JWT / API Key / OAuth2 / mTLS
  - Standard error format: HTTP status codes, error body structure
  Should have: rate limiting, pagination convention, idempotency for mutating ops
  Don't include here: endpoint list, detailed request/response schemas — those are the registry below + the implementation. Bullet list or short table. -->

### 9.2 Integration Contract Registry

<!-- The registry of STABLE contracts (service-to-service and external). Each contract gets an `IC-NN` ID and is the anchor a Feature Technical Plan copies into its "DO NOT CHANGE" section — a coding agent must not alter a contract signature listed here without a new ADR.
  Keep this to the contract surface (endpoint/event, request/response shape, timeout, owning MOD). Full schemas live with the implementation.
  **Coverage (tracked):** every `IC-NN` is a tracked design item. Its **producer** Feature is the one that builds the Producer (MOD) component; consumers reference it via DO NOT CHANGE. The `/tas-master-plan` break gate asserts every IC-NN has a producer Feature, and `/tas-status` asserts it was built — so no registered contract is left unimplemented. -->

| IC-ID | Contract (endpoint / event) | Producer (MOD) | Consumers | Request → Response (shape) | Timeout / Notes |
|-------|-----------------------------|----------------|-----------|----------------------------|-----------------|
| IC-01 | POST /v1/payments | MOD-03 Payment | MOD-02 Order | {order_id, amount, method} → {payment_id, status} | 30s, 1 retry |
| IC-02 | event OrderConfirmed | MOD-02 Order | Notification, Analytics | {order_id, customer_id, total} | async (queue) |

---

## 10. Security Architecture

<!-- Proposal sub-artifact (from PRD.NFR). An architectural concern, not implementation detail. ONE section: the design narrative + diagrams first, then the trackable Security Controls table.
  Design narrative + diagrams:
  - Threat Model: attack surfaces, trust boundaries, top threats (STRIDE if needed) — table (Threat | Vector | Mitigated by → SEC-NN). Reference controls by ID; do not restate them.
  - Identity & Auth Flow: AuthN/AuthZ mechanism, token lifecycle, privilege escalation path — Mermaid sequenceDiagram
  - Data Classification: PII / Sensitive / Internal / Public — handling rules per class
  - Network Security Zones: public / DMZ / private / data tier and rules between zones — Mermaid flowchart, subgraph per zone
  - Encryption: at-rest (algorithm, key management) and in-transit (TLS version, cert strategy)
  Should have: secrets management (Vault, AWS SSM), audit logging scope + retention, compliance (GDPR, PCI-DSS, SOC2) if applicable.

  Then the Security Controls table below — each control gets a stable `SEC-NN` ID, defined ONCE here (the threat model references them by ID). Realized as = a dedicated Feature (login, MFA, audit-log viewer) OR a cross-cutting constraint (JWT on every protected route, PII encryption at rest).
  **Coverage (tracked):** the `/tas-master-plan` break gate asserts every `SEC-NN` is addressed by ≥1 Feature (via a Feature's `## Modules > Security` claim or its own Feature); `/tas-status` asserts it was implemented — so no specified control is silently skipped. -->

**Security Controls**

| SEC-ID | Control / Mitigation | Threat (STRIDE) | Realized as | Linked FR / asset |
|--------|----------------------|-----------------|-------------|-------------------|
| SEC-01 | JWT Bearer auth on all /api routes except /auth | Spoofing | cross-cutting constraint | all protected FRs |
| SEC-02 | PII encrypted at rest (AES-256) | Information disclosure | cross-cutting constraint | E-001 Customer |
| SEC-03 | MFA enrolment + challenge | Spoofing / Elevation | Feature | FR-00X |

---

## 11. NFR Strategy

<!-- Proposal sub-artifact (from PRD.NFR). Each NFR-xxx in the PRD must have a corresponding strategy here (reference by ID).
  Cover the categories that have a related NFR:
  - Performance: caching (L1/L2/CDN), DB indexing, query optimization
  - Scalability: horizontal vs vertical, stateless design, queue-based decoupling
  - Availability: redundancy model (Active-Active/Active-Passive), failover, SLA target
  - Resilience: circuit breaker, retry with backoff, bulkhead, timeout policy
  - Observability: structured logging, distributed tracing, metrics & alerting thresholds
  Should have: capacity planning baseline, DR strategy (RPO/RTO, backup/restore)
  **Coverage (tracked):** every `NFR-NNN` is a tracked design item. It must be addressed by ≥1 Feature — as a constraint in that Feature's `## Modules > NFRs` claim (e.g. a latency/caching target) or realized as its own Feature (e.g. a backup/restore admin screen). The `/tas-master-plan` break gate asserts every NFR-NNN is addressed, and `/tas-status` asserts it was enforced. -->

| NFR ID | Category | Target | Strategy | Notes |
|--------|----------|--------|----------|-------|
| NFR-001 | Latency | P99 < 300ms | Redis cache L2, read replicas | Cache TTL 5m |
| NFR-002 | Availability | 99.9% | Active-Active, 2 AZs | Health check interval 10s |

---

## 12. Deployment Topology

<!-- Proposal sub-artifact (from PRD.NFR + SE). Answers: "Where do components run in the infrastructure?"
  Required:
  - Infrastructure diagram: regions, AZs, VPC/subnets, load balancers, entry points
  - Component-to-infrastructure mapping: service X → ECS Fargate, DB → RDS Multi-AZ, ...
  - Traffic entry points: CDN → ALB → API Gateway → Service flow
  - Environment matrix: dev / staging / prod — differences in scale, config, isolation — table (Component | Dev | Staging | Prod)
  Should have: network topology (public/private/data subnets + routing), CI/CD pipeline overview (build → test → deploy + approval gates), orchestration config if K8s/ECS
  Mermaid flowchart with subgraph per environment tier or network zone. -->

---

## 13. Architectural Decisions (ADR Index)

<!-- Proposal-mandated (gap table §11: "đổi ADR inline table thành ADR Index với link"). This is an INDEX, not the decisions themselves.
  Each ADR is an immutable standalone file under docs/adr/ created by `/tas-adr` (template .tas/templates/ADR.md). Once Accepted an ADR is never edited — a change creates a new ADR that supersedes it.
  This table only links to those files and shows current status. Add a row when `/tas-adr` creates an ADR; update Status when one is superseded.
  Status values: Proposed | Accepted | Deprecated | Superseded -->

| ID | Title | Status | Date | Link |
|----|-------|--------|------|------|
| ADR-001 | {Payment provider selection} | Accepted | {date} | [docs/adr/ADR-001.md](adr/ADR-001.md) |

---

## 14. Risks & Mitigation

<!-- Interim — the proposal governs risks in a separate Risk Record living document (out of scope this round). Until that exists, architectural risks are tracked here.
  Risk, Impact (H/M/L), Probability (H/M/L), Mitigation, Owner. Sort by Impact × Probability descending. -->

| Risk | Impact | Probability | Mitigation | Owner |
|------|--------|-------------|------------|-------|

---

## Changelog

| Date | Version | Changes | Author |
|------|---------|---------|--------|
| [Date] | 1.0 | Initial draft | [Name] |

---

## AI Usage Log

| # | Date | Command | Input (est.) | Output (est.) |
|---|------|---------|-------------|---------------|
| 1 | [Date] | /tas-sad | ~{N}k | ~{N}k |
| **Total** | | | **~{N}k** | **~{N}k** |
