Test coverage: from module directories to one RBAC route matrix
“49 module test directories” only speaks to breadth; quality depends on how cases pin boundaries. Below, one real RBAC route matrix shows what behavior is under test.
Organized by module
Section titled “Organized by module”Directory names under test/ map to modules (for example rbac/, audit/, trigger/, team/). Change a module, run that directory first — the regression net stays clear. Each governance capability has its own directory, which reduces blind spots where a feature has no tests. Cross-cutting unit/ / integration/ trees often force searching across folders after a module change and make missed regressions more likely.
Those directories cover kernel behavior (sessions, tools, providers) and governance behavior (RBAC, identity, org, team, triggers, retention, observability).
One RBAC route matrix
Section titled “One RBAC route matrix”Route-permission cases enumerate role × method × path in a table:
const cases: Case[] = [ ["operator", "GET", "/global/config", true], ["operator", "PATCH", "/global/config", false], ["approver", "PATCH", "/global/config", false], ["operator", "POST", "/global/dispose", false], ["operator", "GET", "/global/dispose", true], ["admin", "POST", "/global/dispose", true], ["operator", "POST", "/global/retention/run", false], ["admin", "POST", "/global/retention/run", true], ["readonly", "GET", "/global/health", true], ["operator", "POST", "/session/abc/init", true], ["operator", "PATCH", "/prefs", true],]
for (const [role, method, path, want] of cases) { test(`${role} ${method} ${path} → ${want}`, () => { expect(allowed(role as never, method, path)).toBe(want) })}Three boundaries (where over-privilege bugs often hide):
Same path, different read vs write. GET /global/dispose is open to operator; POST is admin-only. Auth is path × method, not path alone.
Exceptions are in the cases. GET /global/health is true for readonly as well. Health probes must not be broken by a tight permission default; the exception is pinned by tests, not by convention.
Regression guards. Operator can still init a session and change prefs — tightening global write must not lock normal execution paths.
Permission defects look like “this role is allowed or blocked wrongly for this method+path.” The matrix pins combinations; adding a route means adding a row.
Isolation via fixtures
Section titled “Isolation via fixtures”Temp-directory fixtures give each case its own directory, optionally init git / write config, clean up at the end, and scrub null bytes from paths (CI defense). Multi-tenant and multi-instance isolation only stays stable when cases do not contaminate each other.
Related: