Status
Ảnh chụp tiến độ hiện tại của codebase so với ROADMAP. File này được cập nhật mỗi đợt làm việc; lịch sử chi tiết nằm trong git log.
Cập nhật lần cuối: 29/07/2026
Đang ở đâu
Phase 2 — Pro modules (đang chạy; Phase 1 core đã xong).
Đã xong
- Repo Next.js 16 + TypeScript + Tailwind 4, CI (lint + typecheck + build)
- Typed env bằng Zod — fail fast lúc boot (
src/lib/env.ts) -
PaymentProviderinterface gateway-agnostic (src/lib/payments/types.ts) - Mock provider (dev/CI không cần sandbox)
- VNPay adapter đầy đủ quirk (×100, HMAC-SHA512 sort+encode, GMT+7, JSON RspCode)
- Chuẩn hoá docs: VISION / ROADMAP / STATUS / GLOSSARY / architecture / engineering / legal
- LICENSE thương mại + script chèn copyright header tự động (
scripts/add-headers.ts)
Đã xong (Phase 1)
- MoMo adapter (chữ ký thứ tự cố định, IPN 204)
- ZaloPay adapter (
app_trans_idprefix ngày GMT+7, MAC key2) - Prisma schema: User / Order / Payment (dedupe IPN theo
gatewayTxnId) - NextAuth v5: credentials + Google conditional (Zalo OAuth → Phase 2) + API đăng ký
- Checkout flow end-to-end: tạo đơn → payUrl → IPN idempotent (đối chiếu tiền, chống double-credit) → return page
- Trang mock-checkout giả lập cổng thanh toán
- Test tay end-to-end với mock provider: thành công / thất bại / retry IPN / chữ ký sai / lệch tiền
Đã xong (Phase 2 — đợt 1)
- Trang đăng nhập/đăng ký UI + session trên trang chủ (cookie tên riêng
phostack.session-token— tránh đụng cookie authjs của app localhost khác) - Stripe adapter (Checkout Session qua REST, webhook verify chữ ký trên raw body, VND zero-decimal)
- VietQR: lib build URL ảnh QR + trang demo
/vietqr - E-invoice NĐ70:
InvoiceProvider+ mock + SInvoice/meInvoice adapter; model Invoice (1 đơn ↔ 1 hoá đơn); API/api/invoices/issueidempotent, chặn lệch tiền, chỉ phát hành đơn PAID — test E2E với mock - Zalo ZNS:
NotificationProvider+ mock + ZNS adapter; API/api/notifications/send(yêu cầu đăng nhập) - Multi-tenant + RBAC: Workspace/Membership (OWNER/ADMIN/MEMBER), helpers
requireWorkspaceRolechống IDOR (non-member nhận 404 như workspace không tồn tại) — test E2E 200/401/404 - Admin panel
/admin(gateUser.isAdmin): bảng đơn + tổng thu - Email transactional:
EmailProvider+ mock + Resend adapter (REST) - Dữ liệu 34 tỉnh thành sau sáp nhập 2025 (NQ 202/2025/QH15) +
resolveProvincetra tên cũ→mới (migrate địa chỉ) + API/api/vn/provinces - Zalo OAuth: flow tự viết (
/api/auth/zalo/start+/callback, PKCE S256, state cookie) bàn giao session cho NextAuth qua one-time login token (5 phút, dùng 1 lần) — vì OAuth v4 của Zalo phi chuẩn, không dùng được provider Auth.js. Đã smoke test token 1 lần/reuse-fail; login thật cần app Zalo + redirect_uri khai báo
Đã xong (Phase 2 — đợt 2)
- Unit tests (Vitest, 43 test): tự ký payload verify chữ ký cả 4 cổng thật + mock (VNPay sort+encode, MoMo thứ tự cố định, ZaloPay key1/key2, Stripe raw body + tolerance), lineTotals VAT, resolveProvince —
yarn test, chạy trong CI - Seed:
yarn db:seed(admin) +yarn db:seed:demo(24 đơn đủ cổng/trạng thái, 3 khách, workspace, hoá đơn — an toàn chạy lại) - UI quản lý workspace
/workspaces: list + form tạo (tự gợi ý slug từ tên có dấu) - Admin: filter theo trạng thái/cổng qua searchParams (không client JS)
Đã xong (Phase 2 — đợt 3: lớp trình diễn)
-
/store: trang bán license PhoStack chạy trên chính hạ tầng của nó — 3 gói → checkout (nhận sẵn amount/description) → cổng → IPN → xuất hoá đơn điện tử ngay trên trang kết quả (dogfooding trọn luồng kinh doanh) -
/dev: Dev console — trạng thái từng module (Thật/Mock/Tắt theo env) + IPN log 10 giao dịch gần nhất kèm payload gốc -
/docs: docs site render bộ markdown trong app (react-markdown + GFM + typography), sidebar curated, rewrite link nội bộ, chặn path traversal
Đã xong (Phase 2 — đợt 4)
- i18n vi/en không dependency: dictionary typed cùng shape (
en: typeof vi— thiếu key là typecheck fail), locale qua cookie (mặc định vi), switcher VI/EN trên header (server action),html langtheo locale. Toàn bộ UI song ngữ; docs content giữ tiếng Việt (selling point). Client components nhậnlocaleprop + import từi18n/dictionaries(client-safe, không next/headers)
Đã xong (Phase 2 — đợt 5)
- Docs song ngữ: bộ dịch tiếng Anh đầy đủ 10 tài liệu trong
docs/en/(mirror cây VI); bản VI là canonical, bản EN ghi rõ là courtesy translation. Trang/docschọn theo locale — EN thiếu bản dịch thì fallback bản VI kèm thông báo. Quy tắc "sửa doc là sửa cả 2 ngôn ngữ" ghi trong ENGINEERING-STANDARDS
Đã xong (Phase 2 — đợt 6: hoàn thiện tài khoản)
-
/account: sửa tên, đổi mật khẩu (verify mật khẩu hiện tại), lịch sử đơn; email header → link account -
/admin/users: bảng khách hàng (đơn/tổng chi/vai trò), cấp/gỡ admin qua server action (không tự gỡ mình) - Gate
/adminchuyên nghiệp: khách → redirect login; non-admin → 403 sạch (gợi ý SQL chỉ ở dev) - Nav lọc theo quyền (public/auth/admin); docs kỹ thuật (Quickstart/Deployment/Architecture/Engineering) khoá sau đăng nhập — docs marketing (Vision/Roadmap/Legal…) vẫn public, sidebar hiện 🔒
Đã xong (Phase 3 — đợt 1: hạ tầng kinh doanh)
- Module Lead/Booking (29/07/2026) cho topology 3 instance (phostack.com hub → saas-demo → hq): model
Lead(DEMO_BOOKING/PREORDER/CONTACT, pipeline NEW→CONTACTED→CONVERTED/CLOSED, tier, source); endpoint publicPOST /api/leads(CORS allowlist chỉ phostack.com, honeypot nuốt bot lặng lẽ, Zod limit chặt);/admin/leadspipeline view + server action đổi trạng thái; doanh thu 6 tháng gần nhất trên/admin— API E2E test đủ 5 case (preflight 204, 2 lead thật 201, honeypot fake-201 không lưu, email sai 400) - phostack.com thành site công ty (29/07/2026): bỏ landing tĩnh 1 sản phẩm, dựng Next.js app riêng (repo
phostack/website) — trang chủ công ty + catalogue sản phẩm trongsrc/data/products.ts(thêm starter mới = thêm 1 object,/products/[slug]tự có) + about + contact; lead gửi qua server action nên trình duyệt không chạm HQ, không còn CORS. Deploy Vercel (phostack-web), Cloudflare chỉ giữ DNS — hết upload tay - APP_MODE=hq (29/07/2026): cùng source SaaS Kit chạy được như backend kinh doanh riêng tư — chưa đăng nhập là đẩy về
/login,/vào thẳng/admin, tắt tự đăng ký; chỉ/api/auth/*,/api/payments/ipn/*,/api/leadscòn mở. Verify local đủ 2 chiều (khách bị chặn, admin vào được, lead vẫn nhận) - Form book demo/pre-order thật trên landing (thay mailto): POST JSON tới
https://hq.phostack.com/api/leads, fallback mở mailto nếu HQ chưa sống; CTA bảng giá tự điền type/tier
Đã xong (Phase 3 — đợt 2: lên sóng thật)
- Topology 3 instance chạy production (29/07/2026) — verify bằng dữ liệu thật, không phải bằng UI:
phostack.com→ Vercelphostack-web(site công ty, Next.js, catalogue sản phẩm data-driven)saas-demo.phostack.com→ Vercelphostack-saas-demo(demo công khai, DB Neon riêng)hq.phostack.com→ Vercelphostack-hqvớiAPP_MODE=hq, DB Neon riêng — chưa đăng nhập là đẩy/login(đã đo/và/stoređều 307), tài khoản admin seed bằng mật khẩu sinh ngẫu nhiên- Lead thật đi trọn đường: form trên phostack.com → server action → HQ → bảng
Lead→ hiện trong/admin/leads(source ghi đúngphostack.com/contact); request giả danhOrigin: evil.combị chặn 403 - DNS: 4 bản ghi CNAME tại Cloudflare, tất cả DNS only (proxy cam gây lỗi SSL 525 — đã gặp và sửa)
- Bổ sung bảng
Leadcho DB demo (tạo trước khi có model này nên thiếu) - Chuyển
middleware.ts→proxy.tstheo convention Next 16 (Middleware đã deprecated) - Dọn workspace: repo thật về đúng
~/Projects/phostack/saas-kit(trước đó tồn tại 2 bản clone, bản trong workspace là bản cũ)
Còn lại để chốt hạ tầng
- Đặt
phostack.comlàm Primary trong Vercel (hiện apex 308 sangwww) -
APP_URLcủa demo →https://saas-demo.phostack.com+ đổi IPN URL VNPay tương ứng - Cloudflare Email Routing cho
hello@phostack.com— hiện chưa có MX, thư khách gửi tới địa chỉ in trên website đang bị trả về
Đang làm / còn lại (Phase 2)
- VNPay sandbox verify với hệ thống thật (29/07/2026): tạo đơn qua sandbox → thanh toán thẻ test NCB → replay bộ tham số có chữ ký thật của VNPay vào IPN handler → chữ ký HMAC-SHA512 verify pass, đơn PAID, amount ×100 chia lại đúng; retry idempotent (1 Payment duy nhất); sửa amount sau khi ký → RspCode 97. IPN server-to-server thật đã verify (29/07/2026) sau khi deploy Vercel + cấu hình IPN URL tại sandbox.vnpayment.vn/vnpaygw-sit-testing/ipn: đơn trên demo cloud tự chuyển PAID qua IPN VNPay gọi thẳng vào
/api/payments/ipn/vnpay(txn 15639474, payload lưu trong Payment.rawIpn) — VNPay xong trọn vẹn end-to-end - Test MoMo/ZaloPay sandbox end-to-end (cần tài khoản sandbox)
- SInvoice/meInvoice: verify payload với tài khoản T-VAN thật — adapter viết theo docs công khai, CHƯA chạy với môi trường thật
- ZNS: vòng đời token production (access token ~25h, refresh token dùng 1 lần → cần cron refresh + lưu DB; hiện nhận token qua env)
- Zalo OAuth: test end-to-end với app Zalo thật (flow + token đã smoke test nội bộ)
- Metadata title các trang còn tĩnh tiếng Việt — chuyển generateMetadata theo locale nếu cần SEO song ngữ
Rủi ro đang theo dõi
| Rủi ro | Ảnh hưởng | Ứng phó |
|---|---|---|
| Sandbox MoMo không ổn định | Chậm verify adapter | Mock-first; chỉ test sandbox ở bước cuối |
| NextAuth v5 còn beta | API có thể đổi | Pin version trong lockfile; wrap sau facade riêng |
| Nghị định hướng dẫn NĐ70 thay đổi chi tiết kỹ thuật | Adapter e-invoice phải sửa | Đây chính là giá trị bán — quy trình theo dõi trong LEGAL-FRAMEWORK |