跪拜 Guibai
← All articles
Frontend · Backend · Algorithm

ZenTao Reborn: A NestJS + Vue3 Full-Stack Replica With 58 Tables, 229 APIs, and Source-Verified State Machines

By 梦里寻码 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

A full, tested implementation of a mature development management system is now open source under MIT, giving teams a reference for state machines, RBAC with data scoping, and real-time collaboration that have been validated against ZenTao's PHP source. The permission drift gate and shared contract package are directly applicable to any full-stack project wrestling with frontend/backend contract decay.

Summary

A developer has open-sourced a full-stack reconstruction of ZenTao, the long-running R&D management tool, using NestJS 11 on the backend and Vue 3.5 with Element Plus on the frontend. The monorepo replicates the original system's business logic at source-code level: every state transition rule is traced to ZenTao's PHP code, with 58 MySQL tables, 229 Swagger-verified endpoints, and 221 permission points.

A shared TypeScript contract package with zero runtime dependencies keeps front and back ends in sync: enums, a state transition authority table, permission constants, socket contracts, and error codes all live there. The backend uses three guards—JWT for identity, PermissionsGuard for actions, DataScopeGuard for data visibility—with permission data sourced from the DB and cached in Redis. A drift-check script fails CI if shared constants and DB permissions diverge.

The kanban treats columns as status and drag as a server-side action, using Socket.IO with eventId idempotency and optimistic updates. Testing combines 62 Vitest unit tests, 130 plain HTTP assertion scripts that boot a real MySQL/Redis stack, and 7 Playwright E2E cases; the assertion scripts are positioned as reproducible acceptance evidence rather than framework reports. The write-up also documents eight real pitfalls, from ESM import suffixes to silent DTO stripping.

Takeaways
— The project reproduces ZenTao with 58 MySQL tables, 229 endpoints, 221 permission points, and 34 frontend pages.
— A shared TypeScript contract package with zero runtime dependencies holds enums, transition tables, permission constants, socket contracts, and error codes, used by both frontend and backend.
— Task state transitions are copied from ZenTao's model.php:2533-2596; illegal transitions return error code 3006.
— Logging effort implicitly changes task status: wait becomes doing, left=0 becomes done, and done with left>0 becomes doing again.
— Permissions are split: JWT only identifies the user; PermissionsGuard checks actions; DataScopeGuard checks data visibility; DB is the single source with Redis cache and a drift-check script that fails CI on divergence.
— The kanban treats column as status and drag as a server-side action over Socket.IO; eventId deduplicates retries, and WIP over-limit only warns.
— Testing uses 62 Vitest units, 130 HTTP assertion scripts against real MySQL/Redis, and 7 Playwright E2E cases, plus a Swagger audit and permission drift gate.
— Eight documented pitfalls include ESM `.js` import suffixes, Nest DTO whitelist silently stripping fields, and a 401 refresh storm solved with single-flight refresh.
— CI runs dual jobs: quality (types, units, build) and integration (real MySQL/Redis, migration-first, full regression).
Conclusions

Reconstructing a 20-year-old system like ZenTao surfaces edge cases that greenfield designs miss; the author credits source-level reading over documentation for rules like version-based review trimming and effort-driven status migration.

The separation of JWT identity, action permission, and data scope, with the DB as single source and a drift-check gate, directly addresses the common failure of forgotten reseeding after enum changes.

Plain HTTP assertion scripts serve as acceptance evidence that runs identically in local and CI environments, trading framework reporting for a deterministic exit-code tally.

The project's stance that documentation is the context contract for AI collaboration, with append-only ADRs and traced business rules, is directly relevant to teams using AI-assisted development.

Concepts & terms
Source-level calibration
In this project, every business rule is traced to the exact file and line number in ZenTao's PHP source, making the original source the final authority for how a feature should behave.
Permission drift check
A CI script that compares the shared permission constants with the database table version, failing the build if they diverge, preventing the common mistake of changing an enum without rerunning seed data.
Implicit state transition
A task's status changes automatically when effort is logged (e.g., wait→doing, left=0→done, done with left>0→doing), without requiring an explicit user action.
Single-flight refresh
A technique to handle concurrent token refreshes by ensuring only one refresh request is in flight at a time, queueing other requests until it completes, preventing overwrites and loops.
DataScopeGuard
A Nest guard that precomputes each user's visible object IDs into Redis and enforces data-level access on every query, separating 'what you can do' from 'what you can see'.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗