Files
WRNexusJS/packages/authz/src/codegen.ts
T
ClintchizandClaude Opus 5 41b6e2ed2b fix(authz): freeze catalog values after boot; correct compile-time-check claims
frozenMap only blocked the Map's own mutators, so
catalog.roles.get("editor").push("*") escalated a role to a full wildcard
past an error string claiming the catalog is frozen after boot; the same
applied to permission/attribute metadata objects and binding arrays.
mergeCatalogs now stores frozen copies of each, so the original declaring
module's objects are never mutated either.

Also corrects two docstrings (codegen.ts, the design doc) that claimed
`wrnexus authz generate`'s output makes a permission typo a type error —
can(), guardPermission(), and decideFor() all take a bare string and nothing
consumes the generated union automatically. Documents what it actually is:
a Permission/Role union to type your own helpers/constants against. Also
adds a README note on the subject.id contract (must be a non-empty string;
owner() compares with Object.is).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 02:10:24 +05:30

32 lines
1.2 KiB
TypeScript

import type { AuthzCatalog } from "./types.ts";
function union(values: string[]): string {
if (!values.length) return "never";
// JSON.stringify escapes backslashes, quotes, and control characters
// (including raw newlines, which the registry does not reject in role
// names and which would otherwise break out of the string literal).
return values
.slice()
.sort()
.map((value) => JSON.stringify(value))
.join(" | ");
}
/**
* Emit `Permission`/`Role` string-literal unions from the registered catalog.
*
* This does NOT make `can(ctx, "post:wrtie")` a type error — `can()`,
* `guardPermission()`, and `decideFor()` all take a bare `string`, and
* nothing in the framework consumes this generated file automatically.
* Import the unions yourself to type your OWN helpers/constants, e.g.
* `const PERM: Permission = "post:write"` or a typed wrapper around `can()`.
*/
export function generatePermissionTypes(catalog: AuthzCatalog): string {
return `// Generated by \`wrnexus authz generate\`. DO NOT EDIT.
export type Permission = ${union([...catalog.permissions.keys()])};
export type Role = ${union([...catalog.roles.keys()])};
`;
}