Skip to content

fix(server): type rules.entitlement() with registered Entitlement union [#2992]#2993

Merged
viniciusdacal merged 2 commits intomainfrom
fix/rules-entitlement-typed
Apr 24, 2026
Merged

fix(server): type rules.entitlement() with registered Entitlement union [#2992]#2993
viniciusdacal merged 2 commits intomainfrom
fix/rules-entitlement-typed

Conversation

@viniciusdacal
Copy link
Copy Markdown
Contributor

Summary

Closes #2992.

  • rules.entitlement(name) accepted any string, so typos like rules.entitlement('task:udpate') compiled cleanly and only surfaced at runtime. Narrows the parameter to the Entitlement type so typos become TypeScript errors and autocomplete surfaces declared entitlements.
  • The infrastructure was already in place — @vertz/codegen's AccessTypesGenerator already emits declare module '@vertz/server' { interface EntitlementRegistry { ... } } into access.d.ts, and Entitlement = keyof EntitlementRegistry extends never ? string : Extract<keyof EntitlementRegistry, string> is defined in access-context.ts. The builder just wasn't consuming the Entitlement type.
  • Falls back to string when the registry is empty, so projects that haven't run codegen keep compiling.

Public API Changes

  • packages/server/src/auth/rules.tsrules.entitlement(name: string)rules.entitlement(name: Entitlement). Non-breaking when EntitlementRegistry is empty (parameter resolves to string); narrows in projects where codegen has emitted access.d.ts.

Test plan

  • tsgo --noEmit clean on @vertz/server (both tsconfig.json and tsconfig.typecheck.json)
  • oxlint clean on changed files
  • vtz test — 2193 passed, 0 failed on @vertz/server, including the new rules.test-d.ts
  • Pre-push gates (build-typecheck, lint, test, trojan-source) all green
  • New .test-d.ts covers positive (accepts string fallback) and negative (@ts-expect-error on non-string inputs) cases

🤖 Generated with Claude Code

viniciusdacal and others added 2 commits April 24, 2026 08:45
…on [#2992]

Closes #2992.

rules.entitlement() took a raw string, so typos like 'task:udpate' passed
both TypeScript and the compiler and only failed at runtime. The codegen
path that augments EntitlementRegistry already existed; the builder just
wasn't consuming it. Switch the parameter to the Entitlement type so the
narrowing propagates end-to-end: typos become TS errors and autocomplete
surfaces declared entitlements. Falls back to string when the registry is
empty so projects that haven't run codegen keep compiling.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ows rules.entitlement end-to-end [#2992]

Simulates what @vertz/codegen's AccessTypesGenerator emits into access.d.ts
and confirms the narrowing actually propagates through the published
@vertz/server boundary: declared entitlements compile, typos trip ts-expect-error,
and the same narrowing reaches AccessContext.can/authorize. Without this test
the previous fix only proved the signature references Entitlement, not that
codegen's output is wired through correctly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@viniciusdacal viniciusdacal merged commit f426ce5 into main Apr 24, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validate entitlement strings at compile time in rules.entitlement()

1 participant