# NCV DCIMS — NCV Dental Clinical Image Management System

Bằng chứng kiểm bản **0.2.30**, ngày **30/09/2026**. Đã hoàn tất bảy nhóm được chủ hệ thống duyệt và yêu cầu bổ sung bỏ icon trước tiêu đề Cài đặt. Bảng kiểm chuẩn bị bên dưới ghi kết quả trước triển khai. Sau sự cố quyền image, NAS đã migration/activate/sync DSM/smoke thành công, lưu source Dockerfile sửa và operator xác nhận đăng nhập/giao diện bình thường; xem trạng thái chốt cuối tài liệu. Lần kiểm NAS này chưa thay nghiệm thu DR/offsite/reboot hoặc full rebuild source mới.

| Vấn đề đã duyệt | Kết quả sửa | Bằng chứng |
| --- | --- | --- |
| Chia sẻ còn dùng sau xóa ca | Thu hồi link trong transaction xóa; public endpoint kiểm patient/case/branch/session; restore không hồi sinh link. Migration sửa link cũ có parent đã xóa và audit | Unit auth/share/lifecycle; PostgreSQL revocation, object relationship và IDOR |
| Vượt giới hạn đăng nhập đồng thời | Reservation PostgreSQL và lock ngắn theo IP; giới hạn Argon2 hai tác vụ, 16 chờ; gateway limiter nhận cả biến thể hoa/thường và dấu slash | Hai repository gửi 50 reservation đồng thời: 20 nhận, 30 từ chối; queue unit; gateway 100 yêu cầu, 79 bị throttle |
| Dependency có advisory | Cập nhật dependency và lockfile, giữ patch vinext; không thêm Redis | `pnpm audit --json`: từ 95 advisory ở baseline xuống 0 ở lần quét 30/09; build/unit và image Linux đạt |
| Giới hạn 100 bệnh nhân và lọc cục bộ | Server paging 25, count/sort/filter và dropdown theo scope; bác sĩ/dịch vụ khớp cùng ca; tổng trang được ghi đúng nhãn | PostgreSQL 130 hồ sơ, trang 6, filter và cross-user/branch/patient/case; UI trang 5, tìm/lọc hồ sơ 129, 60 hồ sơ đã xóa; E2E 390/768/1440 |
| API thiếu security header | Khai báo lại đủ header ở location API/health để tránh mất inheritance; lỗi vẫn có header | Nginx 1.30.4 TLS local: 200/401/404/413/429/500/502/504 và health; tám header |
| Render watermark lặp gây tải | Cache RAM private 32 MiB/128 ảnh/10 phút; coalesce; hai render và 16 chờ; kiểm quyền trước và sau render/cache, audit mỗi lần trả ảnh | Unit bounded-work/cache, link revoke/expiry/parent; không cache public hoặc ghi ra shared folder |
| API dùng credential database quá mạnh | Tách runtime/migration/backup; API DML, migration sở hữu schema, backup read-only. Job quản trị chạy riêng, password riêng và không log URL | Real PostgreSQL role denial, audit append-only, migration metadata private; migration+seed bằng migration role; dump bằng backup role và restore database giả lập |

## Kiểm bắt buộc

| Kiểm | Kết quả |
| --- | --- |
| `pnpm lint` | PASS |
| `pnpm type-check` | PASS |
| `pnpm test` | 688 PASS, 0 FAIL, 1 SKIP có sẵn: test SSR dashboard trong `dashboard-workspace-contracts.legacy.mjs`. Không đổi skip thành pass; workspace có session đã được kiểm bằng E2E thật |
| `pnpm build` | PASS API và Web |
| PostgreSQL 17.10 database trống | 47 migration và seed PASS với migration role; hai integration suite PASS |
| Linux Node 22.23.1 / pnpm 11.9 | Image integration chạy migration/seed/role/IDOR PASS; image API runtime và Web production build PASS |
| Database có dữ liệu | Thêm bootstrap migration trước lịch sử PASS; template/slot và checksum migration cũ không đổi |
| Backup/restore giả lập | Dump bằng role chỉ đọc, parse và restore database giả lập PASS; không phải restore drill NAS/filesystem |
| Responsive E2E | 390/768/1440 PASS: phân trang, tìm kiếm/lọc sau vị trí 100, hồ sơ đã xóa, sort/filter, Back/Forward và Cài đặt không icon tiêu đề, không tràn ngang |
| Site adapter Volume 2 | Compose thật tương đương override/DSM, tách secret, đúng volume/UID, shell LF/syntax và manifest PASS; giữ nguyên byte chín payload lịch sử; 17 luồng updater thành công/lỗi bằng mock PASS |

Browser Back/Forward nay khôi phục history theo user khi framework tạo lại trang; patient ngoài trang được tải bằng API có authorization, không đưa ID hồ sơ vào URL. Case/session chỉ giữ nếu còn trong response được phép. Các icon điều hướng/nút thao tác không thuộc vùng tiêu đề được yêu cầu bỏ.

## Tài liệu và phạm vi vận hành

Đã đối chiếu task **Di chuyển share folder sang Volume 2**, thread `01a088d3-9f13-7a71-a507-3c5e690851b8`, tổng kết 15/09/2026: NAS báo cáo chạy 0.2.29; project/database/media/ledger/backup trên Volume 2, Docker Root/Container Manager vẫn Volume 1; updater ngoài source có DSM sync. Không suy diễn trạng thái này thành kiểm thực tế ngày 30/09.

Hướng dẫn hiện hành: [Cập nhật Synology 0.2.30](../operations/synology-update-0.2.30.md). Thêm ba secret DB mới, giữ URL quản trị cũ, cài revision adapter có hash/layout/DSM guard; build trước dừng writers, PostgreSQL tiếp tục chạy; provision role trước/sau migration. Không chạy storage-init/chown ledger WriteOnce trong updater. Recovery sau thay ownership/schema cần kế hoạch được chủ hệ thống xác nhận; không tự rollback image hoặc restore.

Log local tại `tmp/security-performance-0.2.30/`: `*-release-gate.log`, `audit-release-gate.json`, `postgres-final.json`, `postgres-final-tests.log`, `linux-integration.log`, `upgrade-bootstrap.log`, `gateway-runtime.json`, `adapter-fixture/checks.json`, `ui/e2e-results.json`, các ảnh UI và log Docker build cuối. Thư mục này chứa fixture/secrets test nên **không đưa vào ZIP**; bằng chứng tổng hợp này nằm trong bộ cài.

Giới hạn: audit 0 là kết quả quét advisory đã biết, không bảo đảm không còn lỗ hổng; chưa đo CPU/RAM/độ trễ trên NAS thật hoặc benchmark lâm sàng. Cache/queue/paging đã giới hạn tài nguyên và có kiểm hành vi, chưa có số liệu để hứa mức tăng tốc cụ thể. PostgreSQL test có cảnh báo deprecation từ pg khi adapter phát query đang bận; không có test thất bại, không chứng minh tương thích pg 9. Backup ngoài NAS, auto-unlock folder mã hóa, Task Scheduler, HTTPS thật và restore/reboot thực tế vẫn thuộc Owner NAS/chủ hệ thống, cần bằng chứng riêng. Không thay retention, legal hold, purge hay quyền ngoài hệ thống.

## Revision tài liệu r1, 30/09/2026

Theo yêu cầu làm rõ ba điểm, guide được viết lại thành 11 bước: đường dẫn upload/giải nén/project riêng, lệnh PowerShell/SSH root, backup source/config trước đổi, dò file credential cũ, kết quả mong đợi và điểm dừng. Đối chiếu guide 0.2.25/0.2.27/0.2.28/0.2.29, NAS-V2-r2 và task Volume 2. Giữ DSM sync, DB external/media/ledger/backup V2, Docker Volume 1, keys và chính sách dữ liệu; lần này cài revision có guard và không dùng rollback chỉ đổi image.

Kiểm local tài liệu: 11 khối shell và hai khối PowerShell đạt syntax; BusyBox Alpine trong container không mạng thực hiện backup/overlay trên fixture giả, giữ cấu hình, loại dependency/cache và từ chối bốn entry private; dò ba dạng đường dẫn file cũ; generator thật tạo ba credential khác nhau và từ chối ghi đè đạt. Bằng chứng `tmp/security-performance-0.2.30/guide-r1-fixture/checks.json`. Không chạy lệnh trên NAS.

ZIP r1 là revision tài liệu, ứng dụng vẫn 0.2.30. Không chạy lại lint/type-check/unit/integration/build/E2E sản phẩm vì không thay source runtime/migration/Compose/updater; giữ kết quả lượt kiểm ở trên. Khi đóng gói kiểm checksum, entry/CRC, nội dung guide và đối chiếu byte tất cả file giữa ZIP gốc/r1; chỉ hai tài liệu guide/evidence được phép khác. Giữ nguyên ZIP gốc để truy nguyên.


## Bổ sung sự cố NAS: quyền image khi migration, 30/09/2026

Operator báo bước source/credential/env/adapter đã đạt, cập nhật build xong và dump/role provision xong nhưng migration job dừng do Corepack EACCES đọc package.json. Chưa có log Prisma migrate hoặc UPDATE_OK; kết quả trước đó không chứng minh NAS thành công.

- Sửa deploy/docker/api.Dockerfile: normalise quyền đọc/traverse của program workspace trước shared migration/runtime; chỉ file/directory chưa đủ quyền được chmod, không cấp quyền ghi hoặc đổi host data.
- Thêm prepare-migration-permissions-0.2.30.sh và guide recovery. Chuẩn bị hai image ứng viên, không retag release, không mount host, SQL/migrate/start/up; kiểm bằng UID site thực, network none và read-only.
- Kiểm shell syntax và 7 trường hợp orchestration với Docker mock/Node guard thật: success, lỗi pnpm/Prisma, writer còn chạy, DB unhealthy, lock tồn tại, env version sai, image package version sai. Tất cả đạt; bằng chứng tmp/permission-recovery-0.2.30/run-09u1ar/checks.json. Đây không phải Linux permission proof.
- 14 contract tests liên quan production secrets/access, Docker/release cleanup đạt, không skip/fail.
- Docker Engine local không có pipe; WSL trả E_ACCESSDENIED. Chưa chạy lại Docker build/integration thực cho bản sửa, Linux UID permission check và NAS activation/smoke chưa có kết quả. Lint/type-check/unit đầy đủ/UI giữ bằng chứng trước sự cố vì không đổi TypeScript hoặc UI; không suy diễn lượt kiểm đó chứng nhận Dockerfile sửa mới.
- Chưa đóng gói ZIP đầy đủ sửa lỗi hoặc đánh dấu phase complete. Kết quả ứng viên trên NAS và hướng tiếp tục migration cần được kiểm riêng; không tự rollback schema hay restore dữ liệu.


### Bổ sung: image ứng viên đã kiểm trên NAS

Ảnh operator gửi tiếp cho thấy MIGRATION_TOOLCHAIN_READ_OK, PERMISSION_IMAGE_OK cho cả ncv-dcims-api-migration và ncv-dcims-api tag 0.2.30-permissions-r2 với UID/GID 1044:65549, PROGRAM_READ_AND_NATIVE_MODULES_OK và PERMISSION_CANDIDATE_IMAGES_READY. Đây là kiểm Linux thực của hai image ứng viên, chưa phải full build từ Dockerfile mới hoặc migration/activation/UAT thành công. Chưa đổi tag phát hành, còn cần kiểm dump/lịch sử migration rồi tiếp tục đúng giai đoạn.


### Bổ sung: kiểm hiện trạng trước resume migration

Ảnh NAS: một update backup khớp .env, dump parse đạt, PostgreSQL healthy; ba writers stopped. _prisma_migrations có 45 bản, unfinished_migrations=0. Chưa restore drill/media backup/UAT. Cung cấp khối migration riêng trong guide recovery, kiểm syntax và 5 Docker-mock fixture orchestration đạt; chưa chạy migration/activation trên NAS.


### Bổ sung: migration tiến về phía trước đạt trên NAS

Ảnh operator xác nhận Prisma migrate deploy áp thành công 3 migration (bootstrap thiếu nguồn checklist, login reservations, revoke deleted case shares), STEP8_MIGRATION_COMPLETE. Source báo 47 migration; chưa kiểm lại tổng hàng lịch sử DB. Cung cấp khối post-migration role provisioning/activation/DSM sync đã kiểm syntax + 7 Docker-mock fixture; chưa nhận kết quả activation/smoke/UAT. Không restore database hoặc rollback ứng dụng.


### Bổ sung: activation và DSM sync đạt trên NAS

Ảnh operator ngày 30/09 xác nhận DB_ROLES_PROVISIONED sau migration; API/Web/Gateway healthy, image API/Web khớp tag phát hành; DSM_COMPOSE_EQUIVALENT_OK (four active services; Volume2 database), DSM_DEFAULT_COMPOSE_SYNCED, NCV_VOLUME2_READY version=0.2.30 và STEP9_APPLICATION_READY_0.2.30. Đây là bằng chứng activation/DSM trên NAS, chưa phải HTTPS smoke/UAT hoặc full build lại từ Dockerfile sửa quyền. Không restore hay rollback dữ liệu.


### Bổ sung: HTTPS smoke đạt trên NAS

Ảnh operator xác nhận NCV_DCIMS_POST_UPDATE_SMOKE_OK qua HTTPS với NCV_DCIMS_PUBLIC_HOST hiện có. Activation/migration/DSM sync và kiểm HTTPS đạt trên NAS. Chưa có xác nhận đăng nhập/UAT UI hoặc full build từ Dockerfile đã sửa. Không coi dump parse là restore drill hoặc xác nhận backup toàn bộ media.


### Chốt trạng thái vận hành NAS sau sửa quyền

Operator đã xác nhận ngày 30/09/2026: migration thành công; provision role sau migration đạt; API/Web/Gateway healthy và đúng image; DSM đồng bộ Volume 2; NCV_DCIMS_POST_UPDATE_SMOKE_OK; Dockerfile source trên NAS đạt DOCKERFILE_FIXED_NO_RESTART và checksum chuẩn hóa 43f6cc05d3a78f6da7bd726a01eeb5a6e5328a99973e6ec4cafa6886b90d98a1; đăng nhập lại và giao diện bình thường. Không chạy lại updater/sinh credential/overlay ZIP cũ trên NAS này chỉ để nhận bộ r2.

Không thực hiện restore/rollback, không thay retention/legal hold/data scope, không sửa IMS. NAS đã kiểm image ứng viên với UID/GID thực, migration, activation và HTTPS; chưa chạy lại full Docker build từ đầu với source Dockerfile mới do engine local không có/WSL không truy cập được. Không đồng nhất đăng nhập/giao diện bình thường với toàn bộ role/scope/share/reboot/offsite/restore UAT trên NAS. Kiểm responsive/IDOR/integration đầy đủ với dữ liệu giả vẫn là bằng chứng chuẩn bị trước sự cố. Source TypeScript/UI/SQL không đổi trong hotfix quyền.


### Chốt source r2 và kiểm bàn giao

Bộ r2 chỉ thêm Dockerfile sửa quyền, công cụ chuẩn bị image và tài liệu incident/update/evidence so với bộ r1; phiên bản ứng dụng vẫn 0.2.30. Guide r2 khôi phục đầy đủ khai báo PROJECT/STAGE/TOOLS trước bước kiểm và dùng File Station giải nén vào source (NAS không có unzip). Thêm kiểm normalized checksum Dockerfile trước overlay để tránh dùng nhầm source chưa sửa.

Kiểm bổ sung: 15 contract tests PASS, shell syntax tất cả khối sh trong guide update/recovery PASS; 7 prepare fixture, 5 migration fixture, 7 activation fixture và 6 persistence fixture đã đạt theo từng lượt. Lint/type-check/unit/integration/build/E2E TypeScript/UI/SQL giữ bằng chứng trước sự cố vì không thay các source đó; chưa chạy lại fresh full Docker build từ source Dockerfile sửa. Hai candidate image với đúng logic chmod đã chạy thật trên NAS, role job/migrate/API activation/smoke đạt. Kết quả checksum/CRC và so byte ZIP r2 được lưu riêng trong receipt release sau khi chạy kiểm artifact; không ghi trước thành PASS.


### Tối ưu hướng dẫn chính r2 theo yêu cầu bàn giao

Guide chính tổng hợp toàn bộ lỗi đã gặp, xác định NAS hiện tại đã xong, hướng dẫn site còn 0.2.29 qua 5 khối NAS sudo sh heredoc tự khai báo và có marker. File Station thay unzip; backup path được lưu từ mktemp, không gõ suffix; credential và năm khóa .env được chuẩn bị tự động, pnpm/Prisma kiểm offline bằng UID thực trước downtime. Installer/updater có guard riêng, giữ Volume 2 và DSM sync. Tách nhật ký recovery khỏi đường cập nhật thông thường.

Kiểm wrapper và body syntax cả 5 khối đạt; 12 fixture source/env đạt: source thành công/sai version/sai Dockerfile/private item/state đã có/tar lỗi, env thành công/duplicate key/credential đã có/toolchain lỗi/generator lỗi/version đã 0.2.30. File I/O, hash và config giữ nguyên được kiểm thật trong fixture; Docker là mock, tar wrapper chỉ chuyển path MSYS cho Windows. Không tuyên bố quy trình gộp mới đã chạy trên NAS. Runtime TypeScript/UI/SQL/Compose/Dockerfile không thay đổi ở lượt tối ưu tài liệu; chỉ cập nhật packaging matcher cho shell isolation. ZIP r2 trước lượt tối ưu được giữ riêng, receipt mới phản ánh bộ r2 hướng dẫn cuối.
