Migration: 0.1 to 0.2
@nestarc/rbac 0.2 is an additive upgrade. Existing string permissions, decorators, module options, storage adapters, and the Prisma schema remain compatible.
Upgrade
npm install @nestarc/rbac@0.2No database migration is required. Applications that assert exact RbacDecision object equality should allow the new optional details field.
Adopt typed permissions
Create one permission contract and replace string literals incrementally:
import { defineRbacPermissions } from '@nestarc/rbac';
export const permissions = defineRbacPermissions({
reports: {
read: 'reports.read',
export: 'reports.export',
},
} as const);The persisted strings do not change. Start with new code, then migrate role seeds and decorators as they are touched.
Adopt strict options
Enable strict defaults in tests or one module before applying them globally:
import { createStrictRbacOptions, RbacModule } from '@nestarc/rbac';
RbacModule.forRoot(
createStrictRbacOptions({
storage,
}),
);Before a global rollout:
- Mark intentionally public routes with
@SkipRbac(). - Add RBAC metadata to protected routes.
- Confirm auth and tenancy middleware resolve context before RBAC.
- Add denial tests for missing subject, tenant, resource, and permission.
- Decide whether
rejectGlobalRoleInTenantBindingshould remainfalseor be enabled for your policy.
Connect audit logging
The optional audit-log adapter is exported from its own subpath:
import { createAuditLogRbacLogger } from '@nestarc/rbac/integrations/audit-log';
RbacModule.forRoot({
storage,
auditLogger: createAuditLogRbacLogger({ auditLog: auditService }),
});The root package remains dependency-light and does not require @nestarc/audit-log at runtime.
Publish policy changes
Use changePublisher for best-effort cache invalidation or outbox integration:
RbacModule.forRoot({
storage,
changePublisher: {
publish: (event) => outbox.publish('rbac.policy.changed', event),
},
});These hooks do not provide distributed consistency by themselves. Monitor failures and design cache freshness around the delivery mechanism used by the consuming application.
Verify the upgrade
- Run existing role, guard, and Prisma adapter tests unchanged.
- Add
expectDeniedReason()assertions for critical denial paths. - Add an
expectRbacMatrix()table for tenant and resource boundary cases. - Confirm default HTTP denials do not expose
decision.details. - Confirm audit metadata does not contain tokens, secrets, request bodies, headers, or raw subject attributes.
Upgrade from 0.2.0/0.2.1 to 0.2.2
- Reconcile all authenticated subject and tenant sources; canonical API-key identity belongs in
request.apiKey. Remove conflicting legacy writers. - Account for authoritative configured tenant resolvers.
tenant.resolverMode: 'legacy-fallback'exists only as a deprecated temporary migration option. - Handle missing-role
updateRole()errors and no-op mutations without expecting success audit/change events. - Prefer
RbacServiceDecisionand its service-specific reason/details types forcan(); wider decision envelopes remain compatible. The unused decoratorreasonoption and dormant error/detail fields are deprecated. - Keep guard integrations on HTTP; invoke
RbacServicefrom application-owned non-HTTP adapters. - Validate representative Node 22/24 and NestJS 10/11/12 consumers. Prisma 7 support arrived in 0.2.1 and does not require an RBAC schema migration.