@vertz/server 0.2.12 → 0.2.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/README.md +76 -0
  2. package/dist/index.d.ts +1001 -156
  3. package/dist/index.js +3491 -512
  4. package/package.json +6 -6
package/README.md CHANGED
@@ -288,6 +288,82 @@ if (result.ok) {
288
288
  }
289
289
  ```
290
290
 
291
+ ## Access Control
292
+
293
+ `defineAccess()` sets up hierarchical RBAC with plans and usage limits. `createAccessContext()` evaluates entitlements at request time.
294
+
295
+ ```typescript
296
+ import { defineAccess, createAccessContext } from '@vertz/server';
297
+
298
+ const access = defineAccess({
299
+ hierarchy: ['org', 'workspace', 'project'],
300
+ roles: {
301
+ org: ['owner', 'admin', 'member'],
302
+ workspace: ['admin', 'editor', 'viewer'],
303
+ project: ['manager', 'contributor', 'viewer'],
304
+ },
305
+ inheritance: {
306
+ org: { owner: 'admin', admin: 'editor', member: 'viewer' },
307
+ workspace: { admin: 'manager', editor: 'contributor', viewer: 'viewer' },
308
+ },
309
+ entitlements: {
310
+ 'project:create': { roles: ['admin', 'editor'] },
311
+ 'ai:generate': { roles: ['editor'], plans: ['pro', 'enterprise'] },
312
+ },
313
+ plans: {
314
+ free: {
315
+ entitlements: ['project:create'],
316
+ },
317
+ pro: {
318
+ entitlements: ['project:create', 'ai:generate'],
319
+ limits: { 'ai:generate': { per: 'month', max: 1000 } },
320
+ },
321
+ },
322
+ defaultPlan: 'free',
323
+ });
324
+ ```
325
+
326
+ ### Checking Entitlements
327
+
328
+ ```typescript
329
+ const ctx = createAccessContext({
330
+ userId: session.userId,
331
+ accessDef: access,
332
+ closureStore,
333
+ roleStore,
334
+ planStore,
335
+ walletStore,
336
+ orgResolver: async (resource) => session.orgId,
337
+ });
338
+
339
+ // Boolean check
340
+ const allowed = await ctx.can('project:create', { type: 'workspace', id: 'ws-1' });
341
+
342
+ // Structured check with denial reasons
343
+ const result = await ctx.check('ai:generate', { type: 'project', id: 'p-1' });
344
+ // { allowed: false, reasons: ['plan_required'], meta: { requiredPlans: ['pro'] } }
345
+
346
+ // Throws AuthorizationError on denial
347
+ await ctx.authorize('project:create', { type: 'workspace', id: 'ws-1' });
348
+ ```
349
+
350
+ ### Consuming Usage Limits
351
+
352
+ ```typescript
353
+ // Atomic check + consume — avoids TOCTOU races
354
+ const allowed = await ctx.canAndConsume('ai:generate', { type: 'project', id: 'p-1' });
355
+ if (!allowed) return { error: 'Limit reached' };
356
+
357
+ try {
358
+ await generateAI(prompt);
359
+ } catch (err) {
360
+ await ctx.unconsume('ai:generate', { type: 'project', id: 'p-1' });
361
+ throw err;
362
+ }
363
+ ```
364
+
365
+ See the full [Authentication & Access Control guide](https://vertz.dev/guides/server/auth) for hierarchy details, plan configuration, and entity access metadata.
366
+
291
367
  ## Error Handling
292
368
 
293
369
  Entity routes return consistent error responses: