@vielzeug/ward 1.0.3 → 1.0.4

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 +1 @@
1
- {"version":3,"file":"middleware.cjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import type { Principal, Ward, WardDecision } from './types';\n\nexport type WardRequest = Record<string, unknown>;\nexport type PrincipalExtractor<TReq extends WardRequest = WardRequest> = (req: TReq) => Principal | Promise<Principal>;\n\nexport type GuardResult<TAction extends string, TData> =\n | { granted: true; principal: Principal }\n | {\n decision: WardDecision<TAction, TData>;\n granted: false;\n principal: Principal;\n reason: 'explicit-deny' | 'no-matching-rule';\n };\n\n/**\n * Evaluates a ward decision for a known `principal` and returns a `GuardResult`.\n * Use when you have already resolved the principal (e.g. from a session or JWT).\n *\n * For request-object based flows where the principal must be extracted asynchronously,\n * use `guardRequestWith` instead.\n *\n * @example\n * ```ts\n * // Express / Hono / any framework — write a 3-line adapter:\n * app.use('/posts', async (req, res, next) => {\n * const result = await guardRequestWith(ward, req, extractPrincipal, 'posts', 'read');\n * result.granted ? next() : res.status(403).json({ reason: result.reason });\n * });\n * ```\n */\nexport function guardRequest<TAction extends string, TData>(\n ward: Ward<TAction, TData>,\n principal: Principal,\n resource: string,\n action: TAction,\n data?: TData,\n): GuardResult<TAction, TData> {\n const decision = ward.explain(principal, resource, action, data);\n\n if (decision.allowed) {\n return { granted: true, principal };\n }\n\n return { decision, granted: false, principal, reason: decision.reason };\n}\n\n/**\n * Evaluates a ward decision by first extracting the principal from a request object,\n * then running the authorization check. The extractor may be async (e.g. to verify a JWT).\n *\n * Use `guardRequest` instead when the principal is already resolved.\n */\nexport async function guardRequestWith<TAction extends string, TData, TReq extends WardRequest>(\n ward: Ward<TAction, TData>,\n req: TReq,\n extractPrincipal: PrincipalExtractor<TReq>,\n resource: string,\n action: TAction,\n data?: TData,\n): Promise<GuardResult<TAction, TData>> {\n const principal = await extractPrincipal(req);\n\n return guardRequest(ward, principal, resource, action, data);\n}\n"],"mappings":"AA8BA,SAAgB,EACd,EACA,EACA,EACA,EACA,EAC6B,CAC7B,IAAM,EAAW,EAAK,QAAQ,EAAW,EAAU,EAAQ,CAAI,EAM/D,OAJI,EAAS,QACJ,CAAE,QAAS,GAAM,WAAU,EAG7B,CAAE,WAAU,QAAS,GAAO,YAAW,OAAQ,EAAS,MAAO,CACxE,CAQA,eAAsB,EACpB,EACA,EACA,EACA,EACA,EACA,EACsC,CAGtC,OAAO,EAAa,EAAM,MAFF,EAAiB,CAAG,EAEP,EAAU,EAAQ,CAAI,CAC7D"}
1
+ {"version":3,"file":"middleware.cjs","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import type { Principal, Ward, WardDecision } from './types';\n\nexport type WardRequest = Record<string, unknown>;\nexport type PrincipalExtractor<TReq extends WardRequest = WardRequest> = (req: TReq) => Principal | Promise<Principal>;\n\nexport type GuardResult<TAction extends string, TData> =\n | { granted: true; principal: Principal }\n | {\n decision: WardDecision<TAction, TData>;\n granted: false;\n principal: Principal;\n reason: 'explicit-deny' | 'no-matching-rule';\n };\n\nexport type GuardRequestInput<TAction extends string, TData> = {\n action: TAction;\n data?: TData;\n principal: Principal;\n resource: string;\n ward: Ward<TAction, TData>;\n};\n\nexport type GuardRequestWithInput<TAction extends string, TData, TReq extends WardRequest> = {\n action: TAction;\n data?: TData;\n extractPrincipal: PrincipalExtractor<TReq>;\n req: TReq;\n resource: string;\n ward: Ward<TAction, TData>;\n};\n\nexport function guardRequest<TAction extends string, TData>(\n input: GuardRequestInput<TAction, TData>,\n): GuardResult<TAction, TData> {\n const decision = input.ward.explain({\n action: input.action,\n data: input.data,\n principal: input.principal,\n resource: input.resource,\n });\n\n if (decision.allowed) {\n return { granted: true, principal: input.principal };\n }\n\n return { decision, granted: false, principal: input.principal, reason: decision.reason };\n}\n\nexport async function guardRequestWith<TAction extends string, TData, TReq extends WardRequest>(\n input: GuardRequestWithInput<TAction, TData, TReq>,\n): Promise<GuardResult<TAction, TData>> {\n const principal = await input.extractPrincipal(input.req);\n\n return guardRequest({\n action: input.action,\n data: input.data,\n principal,\n resource: input.resource,\n ward: input.ward,\n });\n}\n"],"mappings":"AA+BA,SAAgB,EACd,EAC6B,CAC7B,IAAM,EAAW,EAAM,KAAK,QAAQ,CAClC,OAAQ,EAAM,OACd,KAAM,EAAM,KACZ,UAAW,EAAM,UACjB,SAAU,EAAM,QAClB,CAAC,EAMD,OAJI,EAAS,QACJ,CAAE,QAAS,GAAM,UAAW,EAAM,SAAU,EAG9C,CAAE,WAAU,QAAS,GAAO,UAAW,EAAM,UAAW,OAAQ,EAAS,MAAO,CACzF,CAEA,eAAsB,EACpB,EACsC,CACtC,IAAM,EAAY,MAAM,EAAM,iBAAiB,EAAM,GAAG,EAExD,OAAO,EAAa,CAClB,OAAQ,EAAM,OACd,KAAM,EAAM,KACZ,YACA,SAAU,EAAM,SAChB,KAAM,EAAM,IACd,CAAC,CACH"}
@@ -10,28 +10,21 @@ export type GuardResult<TAction extends string, TData> = {
10
10
  principal: Principal;
11
11
  reason: 'explicit-deny' | 'no-matching-rule';
12
12
  };
13
- /**
14
- * Evaluates a ward decision for a known `principal` and returns a `GuardResult`.
15
- * Use when you have already resolved the principal (e.g. from a session or JWT).
16
- *
17
- * For request-object based flows where the principal must be extracted asynchronously,
18
- * use `guardRequestWith` instead.
19
- *
20
- * @example
21
- * ```ts
22
- * // Express / Hono / any framework — write a 3-line adapter:
23
- * app.use('/posts', async (req, res, next) => {
24
- * const result = await guardRequestWith(ward, req, extractPrincipal, 'posts', 'read');
25
- * result.granted ? next() : res.status(403).json({ reason: result.reason });
26
- * });
27
- * ```
28
- */
29
- export declare function guardRequest<TAction extends string, TData>(ward: Ward<TAction, TData>, principal: Principal, resource: string, action: TAction, data?: TData): GuardResult<TAction, TData>;
30
- /**
31
- * Evaluates a ward decision by first extracting the principal from a request object,
32
- * then running the authorization check. The extractor may be async (e.g. to verify a JWT).
33
- *
34
- * Use `guardRequest` instead when the principal is already resolved.
35
- */
36
- export declare function guardRequestWith<TAction extends string, TData, TReq extends WardRequest>(ward: Ward<TAction, TData>, req: TReq, extractPrincipal: PrincipalExtractor<TReq>, resource: string, action: TAction, data?: TData): Promise<GuardResult<TAction, TData>>;
13
+ export type GuardRequestInput<TAction extends string, TData> = {
14
+ action: TAction;
15
+ data?: TData;
16
+ principal: Principal;
17
+ resource: string;
18
+ ward: Ward<TAction, TData>;
19
+ };
20
+ export type GuardRequestWithInput<TAction extends string, TData, TReq extends WardRequest> = {
21
+ action: TAction;
22
+ data?: TData;
23
+ extractPrincipal: PrincipalExtractor<TReq>;
24
+ req: TReq;
25
+ resource: string;
26
+ ward: Ward<TAction, TData>;
27
+ };
28
+ export declare function guardRequest<TAction extends string, TData>(input: GuardRequestInput<TAction, TData>): GuardResult<TAction, TData>;
29
+ export declare function guardRequestWith<TAction extends string, TData, TReq extends WardRequest>(input: GuardRequestWithInput<TAction, TData, TReq>): Promise<GuardResult<TAction, TData>>;
37
30
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAClD,MAAM,MAAM,kBAAkB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEvH,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,IACjD;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GACvC;IACE,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,eAAe,GAAG,kBAAkB,CAAC;CAC9C,CAAC;AAEN;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,EACxD,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,EAC1B,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,IAAI,CAAC,EAAE,KAAK,GACX,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAQ7B;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,EAAE,IAAI,SAAS,WAAW,EAC5F,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,EAC1B,GAAG,EAAE,IAAI,EACT,gBAAgB,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAC1C,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,EACf,IAAI,CAAC,EAAE,KAAK,GACX,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAItC"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAE7D,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAClD,MAAM,MAAM,kBAAkB,CAAC,IAAI,SAAS,WAAW,GAAG,WAAW,IAAI,CAAC,GAAG,EAAE,IAAI,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;AAEvH,MAAM,MAAM,WAAW,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,IACjD;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAAE,GACvC;IACE,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IACvC,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,MAAM,EAAE,eAAe,GAAG,kBAAkB,CAAC;CAC9C,CAAC;AAEN,MAAM,MAAM,iBAAiB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,IAAI;IAC7D,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,SAAS,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,EAAE,IAAI,SAAS,WAAW,IAAI;IAC3F,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,gBAAgB,EAAE,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC3C,GAAG,EAAE,IAAI,CAAC;IACV,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;CAC5B,CAAC;AAEF,wBAAgB,YAAY,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,EACxD,KAAK,EAAE,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,GACvC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAa7B;AAED,wBAAsB,gBAAgB,CAAC,OAAO,SAAS,MAAM,EAAE,KAAK,EAAE,IAAI,SAAS,WAAW,EAC5F,KAAK,EAAE,qBAAqB,CAAC,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,GACjD,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAUtC"}
@@ -1,18 +1,30 @@
1
1
  //#region src/middleware.ts
2
- function e(e, t, n, r, i) {
3
- let a = e.explain(t, n, r, i);
4
- return a.allowed ? {
2
+ function e(e) {
3
+ let t = e.ward.explain({
4
+ action: e.action,
5
+ data: e.data,
6
+ principal: e.principal,
7
+ resource: e.resource
8
+ });
9
+ return t.allowed ? {
5
10
  granted: !0,
6
- principal: t
11
+ principal: e.principal
7
12
  } : {
8
- decision: a,
13
+ decision: t,
9
14
  granted: !1,
10
- principal: t,
11
- reason: a.reason
15
+ principal: e.principal,
16
+ reason: t.reason
12
17
  };
13
18
  }
14
- async function t(t, n, r, i, a, o) {
15
- return e(t, await r(n), i, a, o);
19
+ async function t(t) {
20
+ let n = await t.extractPrincipal(t.req);
21
+ return e({
22
+ action: t.action,
23
+ data: t.data,
24
+ principal: n,
25
+ resource: t.resource,
26
+ ward: t.ward
27
+ });
16
28
  }
17
29
  //#endregion
18
30
  export { e as guardRequest, t as guardRequestWith };
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import type { Principal, Ward, WardDecision } from './types';\n\nexport type WardRequest = Record<string, unknown>;\nexport type PrincipalExtractor<TReq extends WardRequest = WardRequest> = (req: TReq) => Principal | Promise<Principal>;\n\nexport type GuardResult<TAction extends string, TData> =\n | { granted: true; principal: Principal }\n | {\n decision: WardDecision<TAction, TData>;\n granted: false;\n principal: Principal;\n reason: 'explicit-deny' | 'no-matching-rule';\n };\n\n/**\n * Evaluates a ward decision for a known `principal` and returns a `GuardResult`.\n * Use when you have already resolved the principal (e.g. from a session or JWT).\n *\n * For request-object based flows where the principal must be extracted asynchronously,\n * use `guardRequestWith` instead.\n *\n * @example\n * ```ts\n * // Express / Hono / any framework — write a 3-line adapter:\n * app.use('/posts', async (req, res, next) => {\n * const result = await guardRequestWith(ward, req, extractPrincipal, 'posts', 'read');\n * result.granted ? next() : res.status(403).json({ reason: result.reason });\n * });\n * ```\n */\nexport function guardRequest<TAction extends string, TData>(\n ward: Ward<TAction, TData>,\n principal: Principal,\n resource: string,\n action: TAction,\n data?: TData,\n): GuardResult<TAction, TData> {\n const decision = ward.explain(principal, resource, action, data);\n\n if (decision.allowed) {\n return { granted: true, principal };\n }\n\n return { decision, granted: false, principal, reason: decision.reason };\n}\n\n/**\n * Evaluates a ward decision by first extracting the principal from a request object,\n * then running the authorization check. The extractor may be async (e.g. to verify a JWT).\n *\n * Use `guardRequest` instead when the principal is already resolved.\n */\nexport async function guardRequestWith<TAction extends string, TData, TReq extends WardRequest>(\n ward: Ward<TAction, TData>,\n req: TReq,\n extractPrincipal: PrincipalExtractor<TReq>,\n resource: string,\n action: TAction,\n data?: TData,\n): Promise<GuardResult<TAction, TData>> {\n const principal = await extractPrincipal(req);\n\n return guardRequest(ward, principal, resource, action, data);\n}\n"],"mappings":";AA8BA,SAAgB,EACd,GACA,GACA,GACA,GACA,GAC6B;CAC7B,IAAM,IAAW,EAAK,QAAQ,GAAW,GAAU,GAAQ,CAAI;CAM/D,OAJI,EAAS,UACJ;EAAE,SAAS;EAAM;CAAU,IAG7B;EAAE;EAAU,SAAS;EAAO;EAAW,QAAQ,EAAS;CAAO;AACxE;AAQA,eAAsB,EACpB,GACA,GACA,GACA,GACA,GACA,GACsC;CAGtC,OAAO,EAAa,GAAM,MAFF,EAAiB,CAAG,GAEP,GAAU,GAAQ,CAAI;AAC7D"}
1
+ {"version":3,"file":"middleware.js","names":[],"sources":["../src/middleware.ts"],"sourcesContent":["import type { Principal, Ward, WardDecision } from './types';\n\nexport type WardRequest = Record<string, unknown>;\nexport type PrincipalExtractor<TReq extends WardRequest = WardRequest> = (req: TReq) => Principal | Promise<Principal>;\n\nexport type GuardResult<TAction extends string, TData> =\n | { granted: true; principal: Principal }\n | {\n decision: WardDecision<TAction, TData>;\n granted: false;\n principal: Principal;\n reason: 'explicit-deny' | 'no-matching-rule';\n };\n\nexport type GuardRequestInput<TAction extends string, TData> = {\n action: TAction;\n data?: TData;\n principal: Principal;\n resource: string;\n ward: Ward<TAction, TData>;\n};\n\nexport type GuardRequestWithInput<TAction extends string, TData, TReq extends WardRequest> = {\n action: TAction;\n data?: TData;\n extractPrincipal: PrincipalExtractor<TReq>;\n req: TReq;\n resource: string;\n ward: Ward<TAction, TData>;\n};\n\nexport function guardRequest<TAction extends string, TData>(\n input: GuardRequestInput<TAction, TData>,\n): GuardResult<TAction, TData> {\n const decision = input.ward.explain({\n action: input.action,\n data: input.data,\n principal: input.principal,\n resource: input.resource,\n });\n\n if (decision.allowed) {\n return { granted: true, principal: input.principal };\n }\n\n return { decision, granted: false, principal: input.principal, reason: decision.reason };\n}\n\nexport async function guardRequestWith<TAction extends string, TData, TReq extends WardRequest>(\n input: GuardRequestWithInput<TAction, TData, TReq>,\n): Promise<GuardResult<TAction, TData>> {\n const principal = await input.extractPrincipal(input.req);\n\n return guardRequest({\n action: input.action,\n data: input.data,\n principal,\n resource: input.resource,\n ward: input.ward,\n });\n}\n"],"mappings":";AA+BA,SAAgB,EACd,GAC6B;CAC7B,IAAM,IAAW,EAAM,KAAK,QAAQ;EAClC,QAAQ,EAAM;EACd,MAAM,EAAM;EACZ,WAAW,EAAM;EACjB,UAAU,EAAM;CAClB,CAAC;CAMD,OAJI,EAAS,UACJ;EAAE,SAAS;EAAM,WAAW,EAAM;CAAU,IAG9C;EAAE;EAAU,SAAS;EAAO,WAAW,EAAM;EAAW,QAAQ,EAAS;CAAO;AACzF;AAEA,eAAsB,EACpB,GACsC;CACtC,IAAM,IAAY,MAAM,EAAM,iBAAiB,EAAM,GAAG;CAExD,OAAO,EAAa;EAClB,QAAQ,EAAM;EACd,MAAM,EAAM;EACZ;EACA,UAAU,EAAM;EAChB,MAAM,EAAM;CACd,CAAC;AACH"}
package/dist/types.d.ts CHANGED
@@ -10,14 +10,6 @@ export type RuleContext<TData = unknown> = {
10
10
  principal: UserPrincipal;
11
11
  };
12
12
  export type WardPredicate<TData = unknown> = (ctx: RuleContext<TData>) => boolean;
13
- /**
14
- * A single authorization rule. `role` accepts a string or string array — it is
15
- * normalized to `readonly string[]` internally. `priority` defaults to `0`.
16
- * The compiled rule object returned from decisions is frozen and must not be mutated.
17
- *
18
- * A rule matches if the principal holds ANY of the listed roles (OR semantics).
19
- * Use `WILDCARD` to match all authenticated principals.
20
- */
21
13
  export type WardRule<TAction extends string = string, TData = unknown> = {
22
14
  action: TAction | typeof WILDCARD;
23
15
  effect: 'allow' | 'deny';
@@ -26,14 +18,6 @@ export type WardRule<TAction extends string = string, TData = unknown> = {
26
18
  role: string | readonly string[];
27
19
  when?: WardPredicate<TData>;
28
20
  };
29
- /**
30
- * The result of an authorization decision.
31
- *
32
- * Three distinct variants for precise narrowing:
33
- * - `allowed: true` — access granted; the winning rule is always present.
34
- * - `allowed: false, reason: 'explicit-deny'` — a deny rule matched; the winning rule is present.
35
- * - `allowed: false, reason: 'no-matching-rule'` — no rule matched; no rule is attached.
36
- */
37
21
  export type WardDecision<TAction extends string = string, TData = unknown> = {
38
22
  allowed: true;
39
23
  rule: Readonly<WardRule<TAction, TData>>;
@@ -50,143 +34,82 @@ export type WardCheck<TAction extends string = string, TData = unknown> = {
50
34
  data?: TData;
51
35
  resource: string;
52
36
  };
53
- /**
54
- * The result of a single check in `checkAll` — a `WardDecision` annotated with
55
- * the originating `resource` and `action` so callers do not need to zip by index.
56
- */
57
37
  export type WardDecisionResult<TAction extends string = string, TData = unknown> = WardDecision<TAction, TData> & {
58
38
  action: TAction;
59
39
  resource: string;
60
40
  };
41
+ export type WardDecisionInput<TAction extends string = string, TData = unknown> = {
42
+ action: TAction;
43
+ data?: TData;
44
+ principal: Principal;
45
+ resource: string;
46
+ };
47
+ export type WardAllowedActionsInput<TAction extends string = string, TData = unknown> = {
48
+ data?: TData;
49
+ knownActions: readonly TAction[];
50
+ principal: Principal;
51
+ resource: string;
52
+ };
53
+ export type WardRulesInScopeInput<TData = unknown> = {
54
+ data?: TData;
55
+ principal: Principal;
56
+ resource: string;
57
+ };
58
+ export type BoundWardDecisionInput<TAction extends string = string, TData = unknown> = {
59
+ action: TAction;
60
+ data?: TData;
61
+ resource: string;
62
+ };
63
+ export type BoundWardAllowedActionsInput<TAction extends string = string, TData = unknown> = {
64
+ data?: TData;
65
+ knownActions: readonly TAction[];
66
+ resource: string;
67
+ };
68
+ export type BoundWardRulesInScopeInput<TData = unknown> = {
69
+ data?: TData;
70
+ resource: string;
71
+ };
61
72
  export type ConflictKind = 'duplicate' | 'shadowed';
62
- /**
63
- * Describes a rule conflict detected at creation time.
64
- *
65
- * Two variants, narrowable by `kind`:
66
- *
67
- * - `'duplicate'`: two **predicate-free** rules have identical (role set, resource, action) —
68
- * one can never affect the outcome because the other always fires first.
69
- * Fields: `ruleA`/`indexA` (first declared, wins) and `ruleB`/`indexB` (unreachable).
70
- *
71
- * - `'shadowed'`: the `shadowingRule` has a higher or equal effective rank AND its
72
- * patterns are at least as broad as `shadowedRule`'s, AND it carries **no** `when`
73
- * predicate — so `shadowedRule` can never win.
74
- *
75
- * Rules that carry a `when` predicate are excluded from both checks because their
76
- * applicability can only be determined at runtime, not statically.
77
- */
78
73
  export type WardConflict<TAction extends string = string, TData = unknown> = {
79
- /** Index of the first-declared (winning) rule in the input array. */
80
74
  indexA: number;
81
- /** Index of the second-declared (unreachable) rule in the input array. */
82
75
  indexB: number;
83
76
  kind: 'duplicate';
84
- /** First-declared rule (the one that always wins). */
85
77
  ruleA: Readonly<WardRule<TAction, TData>>;
86
- /** Second-declared rule (the unreachable duplicate). */
87
78
  ruleB: Readonly<WardRule<TAction, TData>>;
88
79
  } | {
89
80
  kind: 'shadowed';
90
- /** Index of the rule that can never win. */
91
81
  shadowedIndex: number;
92
- /** The rule that can never win. */
93
82
  shadowedRule: Readonly<WardRule<TAction, TData>>;
94
- /** Index of the rule that always wins instead. */
95
83
  shadowingIndex: number;
96
- /** The rule that always wins instead. */
97
84
  shadowingRule: Readonly<WardRule<TAction, TData>>;
98
85
  };
99
- /** One candidate entry in a `WardTrace` — shows why it won or lost. */
100
86
  export type WardTraceCandidate<TAction extends string = string, TData = unknown> = {
101
- /** Original index of this rule in the input array passed to `createWard`. */
102
87
  index: number;
103
88
  priority: number;
104
89
  rule: Readonly<WardRule<TAction, TData>>;
105
90
  score: number;
106
91
  won: boolean;
107
92
  };
108
- /**
109
- * Full decision trace returned by `ward.trace()`.
110
- * Lists every rule that matched the request (before winner selection) so you can
111
- * see exactly which rule won and why other candidates lost.
112
- */
113
93
  export type WardTrace<TAction extends string = string, TData = unknown> = {
114
94
  candidates: WardTraceCandidate<TAction, TData>[];
115
95
  decision: WardDecision<TAction, TData>;
116
96
  };
117
97
  export type Ward<TAction extends string = string, TData = unknown> = {
118
- /**
119
- * Returns allowed concrete actions for a principal on a resource.
120
- * Pass `knownActions` to resolve wildcard-action rules.
121
- *
122
- * **Does not invoke the logger** — this is a side-effect-free enumeration helper.
123
- * Use `checkAll` if you need an auditable batch decision that fires the logger
124
- * for each action checked.
125
- */
126
- allowedActions(principal: Principal, resource: string, knownActions: readonly TAction[], data?: TData): TAction[];
127
- /** Evaluates multiple checks and returns one `WardDecisionResult` per check. Invokes the logger for each. */
98
+ allowedActions(input: WardAllowedActionsInput<TAction, TData>): TAction[];
128
99
  checkAll(principal: Principal, checks: readonly WardCheck<TAction, TData>[]): WardDecisionResult<TAction, TData>[];
129
- /** Returns all rule conflicts in the policy. Lazily computed and cached (and frozen) after first call. @complexity O(n²) */
130
100
  detectConflicts(): readonly WardConflict<TAction, TData>[];
131
- /** Returns the full `WardDecision` for the given principal, resource, and action. Invokes the logger. */
132
- explain(principal: Principal, resource: string, action: TAction, data?: TData): WardDecision<TAction, TData>;
101
+ explain(input: WardDecisionInput<TAction, TData>): WardDecision<TAction, TData>;
133
102
  forUser(principal: UserPrincipal): BoundWard<TAction, TData>;
134
- /**
135
- * Returns all rules whose role, resource, and action patterns match `principal` and `resource`.
136
- * When `data` is omitted, predicate-gated rules are **included** without evaluating their `when`
137
- * condition — useful for introspection. Pass `data` to apply predicates and get the runtime-accurate set.
138
- *
139
- * **Does not invoke the logger.**
140
- */
141
- rulesInScope(principal: Principal, resource: string, data?: TData): ReadonlyArray<Readonly<WardRule<TAction, TData>>>;
142
- /** Returns the full decision trace showing all matching candidates and why the winner was selected. **Does not invoke the logger** — use `explain` when you need the logger to fire. */
143
- trace(principal: Principal, resource: string, action: TAction, data?: TData): WardTrace<TAction, TData>;
144
- };
145
- /**
146
- * A principal-bound view of a Ward. All methods are identical to `Ward` but
147
- * without the leading `principal` argument — it is captured at `forUser()` time.
148
- * `forUser` and `detectConflicts` are not available on a bound view.
149
- */
103
+ rulesInScope(input: WardRulesInScopeInput<TData>): ReadonlyArray<Readonly<WardRule<TAction, TData>>>;
104
+ trace(input: WardDecisionInput<TAction, TData>): WardTrace<TAction, TData>;
105
+ };
150
106
  export type BoundWard<TAction extends string = string, TData = unknown> = {
151
- /**
152
- * Returns allowed concrete actions for this principal on a resource.
153
- * Pass `knownActions` to resolve wildcard-action rules.
154
- *
155
- * @remarks Side-effect-free enumeration helper — does **not** invoke the logger.
156
- * Use `checkAll` if you need an auditable batch decision.
157
- */
158
- allowedActions(resource: string, knownActions: readonly TAction[], data?: TData): TAction[];
159
- /** Evaluates multiple checks in a single call and returns one `WardDecisionResult` per check. */
107
+ allowedActions(input: BoundWardAllowedActionsInput<TAction, TData>): TAction[];
160
108
  checkAll(checks: readonly WardCheck<TAction, TData>[]): WardDecisionResult<TAction, TData>[];
161
- /** Returns the full `WardDecision` for this principal on the given resource and action. Invokes the logger. */
162
- explain(resource: string, action: TAction, data?: TData): WardDecision<TAction, TData>;
163
- /**
164
- * Returns all rules whose role, resource, and action patterns match this principal and resource.
165
- * When `data` is omitted, predicate-gated rules are included without evaluating their `when` condition.
166
- *
167
- * **Does not invoke the logger.**
168
- */
169
- rulesInScope(resource: string, data?: TData): ReadonlyArray<Readonly<WardRule<TAction, TData>>>;
170
- /** Returns the full decision trace showing all matching candidates and why the winner was selected. **Does not invoke the logger** — use `explain` when you need the logger to fire. */
171
- trace(resource: string, action: TAction, data?: TData): WardTrace<TAction, TData>;
172
- };
173
- /**
174
- * Logger context passed to `WardOptions.logger` on every decision.
175
- *
176
- * Structurally identical to `WardDecision` plus the request fields, so you can
177
- * narrow `rule` with the same `if (ctx.allowed)` pattern you already know.
178
- *
179
- * @example
180
- * ```ts
181
- * createWard(rules, {
182
- * logger: (ctx) => {
183
- * if (ctx.allowed) {
184
- * console.log(ctx.rule.role); // no ?. needed
185
- * }
186
- * },
187
- * });
188
- * ```
189
- */
109
+ explain(input: BoundWardDecisionInput<TAction, TData>): WardDecision<TAction, TData>;
110
+ rulesInScope(input: BoundWardRulesInScopeInput<TData>): ReadonlyArray<Readonly<WardRule<TAction, TData>>>;
111
+ trace(input: BoundWardDecisionInput<TAction, TData>): WardTrace<TAction, TData>;
112
+ };
190
113
  export type WardLoggerContext<TAction extends string = string, TData = unknown> = WardDecision<TAction, TData> & {
191
114
  action: TAction;
192
115
  data?: TData;
@@ -195,35 +118,8 @@ export type WardLoggerContext<TAction extends string = string, TData = unknown>
195
118
  };
196
119
  export type WardOptions<TAction extends string = string, TData = unknown> = {
197
120
  logger?: (context: WardLoggerContext<TAction, TData>) => void;
198
- /**
199
- * Maximum number of conflicts returned by `detectConflicts()`. Defaults to `Infinity`.
200
- * Use to cap the O(n²) overhead for large auto-generated policies.
201
- * Setting this to `0` disables conflict detection entirely — `detectConflicts()` will always return `[]`.
202
- */
203
121
  maxConflicts?: number;
204
- /**
205
- * Called synchronously for each detected rule conflict immediately after
206
- * the ward is compiled. Use this to surface conflicts as warnings or errors.
207
- *
208
- * @example
209
- * ```ts
210
- * createWard(rules, {
211
- * onConflict: (c) => c.kind === 'duplicate'
212
- * ? console.warn(`[ward] duplicate: Rule[${c.indexB}] unreachable (Rule[${c.indexA}] always wins)`)
213
- * : console.warn(`[ward] shadowed: Rule[${c.shadowedIndex}] by Rule[${c.shadowingIndex}]`),
214
- * });
215
- * ```
216
- */
217
122
  onConflict?: (conflict: WardConflict<TAction, TData>) => void;
218
- /**
219
- * When `true`, `createWard` throws immediately if any rule conflicts are
220
- * detected. Use `detectConflicts()` on the returned ward for non-throwing
221
- * inspection.
222
- *
223
- * @remarks When both `strict` and `onConflict` are set, `onConflict` is
224
- * called for each conflict **before** the throw, so all conflicts are
225
- * reported even in strict mode.
226
- */
227
123
  strict?: boolean;
228
124
  };
229
125
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/ward.cjs CHANGED
@@ -1,2 +1,2 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`*`,t=`anonymous`;function n(e,t,n,r,i){return r.map(r=>({action:r,effect:e,...i?.priority===void 0?{}:{priority:i.priority},resource:n,role:t,...i?.when===void 0?{}:{when:i.when}}))}function r(e,t,r,i){return n(`allow`,e,t,r,i)}function i(e,t,r,i){return n(`deny`,e,t,r,i)}var a={and(...e){return t=>e.every(e=>e(t))},not(e){return t=>!e(t)},or(...e){return t=>e.some(e=>e(t))},owns(e){return({data:t,principal:n})=>{if(!t||typeof t!=`object`)return!1;let r=t;return Object.hasOwn(r,e)?r[e]===n.id:!1}}};function o(e){return a.owns(e)}var s=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},c=class extends s{},l=class extends s{ruleIndex;constructor(e,t){let n=t instanceof Error?t.message:String(t);super(`Rule[${e}] threw: ${n}`,{cause:t}),this.ruleIndex=e}};function u(e,t){let n=`Rule[${t}]`,r=Array.isArray(e.role)?e.role:[e.role];if(r.length===0||r.some(e=>typeof e!=`string`||!e.trim()))throw new c(`${n}.role must be a non-empty string or non-empty array of strings`);if(typeof e.resource!=`string`||!e.resource.trim())throw new c(`${n}.resource must be a non-empty string`);if(e.resource.endsWith(`:`))throw new c(`${n}.resource '${String(e.resource)}' ends with ':' — did you mean '${String(e.resource)}*'?`);if(typeof e.action!=`string`||!e.action.trim())throw new c(`${n}.action must be a non-empty string`);if(e.action.endsWith(`:`))throw new c(`${n}.action '${String(e.action)}' ends with ':' — did you mean '${String(e.action)}*'?`);if(e.effect!==`allow`&&e.effect!==`deny`)throw new c(`${n}.effect must be "allow" or "deny"`);if(e.priority!==void 0&&(typeof e.priority!=`number`||!Number.isFinite(e.priority)))throw new c(`${n}.priority must be a finite number`);if(e.when!==void 0&&typeof e.when!=`function`)throw new c(`${n}.when must be a function`)}function d(e){return e===`*`?0:e.endsWith(`:*`)?1:2}function f(e){return+!e.role.includes(`*`)+d(e.resource)+d(e.action)}function p(e,t){u(e,t);let n=Array.isArray(e.role)?[...e.role]:[e.role],r=Object.freeze([...new Set(n)]),i=Object.freeze({action:e.action,effect:e.effect,priority:e.priority??0,resource:e.resource,role:r,...e.when===void 0?{}:{when:e.when}}),a=f(i),o=i.priority;return{denyBonus:+(i.effect===`deny`),index:t,priority:o,roles:r,rule:i,score:a}}var m=!globalThis.__WARD_PROD__;function h(e,...t){m&&console.error(`[@vielzeug/ward] ${e}`,...t)}function g(e,t){if(e===`*`||e===t)return!0;if(e.endsWith(`:*`)){let n=e.slice(0,-1);return t.startsWith(n)}return!1}function _(e,t){return e===`*`?!0:t===`*`?!1:e.endsWith(`:*`)?t.startsWith(e.slice(0,-1)):e===t}function v(e){if(typeof e!=`object`||!e)throw new c(`Invalid principal: expected { id: string, roles: string[] }`);let t=e;if(typeof t.id!=`string`||!t.id.trim())throw new c(`Invalid principal: id must be a non-empty string`);if(!Array.isArray(t.roles)||t.roles.some(e=>typeof e!=`string`||!e.trim()))throw new c(`Invalid principal: roles must be an array of non-empty strings`)}function y(e){e!==null&&v(e)}function b(e,n){return n===null?e.includes(t):e.every(e=>e===`anonymous`)?!1:e.includes(`*`)?!0:e.some(e=>n.roles.includes(e))}function x(e,t,n,r,i,a=!1){if(!b(e.roles,t)||!g(e.rule.resource,n)||r!==void 0&&!g(e.rule.action,r))return!1;if(a||!e.rule.when)return!0;if(t===null)return!1;try{let n=e.rule.when({data:i,principal:t});return n instanceof Promise&&h(`Rule[${e.index}] when() returned a Promise. Async predicates are not supported — the Promise is truthy and will always grant access. Use a sync predicate instead.`),n}catch(t){throw new l(e.index,t)}}function S(e,t){return t.priority>e.priority||t.priority===e.priority&&t.score>e.score||t.priority===e.priority&&t.score===e.score&&t.denyBonus>e.denyBonus}function C(e,t,n,r,i){let a;for(let o of e)x(o,t,n,r,i)&&(!a||S(a,o))&&(a=o);return a}function w(e){return e?e.rule.effect===`deny`?{allowed:!1,reason:`explicit-deny`,rule:e.rule}:{allowed:!0,rule:e.rule}:{allowed:!1,reason:`no-matching-rule`}}function T(e,n){let r=n.includes(t),i=n.some(e=>e!==t);return r&&!e.includes(`anonymous`)?!1:i?e.includes(`*`)?!0:n.filter(e=>e!==t).every(t=>e.includes(t)):!0}function E(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}function D(e,t){return T(e.roles,t.roles)&&_(e.rule.resource,t.rule.resource)&&_(e.rule.action,t.rule.action)}function O(e,t){let n=[];for(let r=0;r<e.length&&n.length<t;r++)for(let i=r+1;i<e.length&&n.length<t;i++){let t=e[r],a=e[i];if(!t.rule.when&&!a.rule.when&&E(t.roles,a.roles)&&t.rule.resource===a.rule.resource&&t.rule.action===a.rule.action){n.push({indexA:t.index,indexB:a.index,kind:`duplicate`,ruleA:t.rule,ruleB:a.rule});continue}let o=S(t,a);!o&&!t.rule.when&&D(t,a)?n.push({kind:`shadowed`,shadowedIndex:a.index,shadowedRule:a.rule,shadowingIndex:t.index,shadowingRule:t.rule}):o&&!a.rule.when&&D(a,t)&&n.push({kind:`shadowed`,shadowedIndex:t.index,shadowedRule:t.rule,shadowingIndex:a.index,shadowingRule:a.rule})}return n}function k(e,t,n,r,i){let a=new Set,o=[];for(let s of r)a.has(s)||(a.add(s),C(e,t,n,s,i)?.rule.effect===`allow`&&o.push(s));return o}function A(e,t,n,r){let i=r===void 0,a=[];for(let o of e)x(o,t,n,void 0,r,i)&&a.push(o.rule);return a}function j(e=[],t={}){let{logger:n,maxConflicts:r=1/0}=t,i=e.map((e,t)=>p(e,t));function a(e,t,r,i,a){n&&n({...a,action:r,data:i,principal:e,resource:t})}function o(e,t,n,r){let o=w(C(i,e,t,n,r));return a(e,t,n,r,o),o}function s(e,t,n,r){return y(e),o(e,t,n,r)}function l(e,t){return t.map(t=>({...o(e,t.resource,t.action,t.data),action:t.action,resource:t.resource}))}function u(e,t){return t.length===0?[]:(y(e),l(e,t))}function d(e,t,n,r){return y(e),k(i,e,t,n,r)}function f(e,t,n){return y(e),A(i,e,t,n)}function m(e,t,n,r){y(e);let a=[];for(let o of i)x(o,e,t,n,r)&&a.push(o);let o;for(let e of a)(!o||S(o,e))&&(o=e);let s=w(o);return{candidates:a.map(e=>({index:e.index,priority:e.priority,rule:e.rule,score:e.score,won:e===o})),decision:s}}function h(e){v(e);let t={attributes:e.attributes?structuredClone(e.attributes):void 0,id:e.id,roles:[...e.roles]};return{allowedActions:(e,n,r)=>k(i,t,e,n,r),checkAll:e=>e.length===0?[]:l(t,e),explain:(e,n,r)=>o(t,e,n,r),rulesInScope:(e,n)=>A(i,t,e,n),trace:(e,n,r)=>m(t,e,n,r)}}let g;function _(){return g??=Object.freeze(O(i,r))}if(t.strict||t.onConflict){let e=_();if(e.length>0&&(t.onConflict&&e.forEach(t.onConflict),t.strict)){let t=e.map(e=>e.kind===`duplicate`?`Rule[${e.indexB}] ${e.kind} of Rule[${e.indexA}]`:`Rule[${e.shadowedIndex}] ${e.kind} by Rule[${e.shadowingIndex}]`).join(`; `);throw new c(`${e.length} rule conflict(s) detected: ${t}`)}}return{allowedActions:d,checkAll:u,detectConflicts:_,explain:s,forUser:h,rulesInScope:f,trace:m}}function M(e,t,n,r,i){let a=e.explain(t,n,r,i);return a.allowed?{granted:!0,principal:t}:{decision:a,granted:!1,principal:t,reason:a.reason}}async function N(e,t,n,r,i,a){return M(e,await n(t),r,i,a)}exports.ANONYMOUS=t,exports.WILDCARD=e,exports.WardConfigError=c,exports.WardError=s,exports.WardPredicateError=l,exports.allow=r,exports.createWard=j,exports.deny=i,exports.guardRequest=M,exports.guardRequestWith=N,exports.matchesPattern=g,exports.owns=o,exports.patternCovers=_,exports.predicate=a,exports.ruleFor=n;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=`*`,t=`anonymous`;function n(e,t,n,r,i){return r.map(r=>({action:r,effect:e,...i?.priority===void 0?{}:{priority:i.priority},resource:n,role:t,...i?.when===void 0?{}:{when:i.when}}))}function r(e,t,r,i){return n(`allow`,e,t,r,i)}function i(e,t,r,i){return n(`deny`,e,t,r,i)}var a={and(...e){return t=>e.every(e=>e(t))},not(e){return t=>!e(t)},or(...e){return t=>e.some(e=>e(t))},owns(e){return({data:t,principal:n})=>{if(!t||typeof t!=`object`)return!1;let r=t;return Object.hasOwn(r,e)?r[e]===n.id:!1}}};function o(e){return a.owns(e)}var s=class e extends Error{constructor(e,t){super(e,t),this.name=new.target.name,Object.setPrototypeOf(this,new.target.prototype)}static is(t){return t instanceof e}},c=class extends s{},l=class extends s{ruleIndex;constructor(e,t){let n=t instanceof Error?t.message:String(t);super(`Rule[${e}] threw: ${n}`,{cause:t}),this.ruleIndex=e}};function u(e,t){let n=`Rule[${t}]`,r=Array.isArray(e.role)?e.role:[e.role];if(r.length===0||r.some(e=>typeof e!=`string`||!e.trim()))throw new c(`${n}.role must be a non-empty string or non-empty array of strings`);if(typeof e.resource!=`string`||!e.resource.trim())throw new c(`${n}.resource must be a non-empty string`);if(e.resource.endsWith(`:`))throw new c(`${n}.resource '${String(e.resource)}' ends with ':' — did you mean '${String(e.resource)}*'?`);if(typeof e.action!=`string`||!e.action.trim())throw new c(`${n}.action must be a non-empty string`);if(e.action.endsWith(`:`))throw new c(`${n}.action '${String(e.action)}' ends with ':' — did you mean '${String(e.action)}*'?`);if(e.effect!==`allow`&&e.effect!==`deny`)throw new c(`${n}.effect must be "allow" or "deny"`);if(e.priority!==void 0&&(typeof e.priority!=`number`||!Number.isFinite(e.priority)))throw new c(`${n}.priority must be a finite number`);if(e.when!==void 0&&typeof e.when!=`function`)throw new c(`${n}.when must be a function`)}function d(e){return e===`*`?0:e.endsWith(`:*`)?1:2}function f(e){return+!e.role.includes(`*`)+d(e.resource)+d(e.action)}function p(e,t){u(e,t);let n=Array.isArray(e.role)?[...e.role]:[e.role],r=Object.freeze([...new Set(n)]),i=Object.freeze({action:e.action,effect:e.effect,priority:e.priority??0,resource:e.resource,role:r,...e.when===void 0?{}:{when:e.when}}),a=f(i),o=i.priority;return{denyBonus:+(i.effect===`deny`),index:t,priority:o,roles:r,rule:i,score:a}}function m(e,t){if(e===`*`||e===t)return!0;if(e.endsWith(`:*`)){let n=e.slice(0,-1);return t.startsWith(n)}return!1}function h(e,t){return e===`*`?!0:t===`*`?!1:e.endsWith(`:*`)?t.startsWith(e.slice(0,-1)):e===t}function g(e){if(typeof e!=`object`||!e)throw new c(`Invalid principal: expected { id: string, roles: string[] }`);let t=e;if(typeof t.id!=`string`||!t.id.trim())throw new c(`Invalid principal: id must be a non-empty string`);if(!Array.isArray(t.roles)||t.roles.some(e=>typeof e!=`string`||!e.trim()))throw new c(`Invalid principal: roles must be an array of non-empty strings`)}function _(e){e!==null&&g(e)}function v(e,n){return n===null?e.includes(t):e.every(e=>e===`anonymous`)?!1:e.includes(`*`)?!0:e.some(e=>n.roles.includes(e))}function y(e,t,n,r,i,a=!1){if(!v(e.roles,t)||!m(e.rule.resource,n)||r!==void 0&&!m(e.rule.action,r))return!1;if(a||!e.rule.when)return!0;if(t===null)return!1;try{let n=e.rule.when({data:i,principal:t});if(n instanceof Promise)throw TypeError(`Rule[${e.index}] when() returned a Promise. Async predicates are not supported — use a synchronous predicate.`);return n}catch(t){throw new l(e.index,t)}}function b(e,t){return t.priority>e.priority||t.priority===e.priority&&t.score>e.score||t.priority===e.priority&&t.score===e.score&&t.denyBonus>e.denyBonus}function x(e,t,n,r,i){let a;for(let o of e)y(o,t,n,r,i)&&(!a||b(a,o))&&(a=o);return a}function S(e){return e?e.rule.effect===`deny`?{allowed:!1,reason:`explicit-deny`,rule:e.rule}:{allowed:!0,rule:e.rule}:{allowed:!1,reason:`no-matching-rule`}}function C(e,n){let r=n.includes(t),i=n.some(e=>e!==t);return r&&!e.includes(`anonymous`)?!1:i?e.includes(`*`)?!0:n.filter(e=>e!==t).every(t=>e.includes(t)):!0}function w(e,t){if(e.length!==t.length)return!1;let n=new Set(e);return t.every(e=>n.has(e))}function T(e,t){return C(e.roles,t.roles)&&h(e.rule.resource,t.rule.resource)&&h(e.rule.action,t.rule.action)}function E(e,t){let n=[];for(let r=0;r<e.length&&n.length<t;r++)for(let i=r+1;i<e.length&&n.length<t;i++){let t=e[r],a=e[i];if(!t.rule.when&&!a.rule.when&&w(t.roles,a.roles)&&t.rule.resource===a.rule.resource&&t.rule.action===a.rule.action){n.push({indexA:t.index,indexB:a.index,kind:`duplicate`,ruleA:t.rule,ruleB:a.rule});continue}let o=b(t,a);!o&&!t.rule.when&&T(t,a)?n.push({kind:`shadowed`,shadowedIndex:a.index,shadowedRule:a.rule,shadowingIndex:t.index,shadowingRule:t.rule}):o&&!a.rule.when&&T(a,t)&&n.push({kind:`shadowed`,shadowedIndex:t.index,shadowedRule:t.rule,shadowingIndex:a.index,shadowingRule:a.rule})}return n}function D(e,t,n,r,i){let a=new Set,o=[];for(let s of r)a.has(s)||(a.add(s),x(e,t,n,s,i)?.rule.effect===`allow`&&o.push(s));return o}function O(e,t,n,r){let i=r===void 0,a=[];for(let o of e)y(o,t,n,void 0,r,i)&&a.push(o.rule);return a}function k(e=[],t={}){let{logger:n,maxConflicts:r=1/0}=t,i=e.map((e,t)=>p(e,t));function a(e,t,r,i,a){n&&n({...a,action:r,data:i,principal:e,resource:t})}function o(e,t,n,r){let o=S(x(i,e,t,n,r));return a(e,t,n,r,o),o}function s(e){let{action:t,data:n,principal:r,resource:i}=e;return _(r),o(r,i,t,n)}function l(e,t){return t.map(t=>({...o(e,t.resource,t.action,t.data),action:t.action,resource:t.resource}))}function u(e,t){return t.length===0?[]:(_(e),l(e,t))}function d(e){let{data:t,knownActions:n,principal:r,resource:a}=e;return _(r),D(i,r,a,n,t)}function f(e){let{data:t,principal:n,resource:r}=e;return _(n),O(i,n,r,t)}function m(e){let{action:t,data:n,principal:r,resource:a}=e;_(r);let o=[];for(let e of i)y(e,r,a,t,n)&&o.push(e);let s;for(let e of o)(!s||b(s,e))&&(s=e);let c=S(s);return{candidates:o.map(e=>({index:e.index,priority:e.priority,rule:e.rule,score:e.score,won:e===s})),decision:c}}function h(e){g(e);let t={attributes:e.attributes?structuredClone(e.attributes):void 0,id:e.id,roles:[...e.roles]};return{allowedActions:e=>D(i,t,e.resource,e.knownActions,e.data),checkAll:e=>e.length===0?[]:l(t,e),explain:e=>o(t,e.resource,e.action,e.data),rulesInScope:e=>O(i,t,e.resource,e.data),trace:e=>m({action:e.action,data:e.data,principal:t,resource:e.resource})}}let v;function C(){return v??=Object.freeze(E(i,r))}if(t.strict||t.onConflict){let e=C();if(e.length>0&&(t.onConflict&&e.forEach(t.onConflict),t.strict)){let t=e.map(e=>e.kind===`duplicate`?`Rule[${e.indexB}] ${e.kind} of Rule[${e.indexA}]`:`Rule[${e.shadowedIndex}] ${e.kind} by Rule[${e.shadowingIndex}]`).join(`; `);throw new c(`${e.length} rule conflict(s) detected: ${t}`)}}return{allowedActions:d,checkAll:u,detectConflicts:C,explain:s,forUser:h,rulesInScope:f,trace:m}}function A(e){let t=e.ward.explain({action:e.action,data:e.data,principal:e.principal,resource:e.resource});return t.allowed?{granted:!0,principal:e.principal}:{decision:t,granted:!1,principal:e.principal,reason:t.reason}}async function j(e){let t=await e.extractPrincipal(e.req);return A({action:e.action,data:e.data,principal:t,resource:e.resource,ward:e.ward})}exports.ANONYMOUS=t,exports.WILDCARD=e,exports.WardConfigError=c,exports.WardError=s,exports.WardPredicateError=l,exports.allow=r,exports.createWard=k,exports.deny=i,exports.guardRequest=A,exports.guardRequestWith=j,exports.matchesPattern=m,exports.owns=o,exports.patternCovers=h,exports.predicate=a,exports.ruleFor=n;
2
2
  //# sourceMappingURL=ward.cjs.map