690504:1641 Update specs [skip ci]
This commit is contained in:
@@ -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 |
|
||||
Reference in New Issue
Block a user