@vertz/server 0.2.12 → 0.2.14
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.
- package/README.md +76 -0
- package/dist/index.d.ts +1001 -156
- package/dist/index.js +3491 -512
- 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:
|