Skip to content

Rui-Cheng PMS Whitepaper

An internal project-management system for structural engineering cases

Version 1.0 · June 2026 · 繁體中文版


Executive Summary

Rui-Cheng PMS (瑞成工程專案管理系統) is an internal tool built for the structural engineers of 瑞成土木結構技師事務所 to manage 30+ concurrent engineering cases. It is not a public SaaS product and has no signup, no billing, and no public surface — every user is a member of the firm who logs in with a badge number.

The system is designed around three strategic axes that reflect how an engineering practice actually carries legal and professional liability:

  1. Audit-first design for engineer liability (行為留痕、責任可溯) — every create, update, and delete is funnelled through a single rcLog path that records time, badge, role, and a before/after diff. The log is permanent, immutable, and CSV-exportable, because a certifying engineer's liability can be litigated for up to 10 years.
  2. Client-calendar schedule warning lights (依業主工作日的時程燈號預警) — progress is measured against the client's working calendar (a government agency skips Lunar New Year, a developer works Saturdays, a semiconductor client runs 24/7), surfaced as four-level warning lights and pushed to an in-app notification bell.
  3. Badge login + 3-tier accountability boundary (工牌登入 + 三層權限的責任界線) — login is by badge number plus password, and a 10-flag permission matrix draws a hard line: clerical staff may proxy-operate, but only the certifying engineer may move a progress number.

This whitepaper documents the domain model, the accountability and audit design, and the Next.js architecture that implements them.


1. Problem

A structural-engineering practice runs dozens of cases at once, each with its own client, its own statutory deadline, and its own certifying engineer whose seal carries personal liability. Before Rui-Cheng PMS, that reality was tracked across spreadsheets, shared folders, and memory:

  • Progress was opaque. Whether a case was on track depended on who you asked, and "on track" was judged against a generic calendar, not the day the client actually works.
  • Accountability was ambiguous. When administrative staff updated a case on an engineer's behalf, there was no durable record of who changed what, or whether they were allowed to.
  • Evidence was fragile. An engineer's certification can be challenged years after a project closes. Reconstructing "what did we know, and when" from scattered files is unreliable.
  • Deadlines were reactive. A slipping case was usually noticed when the client called, not before.

The firm needed a single internal system where the progress number is owned by exactly one role, every change is provable, and a case that is falling behind raises its hand on its own.


2. Domain Model

The domain logic lives in components/rc/ and is the heart of the product.

2.1 Six case categories

Cases fall into six built-in categories (plus firm-defined custom categories), grouped by how their progress is computed:

CategoryNameProgress model
A1設計監造 (design supervision)Node-based, auto-summed
A2鑑定 (assessment)Node-based, auto-summed
A3巡查 (inspection)Node-based, auto-summed
B1建案 (building case)Self-filled progress
B2計算案 (calculation case)Self-filled progress
B3鑑定案 (assessment case)Flexible hybrid

The A-series are 公共工程 (public works): progress is a deterministic sum of completed nodes, not a number a human types. The B-series let the responsible engineer fill progress directly, with B3 supporting a hybrid of both styles.

2.2 Sub-cases (母子追加案)

A B2 calculation case may spawn sub-cases (母子追加案) — follow-on work attached to a parent. Sub-cases are tracked by status, not rolled into the parent's progress percentage, so adding follow-on work never distorts the headline completion figure of the original engagement.

2.3 Schedule warning lights (時程燈號預警)

Each case carries a target schedule. A daily scan at 02:00 compares elapsed-progress against elapsed-time, computed against the client's working calendar:

  • a 政府機關 (government agency) client skips 春節 (Lunar New Year),
  • a 建商 (developer) client works Saturdays,
  • a 半導體 (semiconductor) client runs 24/7.

The result is a four-level warning light:

LightThresholdMeaning
綠 Green< 50Comfortable
黃 Yellow50–74Watch
橙 Orange75–89At risk
紅 Red≥ 90Critical

Warnings are delivered through an in-app notification bell only — there is no email path by design.

2.4 Client database (業主資料庫)

A lightweight CRM stores client attributes, NDA flags, contact windows (including the history of contacts who have since resigned), and the set of cases bound to each client — so the warning calendar and the contact record always travel with the case.

2.5 Audit log (稽核日誌)

Every mutation passes through rcLog, recording time, badge, role, and the before/after state. The log is permanent, immutable, and exportable as CSV. Its purpose is concrete: to serve as evidence in civil litigation, where a certifying engineer's liability can persist for up to ten years under the statute of limitations.


3. Accountability and Permissions

3.1 Badge login (工牌登入)

There is no email login, no OAuth, and no 2FA. A user signs in with a badge number (format R00001) and a password. Auth is handled by Auth.js v5 with the Credentials provider and a JWT session strategy (stateless — no DB session table). RBAC guards re-read the user's role from the database on each gated action rather than trusting a stale token claim.

3.2 Three-tier RBAC

Three roles map to real positions in the firm:

RolePositionBoundary
admin管理員 (技師 / certifying engineer)Owns progress numbers
operator行政 (administrative)Clerical proxy-operations; cannot set progress %
staff一般 (general staff)Scoped task access

The core invariant: only the 技師 (admin) may set a progress percentage. An 行政 (operator) can perform clerical proxy-operations across many cases on an engineer's behalf, but the progress number — the figure that carries professional liability — is reserved to the engineer.

3.3 The 10-flag permission matrix

Authorization is expressed as a 10-flag matrix evaluated server-side. Every gated Server Action checks the caller's flags as its first line, so the accountability boundary is enforced at the mutation, not merely hidden in the UI.


4. Architecture

4.1 Next.js App Router (Next.js 16)

The system uses Next.js 16 App Router with:

  • React Server Components (RSC) as the default — "use client" only for browser APIs, event handlers, and state.
  • Server Actions ("use server") for every case mutation — guarded, audited, no separate REST layer for internal state.
  • Route Handlers (app/api/) for the few endpoints that must be callable on a schedule (e.g. the 02:00 schedule-light scan).
  • Nested layouts for route groups: (auth)/, (dashboard)/.

4.2 Domain engine

The case categories, node-summing progress, sub-case status tracking, calendar-aware light computation, and the rcLog audit path all live under components/rc/. Keeping the domain engine in one place is what makes the accountability boundary auditable.

4.3 Authentication (Auth.js v5)

  • Badge-number + password via the Credentials provider.
  • JWT session strategy — sessions are stateless; there is no DB session table. This is a deliberate pairing with Credentials login.
  • Role guards re-read role from the database on each protected action.

4.4 Database (Drizzle + PostgreSQL)

  • Drizzle ORM — type-safe schema with zero runtime overhead.
  • PostgreSQL 15 — production-grade, managed on Zeabur.
  • Migrations via pnpm db:generate + pnpm db:migrate.
  • Core tables include users (with badge + role), cases, case nodes, sub-cases, clients, client calendars, schedule lights, and the immutable audit log.

4.5 UI

The interface is built with Tailwind CSS v4 and shadcn/ui on the Rui-Cheng brand blue (#2C5CB8). List and table views use the reusable data-table component; create/edit flows open in modals rather than redirecting, and the full UI ships in 繁體中文.


5. Out of Scope

Several capabilities common to commercial SaaS products were deliberately excluded because Rui-Cheng PMS is an internal tool with a single tenant — the firm itself:

  • No payments, subscriptions, or any payment-provider integration. There is nothing to bill.
  • No pluggable feature-install / component-distribution mechanism. The codebase is a single application, not a catalog of distributable parts.
  • No OAuth, no two-factor authentication, no LINE integration.
  • No email notifications. Schedule warnings live in the in-app bell only.
  • No file upload. Documents are referenced by NAS links rather than stored in the app.

These omissions are features: the smaller surface is easier to audit and matches how the firm actually works.


6. How It's Built

Rui-Cheng PMS was developed with Claude Code and an Athena agent team running an epic-driven, spec → implement → QA → ship pipeline, with TDD and a coverage gate on every change. This is how the system is built and maintained; it is not a feature of the product.

Quality gates on every change:

  • Typecheck: pnpm typecheck (zero errors enforced)
  • Lint: pnpm lint (eslint-config-next)
  • Unit tests: pnpm test (Vitest, ≥80% coverage gate)
  • E2E tests: pnpm test:e2e (Playwright, smoke gate)

7. Deployment

The application deploys to Zeabur as a single service, with migrations run at startup. This documentation site deploys separately to Cloudflare Pages.


8. Conclusion

Rui-Cheng PMS turns the way a structural-engineering practice actually carries liability into software: one role owns the progress number, every change is provable for a decade, and a case that slips against its client's real calendar raises its own hand. The deliberately small, single-tenant surface is what keeps it auditable.

Learn more: 使用手冊 (User Manual) · 領域概念 (Domain Concepts) · 儀表板 Dashboard · 案件管理 Cases · 系統設定 Settings

Released under the MIT License.