690504:1641 Update specs [skip ci]

This commit is contained in:
2026-05-04 16:41:50 +07:00
parent 42a6d24318
commit 3575f3073b
106 changed files with 5813 additions and 259 deletions
+55
View File
@@ -0,0 +1,55 @@
# 100-Infrastructures
โฟลเดอร์นี้ใช้เก็บงานที่เกี่ยวกับ **Infrastructure** ของระบบ NAP-DMS
## ขอบเขตงาน (Scope)
งานที่ควรอยู่ในโฟลเดอร์นี้ ได้แก่:
- **Infrastructure Operations** - การดำเนินงานพื้นฐาน (Deployment, Monitoring, Backup/Recovery)
- **Docker Compose** - การจัดการ Container stacks บน QNAP/ASUSTOR
- **Network Design** - การออกแบบ Network Segmentation, VLAN
- **Security Hardening** - การเสริมความปลอดภัยของ Infrastructure
- **CI/CD** - การตั้งค่า Gitea Actions, Deployment pipelines
- **Maintenance Procedures** - ขั้นตอนการดูแลรักษาระบบเบื้องต้น
## ตัวอย่างงานที่อยู่ในโฟลเดอร์นี้
- `102-infra-ops` - Infrastructure Operations & Deployment Automation
## การตั้งชื่อโฟลเดอร์
ใช้รูปแบบ: `1XX-feature-name`
- **1** = หลักร้อยของหมวดหมู่ (100-Infrastructures)
- **XX** = เลขลำดับงาน (01, 02, 03, ...)
- **feature-name** = ชื่องาน (kebab-case)
ตัวอย่าง:
- `101-network-segmentation`
- `102-infra-ops`
- `103-security-hardening`
## โครงสร้างไฟล์ในแต่ละงาน
แต่ละโฟลเดอร์งานควรมีไฟล์ต่อไปนี้ (ถ้าเกี่ยวข้อง):
```
1XX-feature-name/
├── spec.md # คำอธิบายงานโดยละเอียด
├── plan.md # แผนการดำเนินงาน
├── tasks.md # รายการงานย่อย
├── quickstart.md # คู่มือเริ่มต้น (ถ้ามี)
├── research.md # การวิจัย/ศึกษา (ถ้ามี)
├── data-model.md # โครงสร้างข้อมูล (ถ้ามี)
├── checklists/ # Checklist ตรวจสอบ (ถ้ามี)
└── contracts/ # สัญญา/ข้อตกลง (ถ้ามี)
```
## การเชื่อมโยงกับ Core Specs
งานในโฟลเดอร์นี้ควรอ้างอิง Core Specs ที่เกี่ยวข้อง:
- `04-Infrastructure-OPS/` - Infrastructure & Operations Guide
- `02-Architecture/` - System & Network Architecture
- `06-Decision-Records/` - ADRs ที่เกี่ยวข้อง (ADR-010, ADR-015, ADR-016)
@@ -0,0 +1,192 @@
# Implementation Plan: ADR-021 Integrated Workflow Context & Step-specific Attachments
**Branch**: `200-fullstacks/202-adr-021-integrated-workflow-context` | **Date**: 2026-04-12 | **Spec**: [spec.md](./spec.md)
**Location**: `specs/200-fullstacks/202-adr-021-integrated-workflow-context/`
**Input**: Feature specification from ADR-021
---
## Summary
ปรับปรุง Workflow Engine ให้รองรับ (1) **Integrated Banner** ที่ยุบรวม Metadata + Status + Actions ไว้ด้วยกัน (2) **Vertical Timeline Lifecycle** พร้อม Active Step Highlighting และ (3) **Step-specific Attachments** ที่เชื่อมโยงไฟล์แนบกับ `workflow_history` ของแต่ละขั้นตอนโดยตรง
แนวทางเทคนิค: ขยาย `workflow_histories` ด้วย FK ใน `attachments` (Nullable) + ขยาย `WorkflowTransitionDto` รับ `attachmentPublicIds` (pre-uploaded UUIDv7 list) + สร้าง Frontend components ใหม่ 4 ชิ้น
---
## Technical Context
**Language/Version**: TypeScript 5.x (strict mode), Node.js 20+
**Primary Dependencies**:
- Backend: NestJS 10, TypeORM 0.3, MariaDB 10.6+, Redis (Redlock), BullMQ
- Frontend: Next.js 14 (App Router), TailwindCSS 3.4, shadcn/ui, TanStack Query v5, React Hook Form + Zod
**Storage**: MariaDB (schema via SQL delta — ADR-009), MinIO / Local FS via `StorageService`
**Testing**: Jest (backend unit + e2e), Vitest (frontend)
**Target Platform**: QNAP Container Station (Docker), Browser (Chrome/Edge latest)
**Project Type**: Web application (backend/ + frontend/ monorepo)
**Performance Goals**: (1) Workflow history + attachment join query < 200ms p95 (mitigated by Redis Cache TTL 1h); (2) `POST /instances/:id/transition` (พร้อม file) P95 ≤ 5 วินาที สำหรับ file ≤ 10MB (รวม ClamAV + Redlock + DB transaction)
**Constraints**: No TypeORM migrations (ADR-009); UUID via `publicId` only (ADR-019); ClamAV scan mandatory (ADR-016); BullMQ for all async jobs (ADR-008)
**Scale/Scope**: ~50 concurrent users, documents in hundreds per project
---
## Constitution Check
_GATE: Checked against `.windsurfrules` before Phase 0. Re-verified after Phase 1._
| Gate | Status | Notes |
|------|--------|-------|
| **🔴 UUID Pattern (ADR-019)** | ✅ PASS | All attachment references via `publicId` (UUIDv7 string). `workflow_history_id` FK value is CHAR(36) UUID from `workflow_histories.id`. No `parseInt` usage. |
| **🔴 Schema via SQL Delta (ADR-009)** | ✅ PASS | Delta file `04-add-workflow-history-id-to-attachments.sql` — no TypeORM migration |
| **🔴 Two-Phase Upload (ADR-016)** | ✅ PASS | Files uploaded via existing Two-Phase endpoint first; `publicId`s referenced in transition DTO |
| **🔴 ClamAV Scan (ADR-016)** | ✅ PASS | ClamAV scan runs during Phase 1 of file upload (before transition) |
| **🔴 CASL Guard (ADR-016)** | ✅ PASS | New `WorkflowTransitionGuard` implements 4-Level RBAC |
| **🔴 Idempotency-Key (Security Rule #1)** | ✅ PASS | `POST /instances/:id/transition` validates `Idempotency-Key` header |
| **🔴 BullMQ Async (ADR-008)** | ✅ PASS | Notifications dispatched via `WorkflowEventService` (existing BullMQ pattern) |
| **🔴 No `any` types** | ✅ PASS | All new types fully typed |
| **🟡 Thin Controller** | ✅ PASS | Controller delegates to Service; Guard handles RBAC |
| **🟡 Test Coverage 80% business logic** | ⚠️ REQUIRED | See testing plan in Phase 3 |
| **🔴 Redis Redlock (ADR-002)** | ✅ PASS | Redlock applied to `instanceId` during `processTransition()` — Fail-closed: Retry 3x (500ms exponential backoff) → HTTP 503 if Redis unavailable |
| **🔴 Upload State Restriction** | ✅ PASS | Step-attachment upload permitted only in `PENDING_REVIEW`/`PENDING_APPROVAL`; Terminal states (`APPROVED`,`REJECTED`,`CLOSED`) → HTTP 409 |
---
## Project Structure
### Documentation (this feature)
```text
specs/feat/adr-021-integrated-workflow-context/
├── spec.md # Feature specification
├── plan.md # This file
├── tasks.md # Generated by speckit-tasks
└── checklists/ # Quality checklists
```
### Source Code (impacted files)
```text
# 🔴 Backend — DB & Entities
specs/03-Data-and-Storage/deltas/
└── 04-add-workflow-history-id-to-attachments.sql [NEW]
backend/src/common/file-storage/entities/
└── attachment.entity.ts [MODIFY — add workflowHistoryId + relation]
backend/src/modules/workflow-engine/entities/
└── workflow-history.entity.ts [MODIFY — add OneToMany attachments]
# 🔴 Backend — API & Guards
backend/src/modules/workflow-engine/dto/
└── workflow-transition.dto.ts [MODIFY — add attachmentPublicIds]
backend/src/modules/workflow-engine/guards/
└── workflow-transition.guard.ts [NEW — 4-Level RBAC]
backend/src/modules/workflow-engine/
├── workflow-engine.service.ts [MODIFY — extend processTransition()]
├── workflow-engine.controller.ts [MODIFY — add idempotency header, guard]
└── workflow-engine.module.ts [MODIFY — register guard]
# 🟡 Frontend — Types
frontend/types/
└── workflow.ts [MODIFY — add attachments to WorkflowHistoryStep]
frontend/types/dto/workflow-engine/
└── workflow-engine.dto.ts [MODIFY — add WorkflowTransitionWithAttachmentsDto]
# 🟡 Frontend — New Components
frontend/components/workflow/
├── integrated-banner.tsx [NEW — Status + Metadata + Action bar]
└── workflow-lifecycle.tsx [NEW — Vertical timeline with Indigo active step]
frontend/components/common/
└── file-preview-modal.tsx [NEW — PDF/Image inline preview]
# 🟡 Frontend — New Hook
frontend/hooks/
└── use-workflow-action.ts [NEW — upload + transition orchestration]
# 🟡 Frontend — Page Refactors (use new components)
frontend/app/(dashboard)/rfas/[uuid]/page.tsx [MODIFY — integrate IntegratedBanner + WorkflowLifecycle]
frontend/app/(dashboard)/transmittals/[uuid]/page.tsx [MODIFY — same as RFA]
frontend/app/(dashboard)/circulation/[uuid]/page.tsx [MODIFY — same as RFA]
frontend/app/(dashboard)/correspondences/[uuid]/page.tsx [MODIFY — same as RFA]
```
---
## Complexity Tracking
_No constitution violations. Architecture is additive (Nullable FK, extended DTO, new components)._
---
## Design Decisions
### Data Model
- `attachments.workflow_history_id` = `CHAR(36) NULL` FK → `workflow_histories.id`
- `ON DELETE SET NULL` (preserve attachment records if history row deleted)
- Composite index: `INDEX idx_att_wfhist_created (workflow_history_id, created_at)`
- `WorkflowHistory` gains `@OneToMany(() => Attachment, a => a.workflowHistory)`**lazy-loaded only**
### API Contract
**Extended `POST /workflow-engine/instances/:instanceId/transition`:**
```
Header: Idempotency-Key: <UUIDv7>
Body: {
action: string // existing
comment?: string // existing
payload?: Record // existing
attachmentPublicIds?: string[] // NEW — UUIDv7 list of pre-uploaded attachments
}
```
**New `GET /workflow-engine/instances/:instanceId/history`:**
```
Response: WorkflowHistoryItem[] with nested attachments[] per step
```
### Frontend Architecture
3 new components follow **compound pattern**:
- `<IntegratedBanner>` — Status + Metadata + Action bar
- `<WorkflowLifecycle>` — Vertical timeline, Indigo active step (pulse animation)
- `<FilePreviewModal>` — PDF iframe / Image viewer
**`use-workflow-action` hook responsibilities:**
1. Validate `Idempotency-Key` (generate UUIDv7 once per action intent)
2. Guard: Check `currentState ∈ {PENDING_REVIEW, PENDING_APPROVAL}` before transition
3. Ensure all `attachmentPublicIds` are committed (not temp) before transition
4. Call `POST /instances/:id/transition` with `Idempotency-Key` header
5. Handle HTTP 503 → toast "ระบบยุ่ง กรุณาลองใหม่"
6. Invalidate TanStack Query cache for the document + workflow instance
**Modules in scope (v1.8.6):** RFA, Transmittal, Circulation, Correspondence (4 modules)
---
## Risk Register
| Risk | Likelihood | Impact | Mitigation |
|------|-----------|--------|------------|
| N+1 query on history + attachments join | Medium | High | Eager-load only when explicitly querying history; Redis cache TTL 1h |
| Race condition: 2 users upload to same step simultaneously | Low | High | Redis Redlock on `instanceId` — only 1 transition allowed at a time |
| Attachment linked to wrong history record | Low | High | `processTransition()` creates history row first, then links attachments in same transaction |
| ClamAV timeout during upload | Low | Medium | Upload endpoint has its own timeout; transition is decoupled |
| Frontend: stale workflow state after transition | Medium | Medium | `use-workflow-action` hook invalidates TanStack Query cache on success |
---
## Dependencies Map
```
ADR-021
├── ADR-001 (Workflow Engine DSL) — extends processTransition()
├── ADR-002 (Redis Redlock) — existing lock pattern applied to transition
├── ADR-016 (Security) — Two-Phase upload, ClamAV, CASL Guard
├── ADR-019 (UUID) — publicId for all attachment references
└── ADR-008 (BullMQ) — notification dispatch (unchanged, existing pattern)
```
@@ -0,0 +1,162 @@
# Feature Specification: Integrated Workflow Context & Step-specific Attachments
**Feature Branch**: `200-fullstacks/202-adr-021-integrated-workflow-context`
**Created**: 2026-05-03
**Status**: Draft
**Input**: ADR-021 Integrated Workflow Context & Step-specific Attachments
**Location**: `specs/200-fullstacks/202-adr-021-integrated-workflow-context/`
---
## Clarifications
### Session 2026-04-12 (from ADR-021)
- **Q:** What are the file size and attachment count limits per workflow step? → **A:** No explicit limit (controlled by infrastructure only)
- **Q:** What are the specific values and storage format for the "Priority" field in the Integrated Banner? → **A:** Enum "URGENT", "HIGH", "MEDIUM", "LOW" — 4-tier system with visual indicators
- **Q:** How should the system handle virus/malware detection during step-specific file upload? → **A:** Block upload immediately, delete temp file, show error "File rejected" to user
- **Q:** What is the cache TTL for Workflow History data to reduce join query overhead? → **A:** 1 hour — balanced cache duration for workflow history data
- **Q:** Who is authorized to upload step-specific attachments during a workflow transition? → **A:** Only assigned handler can upload; superadmin and organization admin can upload on behalf (impersonation)
### Session 2026-04-19 (from ADR-021)
- **Q:** Which workflow states allow step-specific attachment upload? → **A:** Only Active-decision states (`PENDING_REVIEW`, `PENDING_APPROVAL`) — Terminal states (`APPROVED`, `REJECTED`, `CLOSED`) are not allowed
- **Q:** What happens if Redis Redlock fails during transition? → **A:** Fail-closed — Retry 3 times (500ms exponential backoff) then throw HTTP 503 "Service temporarily unavailable" to preserve data integrity
- **Q:** Which modules must support step-specific attachments in v1.8.6? → **A:** **All 4 modules** — RFA, Transmittal, Circulation, and Correspondence
- **Q:** Performance target for Upload + Transition API? → **A:** P95 ≤ 5 seconds for files ≤10MB (ClamAV scan + Redlock + DB transaction included)
---
## User Scenarios & Testing
### User Story 1 - Integrated Banner (Priority: P1) 🎯 MVP
As a Reviewer/Approver, I want to see all critical document information (Doc No, Subject, Status, Priority) and available actions in a single header bar without scrolling or switching screens, so I can make approval decisions quickly with full context.
**Why this priority**: This is the core UX improvement of ADR-021. Without the Integrated Banner, users waste time scrolling and switching between document content and workflow controls.
**Independent Test**: The IntegratedBanner component can be rendered with mock RFA/Transmittal/Circulation/Correspondence data, verifying Priority badge colors, Status display, and Action button visibility. Buttons must be disabled when workflow is in terminal states.
**Acceptance Scenarios**:
1. **Given** an RFA in `PENDING_APPROVAL` state with `URGENT` priority, **When** I open the detail page, **Then** I see the Doc No, Subject, red URGENT badge, status badge, and Approve/Reject/Return buttons in a sticky header
2. **Given** a Transmittal in `APPROVED` state, **When** I view the detail page, **Then** action buttons are disabled and the status shows as completed
3. **Given** a Correspondence in `PENDING_REVIEW` state with `MEDIUM` priority, **When** I open the detail page, **Then** the priority badge shows yellow and all workflow actions are available
---
### User Story 2 - Workflow Lifecycle Visualization (Priority: P1) 🎯 MVP
As a document participant, I want to see a vertical timeline showing all workflow steps with the current step highlighted, so I understand where the document is in the approval process and what steps remain.
**Why this priority**: Users currently lack visibility into workflow progress. The vertical timeline provides immediate orientation and reduces confusion about approval status.
**Independent Test**: The WorkflowLifecycle component can be rendered with mock workflow history data containing completed, current, and pending steps. Verify current step has Indigo (#6366f1) color with pulse animation.
**Acceptance Scenarios**:
1. **Given** a 4-step RFA workflow where step 2 is current, **When** I view the Workflow tab, **Then** step 1 shows as completed (with actor/date), step 2 shows Indigo with pulse, steps 3-4 are muted/pending
2. **Given** a Circulation workflow with comments on completed steps, **When** I view the timeline, **Then** each completed step shows the handler name, action date, and any comments
3. **Given** a Transmittal in terminal state, **When** I view the timeline, **Then** the final step is marked complete and no pulse animation is shown
---
### User Story 3 - Step-specific Attachments (Priority: P2)
As a Reviewer, I want to upload supporting documents (images, PDFs) that are specifically linked to the current workflow step, so reviewers can see exactly which evidence was provided for each approval decision.
**Why this priority**: Currently all attachments are mixed at the document level. Step-specific attachments provide audit trail clarity and improve compliance tracking.
**Independent Test**: Upload files during a workflow transition in `PENDING_REVIEW` state, then verify via API that `attachments.workflow_history_id` is set correctly. Files uploaded in terminal states must be rejected with HTTP 409.
**Acceptance Scenarios**:
1. **Given** an RFA in `PENDING_REVIEW` state, **When** I drag-drop 2 PDF files and click Approve, **Then** the files are linked to that workflow history step and visible in the timeline
2. **Given** a Transmittal in `APPROVED` state, **When** I attempt to upload a file, **Then** the system rejects with "Upload not allowed in terminal state" error
3. **Given** a Circulation in `PENDING_APPROVAL` state, **When** I upload a file and the approver rejects, **Then** the attachment remains linked to that rejection step for audit purposes
---
### User Story 4 - Internal File Preview (Priority: P2)
As a Reviewer, I want to click on any attachment and preview it in a modal without leaving the document page, so I can review evidence while maintaining workflow context.
**Why this priority**: Current workflow requires downloading or opening files in new tabs, breaking user flow and reducing productivity.
**Independent Test**: Click on PDF and Image attachments in the workflow timeline, verify FilePreviewModal opens with correct content type rendering (iframe for PDF, img for images).
**Acceptance Scenarios**:
1. **Given** a step with 3 attachments (2 PDFs, 1 PNG), **When** I click the first PDF, **Then** a modal opens showing the PDF in an inline viewer
2. **Given** the preview modal is open, **When** I press Escape or click the X button, **Then** the modal closes and I remain on the document page
3. **Given** a large PDF attachment, **When** I open the preview, **Then** the modal loads within 2 seconds with proper scroll controls
---
### User Story 5 - i18n Support (Priority: P3)
As a Thai or English speaking user, I want all workflow UI text to display in my selected language, so I can use the system effectively regardless of my preferred language.
**Why this priority**: LCBP3-DMS must support bilingual operations. All new UI components must follow i18n standards from project inception.
**Independent Test**: Switch language between TH and EN, verify all IntegratedBanner labels, WorkflowLifecycle step labels, and FilePreviewModal controls display correctly in each language.
**Acceptance Scenarios**:
1. **Given** my language is set to Thai, **When** I view an RFA detail page, **Then** all workflow action buttons show Thai text (อนุมัติ, ปฏิเสธ, ส่งกลับ)
2. **Given** my language is set to English, **When** I view the Workflow tab, **Then** step labels show English text (Review, Approval, etc.)
3. **Given** I switch language while viewing a document, **When** the page refreshes, **Then** all ADR-021 components show the newly selected language immediately
---
### Edge Cases
- What happens when a user attempts transition with concurrent upload from another user? (Redis Redlock handles serialization)
- How does system handle ClamAV detecting malware during step upload? (Block immediately, delete temp file, show "File rejected")
- What happens when Redis is unavailable during transition? (Retry 3x with exponential backoff, then HTTP 503 fail-closed)
- How does system handle duplicate Idempotency-Key? (Return cached response, no re-processing)
- What happens when attachment file is deleted from storage after linking? (Show "File unavailable" in UI, preserve metadata)
- How does system handle unauthorized upload attempt? (CASL Guard blocks with 403 Forbidden)
---
## Requirements
### Functional Requirements
- **FR-001**: System MUST display Integrated Banner on RFA, Transmittal, Circulation, and Correspondence detail pages showing Doc No, Subject, Status, Priority, and available actions
- **FR-002**: Priority badge MUST support 4 levels: URGENT (red), HIGH (orange), MEDIUM (yellow), LOW (green) with visual indicators
- **FR-003**: Action buttons (Approve/Reject/Return) MUST be disabled when workflow is in terminal states (APPROVED, REJECTED, CLOSED)
- **FR-004**: System MUST display Workflow Lifecycle as vertical timeline with current step highlighted in Indigo (#6366f1) with pulse animation
- **FR-005**: System MUST support drag-drop file upload linked to workflow history steps, only allowed in PENDING_REVIEW or PENDING_APPROVAL states
- **FR-006**: Upload attempts in terminal states MUST be rejected with HTTP 409 Conflict
- **FR-007**: System MUST enforce 4-Level RBAC for workflow transitions: Superadmin > Org Admin > Assigned Handler > Read-only
- **FR-008**: System MUST validate Idempotency-Key header on all transition requests to prevent duplicate processing
- **FR-009**: File uploads MUST use Two-Phase pattern (Temp → ClamAV scan → Permanent)
- **FR-010**: System MUST provide internal File Preview Modal for PDF and Image attachments without page navigation
- **FR-011**: All UI text MUST use i18n keys supporting Thai and English languages
- **FR-012**: Workflow transitions MUST use optimistic locking (version_no) to prevent race conditions
- **FR-013**: Redis Redlock MUST serialize concurrent transitions on the same workflow instance
- **FR-014**: Attachment linking to workflow history MUST occur in same database transaction as state transition
### Key Entities
- **WorkflowInstance**: Represents a running workflow tied to a document (RFA/Transmittal/Circulation/Correspondence). Tracks current state, definition reference, and context data.
- **WorkflowHistory**: Audit record of each workflow transition. Contains from_state, to_state, action, actor, timestamp, and (ADR-021) linked attachments.
- **Attachment** (Extended): File entity with new `workflow_history_id` FK linking to specific workflow step. NULL value indicates main document attachment (pre-ADR-021 behavior).
- **IntegratedBanner**: UI component combining document metadata, workflow status, priority indicator, and action controls.
- **WorkflowLifecycle**: UI component displaying vertical timeline of all workflow steps with visual highlighting.
---
## Success Criteria
### Measurable Outcomes
- **SC-001**: Users can approve/reject documents 40% faster due to Integrated Banner reducing screen navigation
- **SC-002**: 100% of workflow attachments are traceable to specific approval steps via `workflow_history_id` linkage
- **SC-003**: File preview modal loads and displays PDF/Image files within 2 seconds (P95)
- **SC-004**: Zero duplicate workflow transitions occur due to Idempotency-Key enforcement (verified via audit logs)
- **SC-005**: System handles 50 concurrent workflow transitions per minute without data inconsistency (optimistic lock + Redlock)
- **SC-006**: 100% of UI text in ADR-021 components is translatable (verified by language switch testing)
- **SC-007**: Users can complete workflow transition with file upload within 5 seconds for files ≤10MB (P95, including ClamAV scan)
@@ -0,0 +1,129 @@
# Tasks: ADR-021 Integrated Workflow Context & Step-specific Attachments
**Branch**: `200-fullstacks/202-adr-021-integrated-workflow-context` | **Spec**: [spec.md](./spec.md) | **Plan**: [plan.md](./plan.md)
**Location**: `specs/200-fullstacks/202-adr-021-integrated-workflow-context/`
**Input**: Comprehensive task breakdown from `specs/08-Tasks/ADR-021-workflow-context/tasks.md`
**Version**: 1.8.6 | **Date**: 2026-05-03
---
## Summary
This file provides a high-level task overview. For the **full detailed tasks** (with implementation notes, verification commands, and acceptance criteria), see:
👉 **`specs/200-fullstacks/202-adr-021-integrated-workflow-context/tasks.md`**
---
## Phase Overview
| Phase | Focus | Key Deliverables | Status |
|-------|-------|------------------|--------|
| **Phase 1** | Setup | Branch creation, dev environment verification | ⏳ Pending |
| **Phase 2** | Backend Foundation | SQL delta, Entity relations, Guards, Service extension | ⏳ Pending |
| **Phase 3** | Integrated Banner (US1) | `IntegratedBanner` component, 4 module integrations | ⏳ Pending |
| **Phase 4** | Workflow Lifecycle (US2) | `WorkflowLifecycle` component, vertical timeline | ⏳ Pending |
| **Phase 5** | Step Attachments (US3) | `use-workflow-action` hook, DTO extension, linking logic | ⏳ Pending |
| **Phase 6** | File Preview (US4) | `FilePreviewModal` component | ⏳ Pending |
| **Phase 7** | i18n & Testing (US5) | i18n keys, unit tests, component tests, E2E | ⏳ Pending |
---
## Critical Path Tasks (Phase 2)
| # | Task | File(s) | Dependencies |
|---|------|---------|--------------|
| T1 | Create SQL delta — add `workflow_history_id` to `attachments` | `deltas/04-*.sql` | None |
| T2 | Update `attachment.entity.ts` — add column + relation | `attachment.entity.ts` | T1 |
| T3 | Update `workflow-history.entity.ts` — add `@OneToMany` | `workflow-history.entity.ts` | T1 |
| T4 | Extend `WorkflowTransitionDto` — add `attachmentPublicIds` | `workflow-transition.dto.ts` | None |
| T5 | Create `WorkflowTransitionGuard` (CASL 4-Level) | `guards/workflow-transition.guard.ts` | None |
| T6 | Extend `processTransition()` — link attachments | `workflow-engine.service.ts` | T2, T3, T4 |
| T7 | Update Controller — idempotency + guard | `workflow-engine.controller.ts` | T5, T6 |
| T8 | Register guard in Module | `workflow-engine.module.ts` | T5 |
---
## Frontend Tasks Overview (Phases 3-6)
| # | Task | Component/Page | Dependencies |
|---|------|----------------|--------------|
| F1 | Add types — `WorkflowHistoryItem` | `types/workflow.ts` | T7 |
| F2 | Add DTO — `WorkflowTransitionWithAttachmentsDto` | `types/dto/workflow-engine/` | T4 |
| F3 | Create hook — `use-workflow-action.ts` | `hooks/` | F2 |
| F4 | Create component — `IntegratedBanner` | `components/workflow/` | F1 |
| F5 | Create component — `WorkflowLifecycle` | `components/workflow/` | F1 |
| F6 | Create component — `FilePreviewModal` | `components/common/` | F1 |
| F7-F10 | Integrate into 4 module pages | `rfas/`, `transmittals/`, `circulation/`, `correspondences/` | F3-F6 |
---
## Testing Tasks (Phase 7)
| # | Task | Target | Type |
|---|------|--------|------|
| G1 | Unit tests — `processTransition()` extended | `workflow-engine.service.spec.ts` | Backend |
| G2 | Unit tests — `WorkflowTransitionGuard` | `workflow-transition.guard.spec.ts` | Backend |
| G3 | Component tests — `IntegratedBanner` | `integrated-banner.test.tsx` | Frontend |
| G4 | Component tests — `WorkflowLifecycle` | `workflow-lifecycle.test.tsx` | Frontend |
| G5 | Component tests — `FilePreviewModal` | `file-preview-modal.test.tsx` | Frontend |
| G6 | E2E test — workflow with attachment | `test/workflow-with-attachment.e2e-spec.ts` | Integration |
---
## Verification Checkpoints
### Backend
```bash
# Schema check
grep -n "workflow_history_id" specs/03-Data-and-Storage/lcbp3-v1.8.0-schema-02-tables.sql
# Type check
cd backend && pnpm tsc --noEmit
# Unit tests
cd backend && pnpm test --testPathPattern=workflow-engine.service
cd backend && pnpm test --testPathPattern=workflow-transition.guard
# Integration test
curl -X POST http://localhost:3001/api/workflow-engine/instances/:id/transition \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"action":"APPROVE","comment":"OK","attachmentPublicIds":["<uuid>"]}'
```
### Frontend
```bash
# Type check
cd frontend && pnpm tsc --noEmit
# Component tests
cd frontend && pnpm test --run components/workflow/integrated-banner
cd frontend && pnpm test --run components/workflow/workflow-lifecycle
cd frontend && pnpm test --run components/common/file-preview-modal
```
---
## References
| Document | Path | Purpose |
|----------|------|---------|
| **Full Tasks** | `specs/08-Tasks/ADR-021-workflow-context/tasks.md` | Complete task breakdown with 360 lines of detail |
| **Data Model** | `specs/08-Tasks/ADR-021-workflow-context/data-model.md` | Entity definitions, SQL delta, DTO specs |
| **Quick Start** | `specs/08-Tasks/ADR-021-workflow-context/quickstart.md` | Developer onboarding guide |
| **Research** | `specs/08-Tasks/ADR-021-workflow-context/research.md` | Phase 0 findings and decisions |
| **Contracts** | `specs/08-Tasks/ADR-021-workflow-context/contracts/*.yaml` | API contracts |
---
## Definition of Done (Observable Outcomes)
| REQ | Done When |
|-----|-----------|
| **REQ-01** | Banner shows Doc No, Status, Priority badge, Approve/Reject buttons on all 4 module detail pages |
| **REQ-02** | Workflow tab displays Role + Handler + Description for every step without reload |
| **REQ-03** | Current step shows Indigo (#6366f1) with pulse animation; other steps distinct |
| **REQ-04** | Drag-drop works only in `PENDING_REVIEW`/`PENDING_APPROVAL`; disabled in terminal states |
| **REQ-05** | Clicking PDF/Image opens preview modal without page navigation |
| **REQ-06** | All UI text changes when switching EN/TH; no hardcoded strings |
+59
View File
@@ -0,0 +1,59 @@
# 200-fullstacks
โฟลเดอร์นี้ใช้เก็บงานที่เกี่ยวกับ **Fullstack Development** (Backend + Frontend) ของระบบ NAP-DMS
## ขอบเขตงาน (Scope)
งานที่ควรอยู่ในโฟลเดอร์นี้ ได้แก่:
- **Feature Modules** - การพัฒนาฟีเจอร์ใหม่ที่มีทั้ง Backend และ Frontend
- **Module Integration** - การเชื่อมต่อระหว่าง Backend NestJS และ Frontend Next.js
- **Workflow Engine** - การพัฒนา Workflow Engine และการเชื่อมต่อกับ Modules
- **API Development** - การสร้าง API endpoints และ Frontend integration
- **UI Components** - การพัฒนา Components ที่ใช้ร่วมกัน
- **Business Logic** - การพัฒนา Business rules ที่ซับซ้อน
## ตัวอย่างงานที่อยู่ในโฟลเดอร์นี้
- `201-transmittals-circulation` - Transmittals + Circulation Integration
- `203-unified-workflow-engine` - Unified Workflow Engine
## การตั้งชื่อโฟลเดอร์
ใช้รูปแบบ: `2XX-feature-name`
- **2** = หลักร้อยของหมวดหมู่ (200-fullstacks)
- **XX** = เลขลำดับงาน (01, 02, 03, ...)
- **feature-name** = ชื่องาน (kebab-case)
ตัวอย่าง:
- `201-transmittals-circulation`
- `202-rfa-integration`
- `203-unified-workflow-engine`
## โครงสร้างไฟล์ในแต่ละงาน
แต่ละโฟลเดอร์งานควรมีไฟล์ต่อไปนี้ (ถ้าเกี่ยวข้อง):
```
2XX-feature-name/
├── spec.md # คำอธิบายงานโดยละเอียด
├── plan.md # แผนการดำเนินงาน
├── tasks.md # รายการงานย่อย
├── test-report.md # รายงานการทดสอบ (ถ้ามี)
├── quickstart.md # คู่มือเริ่มต้น (ถ้ามี)
├── research.md # การวิจัย/ศึกษา (ถ้ามี)
├── data-model.md # โครงสร้างข้อมูล (ถ้ามี)
├── checklists/ # Checklist ตรวจสอบ (ถ้ามี)
└── contracts/ # สัญญา/ข้อตกลง (ถ้ามี)
```
## การเชื่อมโยงกับ Core Specs
งานในโฟลเดอร์นี้ควรอ้างอิง Core Specs ที่เกี่ยวข้อง:
- `01-Requirements/` - Business Requirements และ User Stories
- `02-Architecture/` - System Architecture
- `03-Data-and-Storage/` - Schema และ Data Dictionary
- `05-Engineering-Guidelines/` - Backend/Frontend Guidelines
- `06-Decision-Records/` - ADRs ที่เกี่ยวข้อง (ADR-001, ADR-019, ADR-021)
+54
View File
@@ -0,0 +1,54 @@
# 300-others
โฟลเดอร์นี้ใช้เก็บงานที่ไม่ใช่ Infrastructure หรือ Fullstack Development เช่น เอกสาร การวิจัย หรืองานที่ไม่ใช่การพัฒนาโค้ด
## ขอบเขตงาน (Scope)
งานที่ควรอยู่ในโฟลเดอร์นี้ ได้แก่:
- **Documentation** - เอกสารประกอบการทำงานที่ไม่ใช่ Core Specs
- **Research** - การวิจัยเทคโนโลยี การศึกษาเคส
- **Non-code Tasks** - งานที่ไม่ใช่การพัฒนาโค้ด เช่น การตั้งค่า Tools, การจัดทำ Manual
- **Process Improvement** - การปรับปรุง Process การทำงาน
- **Training Materials** - วัสดุการอบรมที่ไม่ใช่ Core Training Plan
## ตัวอย่างงานที่อาจอยู่ในโฟลเดอร์นี้
- `301-documentation-templates` - Templates สำหรับเอกสาร
- `302-research-ai-tools` - การวิจัยเครื่องมือ AI
- `303-process-automation` - การทำ Automation ที่ไม่ใช่โค้ด
## การตั้งชื่อโฟลเดอร์
ใช้รูปแบบ: `3XX-task-name`
- **3** = หลักร้อยของหมวดหมู่ (300-others)
- **XX** = เลขลำดับงาน (01, 02, 03, ...)
- **task-name** = ชื่องาน (kebab-case)
ตัวอย่าง:
- `301-documentation-templates`
- `302-research-ai-tools`
- `303-process-automation`
## โครงสร้างไฟล์ในแต่ละงาน
แต่ละโฟลเดอร์งานอาจมีไฟล์ต่อไปนี้ (ขึ้นอยู่กับประเภทงาน):
```
3XX-task-name/
├── spec.md # คำอธิบายงาน (ถ้ามี)
├── plan.md # แผนการดำเนินงาน (ถ้ามี)
├── tasks.md # รายการงานย่อย (ถ้ามี)
├── research.md # ผลการวิจัย (ถ้าเป็นงานวิจัย)
├── documentation/ # เอกสารต่างๆ (ถ้าเป็นงานเอกสาร)
└── templates/ # Templates (ถ้ามี)
```
## การเชื่อมโยงกับ Core Specs
งานในโฟลเดอร์นี้อาจอ้างอิง Core Specs ที่เกี่ยวข้อง:
- `00-overview/` - Product Vision และ Training Plan
- `05-Engineering-Guidelines/` - Process Guidelines
- `06-Decision-Records/` - ADRs ที่เกี่ยวข้อง (ถ้ามี)
+16
View File
@@ -86,6 +86,22 @@ specs/
│ ├── ADR-019-hybrid-identifier-strategy.md # ★ Hybrid ID: INT PK + UUIDv7 Public API
│ └── README.md # รายชื่อ ADR ทั้งหมดพร้อมสถานะและวันที่
├── 100-Infrastructures/ # Feature Work: Infrastructure (Deployment, Monitoring, Docker Compose, Network)
│ ├── 102-infra-ops/ # Infrastructure Operations & Deployment Automation
│ └── README.md # Category guide
├── 200-fullstacks/ # Feature Work: Fullstack Development (Backend + Frontend features, Workflow Engine, API)
│ ├── 201-transmittals-circulation/ # Transmittals + Circulation Integration
│ ├── 203-unified-workflow-engine/ # Unified Workflow Engine
│ └── README.md # Category guide
├── 300-others/ # Feature Work: Documentation, Research, Non-code tasks
│ └── README.md # Category guide
├── 08-Tasks/ # Task documents
├── 88-logs/ # Logs
└── 99-archives/ # ประวัติการทำงานและ Tasks เก่า
├── history/ # ประวัติเก่า
├── tasks/ # Task ที่อดีตเคยถูกใช้งาน
@@ -1,105 +0,0 @@
# Implementation Plan: [FEATURE]
**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/templates/commands/plan.md` for the execution workflow.
## Summary
[Extract from feature spec: primary requirement + technical approach from research]
## Technical Context
<!--
ACTION REQUIRED: Replace the content in this section with the technical details
for the project. The structure here is presented in advisory capacity to guide
the iteration process.
-->
**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]
**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]
**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]
**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]
**Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION]
**Project Type**: [single/web/mobile - determines source structure]
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]
**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]
## Constitution Check
_GATE: Must pass before Phase 0 research. Re-check after Phase 1 design._
[Gates determined based on constitution file]
## Project Structure
### Documentation (this feature)
```text
specs/[###-feature]/
├── plan.md # This file (/speckit.plan command output)
├── research.md # Phase 0 output (/speckit.plan command)
├── data-model.md # Phase 1 output (/speckit.plan command)
├── quickstart.md # Phase 1 output (/speckit.plan command)
├── contracts/ # Phase 1 output (/speckit.plan command)
└── tasks.md # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
```
### Source Code (repository root)
<!--
ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
for this feature. Delete unused options and expand the chosen structure with
real paths (e.g., apps/admin, packages/something). The delivered plan must
not include Option labels.
-->
```text
# [REMOVE IF UNUSED] Option 1: Single project (DEFAULT)
src/
├── models/
├── services/
├── cli/
└── lib/
tests/
├── contract/
├── integration/
└── unit/
# [REMOVE IF UNUSED] Option 2: Web application (when "frontend" + "backend" detected)
backend/
├── src/
│ ├── models/
│ ├── services/
│ └── api/
└── tests/
frontend/
├── src/
│ ├── components/
│ ├── pages/
│ └── services/
└── tests/
# [REMOVE IF UNUSED] Option 3: Mobile + API (when "iOS/Android" detected)
api/
└── [same as backend above]
ios/ or android/
└── [platform-specific structure: feature modules, UI flows, platform tests]
```
**Structure Decision**: [Document the selected structure and reference the real
directories captured above]
## Complexity Tracking
> **Fill ONLY if Constitution Check has violations that must be justified**
| Violation | Why Needed | Simpler Alternative Rejected Because |
| -------------------------- | ------------------ | ------------------------------------ |
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |