@aooth/arbac-moost 0.1.70 → 0.1.72

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.
@@ -1,8 +1,53 @@
1
- import { TClassConstructor } from "moost";
2
- import { ControlGate, TProjection, TProjectionChildren, TScopeFilter } from "@aooth/arbac";
3
- import { TMetaResponse } from "@atscript/db";
4
- import { AsDbController } from "@atscript/moost-db";
5
- import { NavPropsOf, OwnPropsOf, TAtscriptAnnotatedType } from "@atscript/typescript/utils";
1
+ import { Mate, TClassConstructor, TMateParamMeta, TMoostMetadata } from "moost";
2
+ import { ControlGate, TProjection, TProjectionChildren, TScopeFieldRules, TScopeFilter } from "@aooth/arbac";
3
+ import { TDbRemoveGuardContext, TDbWriteAction, TDbWriteCheckContext, TDbWriteGuardContext, TMetaResponse } from "@atscript/db";
4
+ import { AsDbController, TDbControlsType, TDbRequestContext } from "@atscript/moost-db";
5
+ import { NavPropsOf, OwnPropsOf, TAtscriptAnnotatedType, TAtscriptDataType } from "@atscript/typescript/utils";
6
+ //#region src/arbac.mate.d.ts
7
+ /**
8
+ * ARBAC metadata fields attached to classes and methods by ARBAC decorators.
9
+ *
10
+ * Augments the shared `TMoostMetadata` workspace via TypeScript declaration
11
+ * merging so other moost-aware tooling (and `getArbacMate()` readers) sees
12
+ * these fields with full type safety.
13
+ */
14
+ interface TArbacMeta {
15
+ arbacResourceId?: string;
16
+ arbacActionId?: string;
17
+ arbacPublic?: boolean;
18
+ }
19
+ declare module "moost" {
20
+ interface TMoostMetadata extends TArbacMeta {}
21
+ }
22
+ type ArbacMate = Mate<TMoostMetadata & {
23
+ params: TMateParamMeta[];
24
+ }, TMoostMetadata & {
25
+ params: TMateParamMeta[];
26
+ }>;
27
+ /**
28
+ * Returns the shared `Mate` instance typed with ARBAC metadata fields.
29
+ *
30
+ * All ARBAC decorators write through this typed wrapper so reads and writes
31
+ * stay type-checked against `TArbacMeta`.
32
+ */
33
+ declare function getArbacMate(): ArbacMate;
34
+ /**
35
+ * Marks a controller whose `prepareRequest` authorizes moost-db's delegated
36
+ * handlers (the ones `getDbEndpoint` tags, e.g. `GET meta/actions/:id`) with
37
+ * ARBAC: a method keyed by this symbol answers whether `method` is such a
38
+ * handler. The authorize interceptor then skips its own evaluation for that
39
+ * handler (the route has no grant of its own). `AsArbacDbController` /
40
+ * `AsArbacDbReadableController` carry it; a controller without it keeps the
41
+ * interceptor's normal (fail-closed) evaluation.
42
+ *
43
+ * @since 0.1.72
44
+ */
45
+ declare const ARBAC_DELEGATED_AUTH: unique symbol;
46
+ /** A controller carrying {@link ARBAC_DELEGATED_AUTH}. @since 0.1.72 */
47
+ interface ArbacDelegatedAuth {
48
+ [ARBAC_DELEGATED_AUTH](method: string): boolean;
49
+ }
50
+ //#endregion
6
51
  //#region src/db/scope-types.d.ts
7
52
  /**
8
53
  * Unwrap a `NavPropsOf<T>[K]` value to its target model type:
@@ -54,6 +99,30 @@ type ControlsOf<T> = IsUnknown<T> extends true ? Record<string, ControlGate> : {
54
99
  [key: `$${string}`]: ControlGate | Array<string> | undefined;
55
100
  };
56
101
  //#endregion
102
+ //#region src/db/write-fields.d.ts
103
+ /**
104
+ * Test-friendly internal helper — exported for unit tests and helper
105
+ * composition; regular consumers should not call this directly.
106
+ *
107
+ * Apply the union of `allowedFields` whitelists (with `preserveFields`
108
+ * always preserved) and overlay each scope's `set` overrides. Returns a
109
+ * copy; the original `data` is not mutated.
110
+ *
111
+ * Path-aware: a top-level entry (`profile`) keeps the whole subtree; a
112
+ * dotted entry (`profile.name`) keeps only that branch of a nested object
113
+ * payload (`profile: { name, tenant }` → `profile: { name }`) — a non-object
114
+ * value under a partially whitelisted key is dropped, never kept whole. A
115
+ * dotted `set` key sets the nested path, merging into the payload's nested
116
+ * object.
117
+ *
118
+ * Patches (`isMergePatch` given): a nested object is written as a whole
119
+ * unless its path is a `@db.patch.strategy 'merge'` block, so a partially
120
+ * whitelisted REPLACE block is dropped (a partial block would clear the
121
+ * non-whitelisted leaves), and a dotted `set` under a replace block the patch
122
+ * does not carry is skipped (adding the block would clear its other leaves).
123
+ */
124
+ declare function applyAllowedFieldsAndSet(data: unknown, scopes: ArbacDbScope[], preserveFields?: readonly string[], isMergePatch?: (objectPath: string) => boolean): unknown;
125
+ //#endregion
57
126
  //#region src/db/as-arbac-db-controller.d.ts
58
127
  /**
59
128
  * Contract returned by an ARBAC role's scope predicate on a DB-backed resource.
@@ -71,9 +140,23 @@ type ControlsOf<T> = IsUnknown<T> extends true ? Record<string, ControlGate> : {
71
140
  * }
72
141
  * }
73
142
  * ```
143
+ *
144
+ * The framework never reads a custom field — the app unions it with its own
145
+ * rule. Where scope lists are CONJOINED (credential attenuation), each custom
146
+ * field needs a conjunction rule registered once with
147
+ * `MoostArbac.registerScopeFields`; a custom field without one fails the
148
+ * evaluation (it is never silently dropped). Since 0.1.72.
74
149
  */
75
150
  interface ArbacDbScope<T = unknown> {
76
151
  filter?: TScopeFilter;
152
+ /**
153
+ * Post-write WITH CHECK filter: every row an insert / replace / update
154
+ * writes must match it (Postgres RLS semantics). Defaults to `filter`;
155
+ * `{}` disables the check. Conjoined (`$and`) like `filter` by
156
+ * `defineTableAccess` part scopes and credential attenuation; unioned
157
+ * across roles. Enforced by the ARBAC DB controllers from 0.1.72.
158
+ */
159
+ check?: TScopeFilter;
77
160
  projection?: ProjectionOf<T>;
78
161
  set?: Partial<Record<OwnFieldKey<T>, unknown>>;
79
162
  allowedFields?: Array<OwnFieldKey<T>>;
@@ -100,21 +183,47 @@ interface ArbacDbScope<T = unknown> {
100
183
  * `?$with=<name>`. Recursive — each sub-scope has the same shape and can
101
184
  * declare its own `with` for nested expansions (e.g. tasks → comments → task).
102
185
  *
103
- * **Authority model**: the PARENT scope owns the policy for joined rows.
104
- * arbac-moost does NOT re-evaluate ARBAC against the joined resource's own
105
- * scopes — that would be a confusing indirection and a perf hit. Whatever
106
- * the parent declares here is what surfaces from the expansion.
186
+ * **Which policy the joined rows obey** (0.1.72+):
187
+ * - Declared in any role → the union of those sub-scopes governs the
188
+ * joined rows (silent roles contribute nothing).
189
+ * - Not declared → the caller's own `query` grant on the related table's
190
+ * ARBAC resource (its filter, projection, controls and `with`); no grant
191
+ * → `Unknown relation` (400), identical to a nonexistent relation.
107
192
  *
108
- * **Union across roles**: when multiple roles allow the same parent table,
193
+ * **Union across roles**: when multiple roles declare the same relation,
109
194
  * their `with[name]` sub-scopes are unioned at every nested level using the
110
195
  * existing `unionProjections` / `mergeScopeFilters` / `unionControlsPolicy`
111
196
  * primitives (additive: broader access wins, same rules as the parent).
112
- *
113
- * **Silence wins**: if no role declares `with.<name>`, expansion is
114
- * unrestricted (matches `controls.$with` whitelist semantics; the gate
115
- * still applies if declared).
197
+ * The `controls.$with` gate still applies either way.
116
198
  */
117
199
  with?: WithOf<T>;
200
+ /**
201
+ * Nav relations (`TO` / `FROM` / `VIA` props) this scope may write THROUGH
202
+ * — nested inserts / updates of related rows in the parent's payload.
203
+ * Default deny: a write payload carrying a nav key not listed by any of
204
+ * the caller's write scopes is rejected with 403. Parent authority — the
205
+ * related rows are written under the PARENT scope, the related table's
206
+ * own ARBAC policy is not consulted. Enforced by the ARBAC DB controllers
207
+ * from 0.1.72.
208
+ */
209
+ nestedWrites?: Array<NavRelationKey<T>>;
210
+ /**
211
+ * FK target checks (opt-in): a write that SETS one of these foreign keys
212
+ * (insert / replace rows; update patches touching it) must reference rows
213
+ * the caller can READ under its own `query` grant on the target table's
214
+ * ARBAC resource — else 403 `Referenced row "<field>" is outside your
215
+ * scope`. `true` = every FK of the table; a list names FK fields or the TO
216
+ * relations they back. A target without a registered ARBAC DB controller or
217
+ * without a read grant → 403. Null / absent FKs are not checked.
218
+ *
219
+ * **Union across roles**: enforced for an FK only when EVERY allowing write
220
+ * scope enables it — write scopes grant additively, so a role without the
221
+ * flag grants unconstrained writes of that FK. Credential attenuation
222
+ * enforces what either side enforces.
223
+ *
224
+ * @since 0.1.72
225
+ */
226
+ checkRefs?: true | Array<OwnFieldKey<T> | NavRelationKey<T>>;
118
227
  }
119
228
  /**
120
229
  * Per-relation sub-scope map. For `T = unknown` falls back to the legacy
@@ -125,9 +234,43 @@ interface ArbacDbScope<T = unknown> {
125
234
  * because it must reference `ArbacDbScope` recursively.
126
235
  */
127
236
  type WithOf<T> = unknown extends T ? Record<string, ArbacDbScope> : { [K in NavRelationKey<T>]?: K extends keyof NavPropsOf<T> ? ArbacDbScope<NavTarget<NavPropsOf<T>[K]>> : ArbacDbScope; };
237
+ /**
238
+ * ARBAC-enforcing CRUD controller over an atscript-db table.
239
+ *
240
+ * Every endpoint — `@DbAction` handlers included — resolves the caller's
241
+ * scopes first in `prepareRequest` (fail closed: no grant → 403, `@Public()`
242
+ * does not bypass it); every other hook reads them. Reads apply
243
+ * the scopes' row filter, projection, controls and `with` sub-scopes. Writes
244
+ * enforce, per request:
245
+ *
246
+ * - **nested writes** — a payload key naming a nav relation → 403 unless a
247
+ * write scope lists it in `nestedWrites`;
248
+ * - **`allowedFields` / `set`** — path-aware whitelist (identifiers, the
249
+ * version column and `$cas` always kept) and forced values;
250
+ * - **USING** — update / replace / delete target only rows matching the
251
+ * scope `filter`, checked on the exact pre-image inside the write's
252
+ * transaction (missing or out of scope → the same 404);
253
+ * - **`checkRefs`** (opt-in) — an FK the write sets must reference a row
254
+ * the caller can read on the target table (else 403);
255
+ * - **WITH CHECK** — every written row must match the scope `check`
256
+ * (default: `filter`; `{}` opts out) after the write, inside the
257
+ * transaction (→ 403, rolled back). On adapters without real transactions
258
+ * the check runs in memory before the write and fails closed on anything
259
+ * it cannot decide.
260
+ */
128
261
  declare class AsArbacDbController<T extends TAtscriptAnnotatedType = TAtscriptAnnotatedType> extends AsDbController<T> {
129
- protected transformFilter(filter: Record<string, unknown> | undefined): Promise<Record<string, unknown>>;
130
- protected transformProjection(projection?: TProjection): TProjection | undefined | Promise<TProjection | undefined>;
262
+ /** Makes this controller the `$with` policy source for its table's ARBAC resource. */
263
+ protected readonly _arbacRelationTarget: true;
264
+ /**
265
+ * Resolve the request's ARBAC scopes before anything else consults them:
266
+ * reuse the ones the authorize interceptor cached, else evaluate the
267
+ * handler's resource/action now — a deny is a 403 (`arbacPublic` never
268
+ * bypasses a DB controller). On read endpoints the `$with` relation policy
269
+ * is resolved for the requested relations.
270
+ */
271
+ protected prepareRequest(ctx: TDbRequestContext): Promise<void>;
272
+ protected transformFilter(filter: Record<string, unknown> | undefined): Record<string, unknown>;
273
+ protected transformProjection(projection?: TProjection): TProjection | undefined;
131
274
  /**
132
275
  * Translate `@uniqu/url` parser failures into HTTP 400 instead of letting them
133
276
  * bubble as 500. The base `parseQueryString` calls `parseUrl()` directly with
@@ -152,32 +295,69 @@ declare class AsArbacDbController<T extends TAtscriptAnnotatedType = TAtscriptAn
152
295
  * controls of a request. Runs after the base validator (which checks the
153
296
  * controls DTO shape) and BEFORE the query/aggregation pipeline executes.
154
297
  *
155
- * Reads the scopes the route-level authorize interceptor cached via
156
- * `arbac.setScopes(...)` — validation runs before `transformFilter`, so
157
- * this hook never re-evaluates ARBAC.
158
- *
159
- * On a violation we throw `HttpError(403)`. moost-db's `query` / `pages` /
160
- * `getOne` handlers do NOT wrap `validateParsed` in try/catch, so the
161
- * thrown error bubbles to moost which translates it to a 403 response.
298
+ * Reads the scopes `prepareRequest` resolved — unresolved scopes are a 403
299
+ * (never "unrestricted"). A violation throws `HttpError(403)`, which
300
+ * moost-db's read handlers let bubble.
162
301
  */
163
- protected validateControls(controls: Record<string, unknown>, type: "query" | "pages" | "getOne"): string | undefined;
302
+ protected validateControls(controls: Record<string, unknown>, type: TDbControlsType): string | undefined;
164
303
  protected applyMetaOverlay(meta: TMetaResponse): Promise<TMetaResponse>;
165
304
  /**
166
- * Scope-aware field visibility (BUG-3 twin of the `/meta` pruning above): a
305
+ * `GET /meta/form/:name` serves a form only when the caller may run at
306
+ * least one of the actions taking it as input (else the unknown-form 404).
307
+ */
308
+ protected authorizeForm(_name: string, actionNames: readonly string[]): Promise<boolean>;
309
+ /**
310
+ * The rows each `@DbAction` may run on: the caller's grant on that action
311
+ * (see `arbacActionRowScope`). Enforced by the action gate and reflected
312
+ * in `$actions` and `GET /meta/actions/:id`. Since 0.1.72.
313
+ */
314
+ protected actionRowScope(name: string): Promise<Record<string, unknown> | undefined>;
315
+ /**
316
+ * The row-level actions `$actions` and `GET /meta/actions/:id` may list:
317
+ * those the caller holds a grant on (the `/meta` overlay's rule, without
318
+ * building the overlay). Since 0.1.72.
319
+ */
320
+ protected allowedActions(names: readonly string[]): Promise<string[]>;
321
+ /**
322
+ * moost-db handlers that delegate their authorization to `prepareRequest`
323
+ * (`getDbEndpoint` — `GET /meta/actions/:id`): the authorize interceptor
324
+ * skips them; `prepareRequest` serves them iff the caller may run at least
325
+ * one row-level action (else 403). Since 0.1.72.
326
+ */
327
+ [ARBAC_DELEGATED_AUTH](method: string): boolean;
328
+ /**
329
+ * Scope-aware field visibility (the twin of the `/meta` pruning above): a
167
330
  * field outside the read-scope projection union answers `false`, which
168
331
  * moost-db's visibility hook turns into the same `Unknown field "x"` 400 a
169
332
  * nonexistent field gets at every gated query position — see the docs'
170
333
  * "Column-scope security floor". Identifiers stay visible. A `rel.x` path
171
- * under a `with`-granted relation (`$with=rel(x>1)`, `$with=rel($sort=x)`,
172
- * `$with=rel($select=x)`) is checked as `x` against the union of the
173
- * `with.rel` sub-scopes, recursively; the related table's own PK /
174
- * `preferredId` stay visible.
334
+ * (`$with=rel(x>1)`, `$with=rel($sort=x)`, `$with=rel($select=x)`) is
335
+ * checked as `x` against the relation's policy, recursively; the related
336
+ * table's own PK / `preferredId` stay visible. Unresolved scopes hide every
337
+ * field.
175
338
  */
176
339
  protected hasField(path: string): boolean;
177
- protected onWrite(action: "insert" | "insertMany" | "replace" | "replaceMany" | "update" | "updateMany", data: unknown): Promise<unknown>;
178
- protected onRemove(id: unknown): Promise<unknown>;
179
- private assertInScope;
180
- private identifierFields;
340
+ /**
341
+ * Untrusted-body stage: reject nested writes the scopes do not opt in
342
+ * (`nestedWrites`), then apply the `allowedFields` whitelist and `set`.
343
+ */
344
+ protected onWrite(action: TDbWriteAction, data: unknown): unknown;
345
+ /** `true` when a patch merges into the nested object at `path` (`@db.patch.strategy 'merge'`). */
346
+ private isMergeBlock;
347
+ /** In-transaction stage — USING, `checkRefs`, and WITH CHECK on non-transactional adapters. */
348
+ protected guardWrite(ctx: TDbWriteGuardContext<TAtscriptDataType<T>>): Promise<void>;
349
+ /** USING for deletes: the exact row the delete targets must match the scope filter (else 404). */
350
+ protected guardRemove(ctx: TDbRemoveGuardContext<TAtscriptDataType<T>>): Promise<void>;
351
+ /**
352
+ * WITH CHECK: after the write, inside its transaction, every written row
353
+ * must match the scopes' `check` (default `filter`) — else 403 and the
354
+ * write rolls back. Non-transactional adapters were checked in
355
+ * {@link guardWrite}.
356
+ */
357
+ protected checkWrite(ctx: TDbWriteCheckContext): Promise<void>;
358
+ /** `this.table` as the write guards see it (the generic `T` defeats structural matching). */
359
+ private get guardedTable();
360
+ private preservedWriteFields;
181
361
  }
182
362
  /**
183
363
  * Test-friendly internal helper — exported for unit tests and helper
@@ -219,15 +399,22 @@ declare function enforceControlsPolicy(policy: Record<string, ControlGate>, cont
219
399
  * gate, which throws if a non-whitelistable control receives a string[]).
220
400
  */
221
401
  declare function extractUsedControlValues(key: string, value: unknown, controls?: Record<string, unknown>): string[];
222
- /**
223
- * Test-friendly internal helper — exported for unit tests and helper
224
- * composition; regular consumers should not call this directly.
225
- *
226
- * Apply the union of `allowedFields` whitelists (with `preserveFields`
227
- * always preserved) and overlay each scope's `set` overrides. Returns a
228
- * shallow copy; original `data` is not mutated.
229
- */
230
- declare function applyAllowedFieldsAndSet(data: unknown, scopes: ArbacDbScope[], preserveFields?: readonly string[]): unknown;
402
+ //#endregion
403
+ //#region src/db/write-refs.d.ts
404
+ /** A `@db.rel.FK` entry as atscript-db's readable exposes it. */
405
+ interface RefForeignKey {
406
+ readonly fields: readonly string[];
407
+ readonly targetFields: readonly string[];
408
+ readonly targetTable?: string;
409
+ readonly alias?: string;
410
+ readonly targetTypeRef?: () => unknown;
411
+ }
412
+ /** The table surface `checkRefs` resolves names against (`AtscriptDbReadable` satisfies it). */
413
+ interface RefTableSource {
414
+ readonly foreignKeys?: ReadonlyMap<string, RefForeignKey>;
415
+ /** The FK a TO relation is backed by (atscript-db's `readable.foreignKeyOf`). @since 0.1.72 */
416
+ foreignKeyOf?(relationName: string): RefForeignKey | undefined;
417
+ }
231
418
  //#endregion
232
419
  //#region src/attenuation.d.ts
233
420
  /**
@@ -241,15 +428,23 @@ declare function applyAllowedFieldsAndSet(data: unknown, scopes: ArbacDbScope[],
241
428
  *
242
429
  * - `roles` — assume a SUBSET of the user's roles. `[]` = no roles (deny-all,
243
430
  * fail-closed); an OMITTED key = keep all the user's roles (attrs-only
244
- * narrowing); a role the user lacks is dropped by the intersection.
431
+ * narrowing); a role the user lacks is dropped by the intersection (unless
432
+ * `allowUnheldRoles`).
245
433
  * - `attrs` — extra/overriding inputs to scope predicates, keyed by the target
246
434
  * user-attribute name, intended to narrow scopes. They are merged LOCALLY
247
435
  * into the credential pass only and clipped by the scope conjunction, so they
248
436
  * can never widen beyond the user.
437
+ * - `allowUnheldRoles` — "view as": evaluate the claimed `roles` as given,
438
+ * including roles the user does not hold (unknown role ids still grant
439
+ * nothing). The result is still conjoined with the user's full authority,
440
+ * so it never widens beyond the user — it previews the claimed roles'
441
+ * surface CLIPPED to the user's own. Opt-in: the app decides who may issue
442
+ * such a credential (e.g. gate it behind a privilege). Since 0.1.72.
249
443
  */
250
444
  interface AoothArbacClaims {
251
445
  roles?: string[];
252
446
  attrs?: Record<string, unknown>;
447
+ allowUnheldRoles?: boolean;
253
448
  }
254
449
  /**
255
450
  * Conjoin the full-authority scopes (`userScopes`, the ceiling) and the
@@ -257,11 +452,12 @@ interface AoothArbacClaims {
257
452
  * `ArbacDbScope`. A row/field/control is admitted only if BOTH passes admit
258
453
  * it — the normative restrict-only clip that closes the attr-widen hole.
259
454
  *
260
- * Each side is first UNIONed with the existing additive helpers (today's
261
- * machinery), then the two RESULTS are CONJOINED with the dedicated combiners
262
- * ({@link conjoinScopeFilters} `$and`, {@link intersectProjections} field ∩,
263
- * {@link intersectControlsPolicy} deny-wins, `with` recursion) — never the
264
- * additive union helpers, which would silently widen.
455
+ * Each side is first UNIONed, then the two results are CONJOINED facet by
456
+ * facet with `conjoinScopes` from `@aooth/arbac` (`$and` filters and WITH
457
+ * CHECK filters, path-wise projection ∩, deny-wins controls, `allowedFields`
458
+ * / `nestedWrites` intersection, `set` combined with the USER winning a key
459
+ * conflict, recursive `with`) — never the additive union helpers, which
460
+ * would silently widen.
265
461
  *
266
462
  * Returned as a single-element list so every downstream scope-application
267
463
  * site (which UNIONs the cached scope list per facet) sees the identity of a
@@ -274,9 +470,26 @@ interface AoothArbacClaims {
274
470
  * closed). When NO field survives (`{a:1}` ∩ `{a:0}`, disjoint whitelists),
275
471
  * the composite keeps the user's projection and gets a match-nothing filter —
276
472
  * an empty field set must never read as the unrestricted `{}`. `with`
277
- * sub-scopes are conjoined without a schema.
473
+ * sub-scopes are conjoined without a schema. `checkRefs` enforces what either
474
+ * side enforces (resolved against `refTable`'s foreign keys when given — the
475
+ * evaluated table). A custom (declaration-merged) scope field is conjoined by
476
+ * its `fields` rule; without one this THROWS — never dropped (fail closed).
477
+ *
478
+ * The third argument is the options object, or (legacy form) `childrenOf`.
278
479
  */
279
- declare function conjoinArbacDbScopes(userScopes: ArbacDbScope[], credScopes: ArbacDbScope[], childrenOf?: TProjectionChildren): ArbacDbScope[];
480
+ declare function conjoinArbacDbScopes(userScopes: ArbacDbScope[], credScopes: ArbacDbScope[], opts?: TProjectionChildren | ConjoinArbacDbScopesOptions): ArbacDbScope[];
481
+ /** Options of {@link conjoinArbacDbScopes}. @since 0.1.72 */
482
+ interface ConjoinArbacDbScopesOptions {
483
+ /** The evaluated table's schema lookup — subtracts a nested exclusion exactly. */
484
+ childrenOf?: TProjectionChildren;
485
+ /** The evaluated table — resolves `checkRefs` names to its foreign keys. */
486
+ refTable?: RefTableSource;
487
+ /**
488
+ * Custom scope field rules (`MoostArbac.registerScopeFields`); a custom
489
+ * field without one throws.
490
+ */
491
+ fields?: TScopeFieldRules<ArbacDbScope>;
492
+ }
280
493
  //#endregion
281
494
  //#region src/user.provider.d.ts
282
495
  /**
@@ -334,4 +547,4 @@ declare abstract class ArbacUserProvider<TUserAttrs extends object = object> {
334
547
  */
335
548
  declare const ArbacUserProviderToken: TClassConstructor<ArbacUserProvider>;
336
549
  //#endregion
337
- export { ArbacDbScope as a, enforceControlsPolicy as c, NavRelationKey as d, NavTarget as f, conjoinArbacDbScopes as i, extractUsedControlValues as l, ProjectionOf as m, ArbacUserProviderToken as n, AsArbacDbController as o, OwnFieldKey as p, AoothArbacClaims as r, applyAllowedFieldsAndSet as s, ArbacUserProvider as t, ControlsOf as u };
550
+ export { ProjectionOf as _, conjoinArbacDbScopes as a, TArbacMeta as b, ArbacDbScope as c, extractUsedControlValues as d, applyAllowedFieldsAndSet as f, OwnFieldKey as g, NavTarget as h, ConjoinArbacDbScopesOptions as i, AsArbacDbController as l, NavRelationKey as m, ArbacUserProviderToken as n, RefForeignKey as o, ControlsOf as p, AoothArbacClaims as r, RefTableSource as s, ArbacUserProvider as t, enforceControlsPolicy as u, ARBAC_DELEGATED_AUTH as v, getArbacMate as x, ArbacDelegatedAuth as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aooth/arbac-moost",
3
- "version": "0.1.70",
3
+ "version": "0.1.72",
4
4
  "description": "Moost RBAC integration for aoothjs (migrated from @moostjs/arbac)",
5
5
  "keywords": [
6
6
  "abac",
@@ -61,30 +61,30 @@
61
61
  },
62
62
  "dependencies": {
63
63
  "@uniqu/core": "^0.1.11",
64
- "@aooth/arbac": "0.1.70",
65
- "@aooth/user": "0.1.70",
66
- "@aooth/arbac-core": "0.1.70"
64
+ "@aooth/arbac": "0.1.72",
65
+ "@aooth/user": "0.1.72",
66
+ "@aooth/arbac-core": "0.1.72"
67
67
  },
68
68
  "devDependencies": {
69
- "@atscript/core": "^0.1.93",
70
- "@atscript/db": "^0.1.140",
71
- "@atscript/db-sql-tools": "^0.1.140",
72
- "@atscript/db-sqlite": "^0.1.140",
73
- "@atscript/moost-db": "^0.1.140",
74
- "@atscript/typescript": "^0.1.93",
75
- "@moostjs/event-http": "^0.6.39",
69
+ "@atscript/core": "^0.1.97",
70
+ "@atscript/db": "^0.1.145",
71
+ "@atscript/db-sql-tools": "^0.1.145",
72
+ "@atscript/db-sqlite": "^0.1.145",
73
+ "@atscript/moost-db": "^0.1.145",
74
+ "@atscript/typescript": "^0.1.97",
75
+ "@moostjs/event-http": "^0.6.41",
76
76
  "@types/better-sqlite3": "^7.6.13",
77
77
  "better-sqlite3": "^12.6.2",
78
- "unplugin-atscript": "^0.1.93"
78
+ "unplugin-atscript": "^0.1.97"
79
79
  },
80
80
  "peerDependencies": {
81
- "@atscript/db": "^0.1.140",
82
- "@atscript/moost-db": "^0.1.140",
83
- "@atscript/typescript": "^0.1.93",
84
- "@moostjs/event-http": "^0.6.39",
85
- "@wooksjs/event-core": "^0.7.23",
86
- "@wooksjs/event-http": "^0.7.23",
87
- "moost": "^0.6.39"
81
+ "@atscript/db": "^0.1.145",
82
+ "@atscript/moost-db": "^0.1.145",
83
+ "@atscript/typescript": "^0.1.97",
84
+ "@moostjs/event-http": "^0.6.41",
85
+ "@wooksjs/event-core": "^0.7.24",
86
+ "@wooksjs/event-http": "^0.7.24",
87
+ "moost": "^0.6.41"
88
88
  },
89
89
  "peerDependenciesMeta": {
90
90
  "@atscript/db": {