@authup/access 1.0.0-beta.66 → 1.0.0-beta.67

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 (30) hide show
  1. package/dist/index.d.mts +86 -6
  2. package/dist/index.d.mts.map +1 -1
  3. package/dist/index.mjs +149 -29
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/permission/authorization/module.d.ts +12 -5
  6. package/dist/permission/authorization/module.d.ts.map +1 -1
  7. package/dist/permission/authorization/policy.d.ts +9 -1
  8. package/dist/permission/authorization/policy.d.ts.map +1 -1
  9. package/dist/permission/authorization/types.d.ts +15 -1
  10. package/dist/permission/authorization/types.d.ts.map +1 -1
  11. package/dist/permission/evaluator/module.d.ts.map +1 -1
  12. package/dist/permission/evaluator/types.d.ts +8 -1
  13. package/dist/permission/evaluator/types.d.ts.map +1 -1
  14. package/dist/permission/realm-scope/helpers.d.ts +1 -1
  15. package/dist/permission/realm-scope/helpers.d.ts.map +1 -1
  16. package/dist/policy/built-in/date/evaluator.d.ts.map +1 -1
  17. package/dist/policy/built-in/permission-binding/identity-evaluator.d.ts.map +1 -1
  18. package/dist/policy/built-in/time/evaluator.d.ts.map +1 -1
  19. package/dist/policy/constants.d.ts +11 -0
  20. package/dist/policy/constants.d.ts.map +1 -1
  21. package/dist/policy/evaluation/context/define.d.ts.map +1 -1
  22. package/dist/policy/evaluation/context/index.d.ts +1 -0
  23. package/dist/policy/evaluation/context/index.d.ts.map +1 -1
  24. package/dist/policy/evaluation/context/transition.d.ts +13 -0
  25. package/dist/policy/evaluation/context/transition.d.ts.map +1 -0
  26. package/dist/policy/evaluation/context/types.d.ts +18 -0
  27. package/dist/policy/evaluation/context/types.d.ts.map +1 -1
  28. package/dist/policy/types.d.ts +5 -0
  29. package/dist/policy/types.d.ts.map +1 -1
  30. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["normalizeDate","toDate"],"sources":["../src/permission/error/module.ts","../src/permission/error/check.ts","../src/permission/realm-scope/constants.ts","../src/permission/realm-scope/helpers.ts","../src/permission/helpers/key.ts","../src/permission/helpers/aggregate.ts","../src/permission/helpers/equal.ts","../src/permission/helpers/grant.ts","../src/permission/provider/memory.ts","../src/policy/issue/constants.ts","../src/policy/issue/define.ts","../src/policy/error/module.ts","../src/policy/error/check.ts","../src/policy/engine/module.ts","../src/policy/data.ts","../src/policy/evaluation/context/define.ts","../src/policy/helpers/invert.ts","../src/policy/built-in/attribute-names/validator.ts","../src/policy/built-in/attributes/define.ts","../src/policy/built-in/constants.ts","../src/policy/built-in/attributes/validator.ts","../src/policy/built-in/attributes/evaluator.ts","../src/policy/built-in/attribute-names/evaluator.ts","../src/policy/built-in/composite/validator.ts","../src/policy/built-in/composite/evaluator.ts","../src/policy/built-in/composite/helper.ts","../src/policy/built-in/date/validator.ts","../src/policy/built-in/date/evaluator.ts","../src/policy/built-in/identity/data/validator.ts","../src/policy/built-in/identity/validator.ts","../src/policy/built-in/identity/evaluator.ts","../src/policy/built-in/realm-match/validator.ts","../src/policy/built-in/realm-match/evaluator.ts","../src/policy/built-in/permission-binding/validator.ts","../src/policy/built-in/permission-binding/identity-evaluator.ts","../src/policy/built-in/permission-binding/module.ts","../src/policy/built-in/time/constants.ts","../src/policy/built-in/time/helpers.ts","../src/policy/built-in/time/validator.ts","../src/policy/built-in/time/evaluator.ts","../src/policy/built-in/define.ts","../src/policy/constants.ts","../src/policy/input.ts","../src/permission/evaluator/module.ts","../src/permission/authorization/error.ts","../src/permission/authorization/check.ts","../src/permission/authorization/schema.ts","../src/permission/authorization/check-schema.ts","../src/permission/authorization/constants.ts","../src/permission/authorization/policy.ts","../src/permission/authorization/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { AuthupErrorOptions } from '@authup/errors';\nimport { AuthupError, ErrorCode, markInstanceof } from '@authup/errors';\nimport type { PolicyIssue } from '../../policy';\n\nexport const PERMISSION_ERROR_INSTANCE = Symbol.for('@authup/access/PermissionError');\n\nexport class PermissionError extends AuthupError {\n constructor(options: AuthupErrorOptions = {}) {\n super({\n ...options,\n message: options.message || 'A permission error occurred.',\n code: options.code || ErrorCode.PERMISSION_DENIED,\n });\n markInstanceof(this, PERMISSION_ERROR_INSTANCE);\n }\n\n static notFound(name: string) {\n return new PermissionError({\n message: `The permission ${name} was not found.`,\n code: ErrorCode.PERMISSION_NOT_FOUND,\n });\n }\n\n static denied(name: string) {\n return new PermissionError({\n message: `The permission ${name} has not been granted.`,\n code: ErrorCode.PERMISSION_DENIED,\n });\n }\n\n static deniedAll(names: string[]) {\n return new PermissionError({\n message: `None of the permissions ${names.join(', ')} has been granted.`,\n code: ErrorCode.PERMISSION_DENIED,\n });\n }\n\n static evaluationFailed(name: string | string[], issues?: PolicyIssue[]) {\n if (Array.isArray(name)) {\n return new PermissionError({\n message: `The evaluation of permissions ${name.join(', ')} failed`,\n code: ErrorCode.PERMISSION_EVALUATION_FAILED,\n issues,\n });\n }\n\n return new PermissionError({\n message: `The evaluation of permission ${name} failed`,\n code: ErrorCode.PERMISSION_EVALUATION_FAILED,\n issues,\n });\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ErrorCode, isAuthupError, matchesInstanceof } from '@authup/errors';\nimport { PERMISSION_ERROR_INSTANCE, type PermissionError } from './module';\n\nexport function isPermissionError(input: unknown): input is PermissionError {\n if (matchesInstanceof(input, PERMISSION_ERROR_INSTANCE)) {\n return true;\n }\n\n if (!isAuthupError(input)) {\n return false;\n }\n\n return input.code === ErrorCode.PERMISSION_NOT_FOUND ||\n input.code === ErrorCode.PERMISSION_DENIED ||\n input.code === ErrorCode.PERMISSION_EVALUATION_FAILED;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * Actor-relative realm reach of a permission grant.\n *\n * Total order (least -> most permissive): none < own < ownOrNull < any.\n * A missing/unknown column coerces to `own` (fail-closed); `none` is only ever an\n * explicit value (the grant reaches no realm at all).\n */\nexport enum RealmScope {\n /** No reach — the grant matches no resource realm. */\n NONE = 'none',\n /** Own realm only — resource realm must equal the actor's realm. */\n OWN = 'own',\n /** Own realm or null/global resources (realmId === null). */\n OWN_OR_NULL = 'ownOrNull',\n /** Any realm, including null/global. */\n ANY = 'any',\n}\n\n/** Numeric restrictiveness order — internal to the fold/compare helpers. */\nexport const REALM_SCOPE_ORDER: Record<`${RealmScope}`, number> = {\n [RealmScope.NONE]: 0,\n [RealmScope.OWN]: 1,\n [RealmScope.OWN_OR_NULL]: 2,\n [RealmScope.ANY]: 3,\n};\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { REALM_SCOPE_ORDER, RealmScope } from './constants';\n\n/**\n * Coerce an arbitrary value to a RealmScope, defaulting to `own` for missing /\n * null / unknown input (fail-closed). `none` is honoured only when explicit.\n */\nexport function normalizeRealmScope(value?: `${RealmScope}` | null): `${RealmScope}` {\n return value === RealmScope.ANY ||\n value === RealmScope.OWN_OR_NULL ||\n value === RealmScope.NONE ?\n value :\n RealmScope.OWN;\n}\n\n/**\n * Numeric comparison of two realm scopes by restrictiveness.\n * Negative when `a` is more restrictive than `b`, positive when less.\n */\nexport function compareRealmScope(\n a?: `${RealmScope}` | null,\n b?: `${RealmScope}` | null,\n): number {\n return REALM_SCOPE_ORDER[normalizeRealmScope(a)] - REALM_SCOPE_ORDER[normalizeRealmScope(b)];\n}\n\n/** Fold scopes to the MOST permissive (ordered max). Empty folds to `own`. */\nexport function maxRealmScope(values: Array<`${RealmScope}` | null | undefined>): `${RealmScope}` {\n let max: `${RealmScope}` = RealmScope.NONE;\n let seen = false;\n for (const value of values) {\n seen = true;\n const scope = normalizeRealmScope(value);\n if (REALM_SCOPE_ORDER[scope] > REALM_SCOPE_ORDER[max]) {\n max = scope;\n }\n }\n // Empty input is fail-closed `own` (not `none`).\n return seen ? max : RealmScope.OWN;\n}\n\n/** Fold scopes to the MORE restrictive (ordered min) — used to CAP a grant. Empty folds to `own`. */\nexport function minRealmScope(values: Array<`${RealmScope}` | null | undefined>): `${RealmScope}` {\n let min: `${RealmScope}` = RealmScope.ANY;\n let seen = false;\n for (const value of values) {\n seen = true;\n const scope = normalizeRealmScope(value);\n if (REALM_SCOPE_ORDER[scope] < REALM_SCOPE_ORDER[min]) {\n min = scope;\n }\n }\n return seen ? min : RealmScope.OWN;\n}\n\n/**\n * Whether `scope` reaches a single resource realm `resourceRealmId` for an actor whose\n * realm is `identityRealmId`/`identityRealmName`.\n *\n * - `any` -> always.\n * - `none` -> never.\n * - realm-less actor (no realmId and no realmName) -> never `own`/`ownOrNull`.\n * - resource realm `null` (global) -> only `ownOrNull`.\n * - concrete resource realm -> must equal the actor's own realm (by id or name).\n */\nfunction matchesSingle(\n normalized: `${RealmScope}`,\n resourceRealmId: string | null,\n identityRealmId: string | null,\n identityRealmName: string | null,\n): boolean {\n if (resourceRealmId === null) {\n return normalized === RealmScope.OWN_OR_NULL;\n }\n return resourceRealmId === identityRealmId || resourceRealmId === identityRealmName;\n}\n\n/**\n * Whether `scope` reaches the resource. The resource realm may be presented as a single\n * id, `null` (global), or an array of realm ids — the array form (a resource that spans\n * multiple realms) requires the scope to reach EVERY listed realm (unanimous, fail-closed),\n * so any app/entity can express its realm via one or many keys under the canonical contract.\n */\nexport function realmScopeMatches(\n scope: `${RealmScope}` | null | undefined,\n resourceRealmId: string | string[] | null | undefined,\n identityRealmId: string | null | undefined,\n identityRealmName?: string | null,\n): boolean {\n const normalized = normalizeRealmScope(scope);\n if (normalized === RealmScope.ANY) {\n return true;\n }\n if (normalized === RealmScope.NONE) {\n return false;\n }\n\n const realmId = identityRealmId ?? null;\n const realmName = identityRealmName ?? null;\n if (realmId === null && realmName === null) {\n return false;\n }\n\n if (Array.isArray(resourceRealmId)) {\n // Fail closed: an empty realm set is unreachable for a scoped actor (`any`\n // already returned above). `[].every()` would otherwise vacuously pass.\n if (resourceRealmId.length === 0) {\n return false;\n }\n return resourceRealmId.every((id) => matchesSingle(normalized, id ?? null, realmId, realmName));\n }\n\n return matchesSingle(normalized, resourceRealmId ?? null, realmId, realmName);\n}\n","/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n\nimport type { BasePermission } from '../types.ts';\n\nfunction formatKeySegment(value?: string | null): string {\n return value || '*';\n}\n\nexport function buildPermissionKey(\n input: BasePermission,\n) {\n return `${formatKeySegment(input.realmId)}/${formatKeySegment(input.clientId)}/${input.name}`;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { DecisionStrategy } from '@authup/kit';\nimport type { BasePolicy } from '../../policy';\nimport { normalizeRealmScope } from '../realm-scope';\nimport type {\n PermissionGrant,\n PermissionPolicyBinding,\n PermissionPolicyBindingAggregated,\n} from '../types';\nimport { buildPermissionKey } from './key';\n\ntype CompositePolicy = BasePolicy & {\n decisionStrategy?: `${DecisionStrategy}`,\n children: BasePolicy[],\n};\n\n/**\n * One disjunction term per raw binding: the grant's realm reach (fail-closed `own` default)\n * paired with its policy — the raw single policy (its `id` preserved for junction propagation),\n * a composite over multiple policies (Layer-1 permission policies, combined under the\n * permission's decisionStrategy), or `undefined` when the grant is unrestricted.\n */\nfunction buildGrant(binding: PermissionPolicyBinding): PermissionGrant {\n let policy: BasePolicy | undefined;\n if (binding.policies && binding.policies.length === 1) {\n policy = binding.policies[0];\n } else if (binding.policies && binding.policies.length > 1) {\n const composite: CompositePolicy = {\n type: 'composite',\n decisionStrategy: binding.permission.decisionStrategy || DecisionStrategy.UNANIMOUS,\n children: binding.policies,\n };\n policy = composite;\n }\n\n return {\n realmScope: normalizeRealmScope(binding.realmScope),\n policy,\n };\n}\n\n/**\n * Group raw permission-policy bindings by permission key into the actor's disjunction of\n * `(realmScope, policy)` grants per permission — with NO lossy collapse. Every consumer\n * (the binding evaluator, isSuperset, junction propagation, the memory provider) evaluates the\n * grant disjunction directly, so each grant's realm reach stays paired with the policy that\n * gates it.\n */\nexport function aggregatePermissionPolicyBindings(\n input: PermissionPolicyBinding[],\n): PermissionPolicyBindingAggregated[] {\n const grouped: Record<string, PermissionPolicyBinding[]> = input\n .reduce((previous, current) => {\n const key = buildPermissionKey(current.permission);\n if (!previous[key]) {\n previous[key] = [];\n }\n\n previous[key].push(current);\n\n return previous;\n }, {} as Record<string, PermissionPolicyBinding[]>);\n\n const output: PermissionPolicyBindingAggregated[] = [];\n for (const group of Object.values(grouped)) {\n output.push({\n permission: group[0]!.permission,\n grants: group.map(buildGrant),\n });\n }\n\n return output;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BasePermission } from '../types';\n\nexport function isPermissionPolicyBindingEqual(\n a: { permission: BasePermission },\n b: { permission: BasePermission },\n): boolean {\n if (a.permission.name !== b.permission.name) {\n return false;\n }\n\n if ((a.permission.realmId ?? null) !== (b.permission.realmId ?? null)) {\n return false;\n }\n\n if ((a.permission.clientId ?? null) !== (b.permission.clientId ?? null)) {\n return false;\n }\n\n return true;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isEqual } from 'smob';\nimport type { BasePolicy } from '../../policy';\nimport { compareRealmScope } from '../realm-scope';\nimport type { PermissionGrant } from '../types';\n\n/**\n * Policy fields that do NOT affect evaluation — persisted identity, audit and label columns plus\n * the loaded `parent` / `realm` relation objects. They are stripped before the structural compare\n * in isPolicyEquivalent so two DISTINCT rows with identical configuration still match. Verified\n * against every built-in evaluator, which read only `type`, `invert`, `decisionStrategy`,\n * `children` and the type-specific config (query / names / types / start / end / interval /\n * dayOf* / attributeName* / scope). `parent` is additionally a circular back-reference and\n * `realm` a nested object with its own id, so leaving either in would break the deep compare.\n *\n * SECURITY INVARIANT: every key here MUST stay non-evaluation-affecting. Adding an\n * evaluation-relevant field would silently widen equivalence into an over-permit. New *config*\n * fields need NOT be added — they are compared by default, which is the fail-closed direction.\n */\nconst NON_SEMANTIC_POLICY_KEYS = new Set<string>([\n 'id',\n 'builtIn',\n 'name',\n 'displayName',\n 'description',\n 'parentId',\n 'parent',\n 'realmId',\n 'realm',\n 'createdAt',\n 'updatedAt',\n]);\n\n/**\n * Project a policy node onto its evaluation-relevant configuration: drop the non-semantic keys\n * and recurse through `children` (the only field that carries nested policy nodes). Config values\n * (e.g. an `attributes` `query`) are left untouched, so a semantic `id` / `name` key *inside* a\n * query is never mistaken for the policy's own identity column.\n */\nfunction normalizePolicyForEquality(policy: BasePolicy): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(policy as Record<string, unknown>)) {\n if (NON_SEMANTIC_POLICY_KEYS.has(key)) {\n continue;\n }\n\n if (\n key === 'children' &&\n Array.isArray(value)\n ) {\n result[key] = value.map((child) => normalizePolicyForEquality(child as BasePolicy));\n continue;\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Whether two restriction policies are provably the SAME policy for domination purposes — by\n * persisted identity OR by identical configuration, never by evaluated effect. Fast path: equal\n * primary-key `id` means the same persisted row (the `typeof … === 'string'` guards keep an\n * id-less / missing-id policy out of it — never `undefined === undefined`). Otherwise fall back to\n * a structural value-compare of the configuration (`normalizePolicyForEquality` strips the\n * non-semantic identity / audit / relation columns, `isEqual` deep-compares the rest), so two\n * distinct rows with identical config — the same predicate — still dominate. Comparing by\n * *effect* is undecidable (a policy is a predicate over PolicyData), so we accept ONLY provable\n * identity or provable structural equality; a genuinely different configuration is treated as\n * distinct (fail-closed) — isSuperset must never assume one restriction covers a different one.\n */\nfunction isPolicyEquivalent(parent: BasePolicy, child: BasePolicy): boolean {\n const parentId = (parent as { id?: unknown }).id;\n const childId = (child as { id?: unknown }).id;\n\n if (\n typeof parentId === 'string' &&\n typeof childId === 'string' &&\n parentId === childId\n ) {\n return true;\n }\n\n return isEqual(normalizePolicyForEquality(parent), normalizePolicyForEquality(child));\n}\n\n/**\n * Whether the actor's `parent` policy provably covers the target's `child` policy on a shared\n * permission. Conservative / fail-closed:\n * - an unrestricted parent (no policy) covers any child;\n * - a restricted parent NEVER covers an unrestricted child — it cannot confer the wider,\n * policy-free reach it does not itself hold;\n * - two restricted grants cover one another only when their policies are provably equivalent.\n * A DIFFERENT policy is NOT assumed to be a subset (#3159: the predecessor treated any two\n * policy-bound grants as mutually dominating, a latent over-permit across disjoint policy\n * scopes — e.g. an actor restricted to `department=X` conferring a `department=Y` grant).\n */\nfunction policyDominates(parent?: BasePolicy, child?: BasePolicy): boolean {\n if (!parent) {\n return true;\n }\n\n if (!child) {\n return false;\n }\n\n return isPolicyEquivalent(parent, child);\n}\n\n/**\n * Whether the actor's `parent` grant covers the target's `child` grant: it reaches at least as\n * far (ordered none < own < ownOrNull < any) AND its policy provably covers the child's\n * (see `policyDominates`). Used per grant by `isSuperset` over the aggregated disjunction —\n * every child grant must be dominated by SOME parent grant.\n */\nexport function grantDominates(parent: PermissionGrant, child: PermissionGrant): boolean {\n if (compareRealmScope(parent.realmScope, child.realmScope) < 0) {\n return false;\n }\n\n return policyDominates(parent.policy, child.policy);\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { aggregatePermissionPolicyBindings, buildPermissionKey } from '../helpers';\nimport type { PermissionPolicyBinding, PermissionPolicyBindingAggregated } from '../types';\nimport type { IPermissionProvider, PermissionGetOptions } from './types';\n\nexport class PermissionMemoryProvider implements IPermissionProvider {\n protected items : Record<string, PermissionPolicyBindingAggregated> = {};\n\n constructor(items: PermissionPolicyBinding[] = []) {\n this.setMany(items);\n }\n\n async findOne(\n options: PermissionGetOptions,\n ): Promise<PermissionPolicyBindingAggregated | null> {\n const key = buildPermissionKey({\n name: options.name,\n clientId: options.clientId,\n realmId: options.realmId,\n });\n\n const entry = this.items[key];\n if (entry) {\n return entry;\n }\n\n return null;\n }\n\n setMany(input: PermissionPolicyBinding[]) {\n this.items = aggregatePermissionPolicyBindings(input)\n .reduce((prev, current) => {\n const key = buildPermissionKey(current.permission);\n prev[key] = current;\n return prev;\n }, {} as Record<string, PermissionPolicyBindingAggregated>);\n }\n}\n","/*\n * Copyright (c) 2026-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum PolicyIssueSeverity {\n WARNING = 'warning',\n ERROR = 'error',\n}\n\nexport enum PolicyIssueCode {\n // Data/Input\n DATA_MISSING = 'DATA_MISSING',\n DATA_INVALID = 'DATA_INVALID',\n\n // Policy Spec / Config\n INVALID = 'INVALID',\n TYPE_UNKNOWN = 'TYPE_UNKNOWN',\n FIELD_MISSING = 'FIELD_MISSING',\n FIELD_INVALID = 'FIELD_INVALID',\n\n // Composite / Tree evaluation\n CHILD_INVALID = 'CHILD_INVALID',\n CHILD_EVALUATION_FAILED = 'CHILD_EVALUATION_FAILED',\n\n // Engine / Evaluator registry\n EVALUATION_DENIED = 'EVALUATION_DENIED',\n EVALUATOR_NOT_FOUND = 'EVALUATOR_NOT_FOUND',\n EVALUATOR_ERROR = 'EVALUATOR_ERROR',\n\n // Execution control\n SKIPPED_EXCLUDED = 'SKIPPED_EXCLUDED',\n SKIPPED_NOT_INCLUDED = 'SKIPPED_NOT_INCLUDED',\n\n // Internal / unexpected\n INTERNAL_ERROR = 'INTERNAL_ERROR',\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueGroup, defineIssueItem } from '@ebec/core';\nimport type { PolicyIssueGroup, PolicyIssueItem } from './types.ts';\n\nexport function definePolicyIssueItem(input: Omit<PolicyIssueItem, 'type'>) : PolicyIssueItem {\n return defineIssueItem(input);\n}\n\nexport function definePolicyIssueGroup(input: Omit<PolicyIssueGroup, 'type'>) : PolicyIssueGroup {\n return defineIssueGroup(input);\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { AuthupError, ErrorCode, markInstanceof } from '@authup/errors';\nimport type { PolicyIssue } from '../issue';\n\nexport const POLICY_ERROR_INSTANCE = Symbol.for('@authup/access/PolicyError');\n\nexport class PolicyError extends AuthupError {\n constructor(message?: string, code?: string | null, issues?: PolicyIssue[]) {\n super({\n message,\n code: code ?? undefined,\n issues,\n });\n markInstanceof(this, POLICY_ERROR_INSTANCE);\n }\n\n static evaluatorNotFound(type: string) {\n return new PolicyError(\n `No evaluator is registered to handle the policy: ${type}`,\n ErrorCode.POLICY_EVALUATOR_NOT_FOUND,\n );\n }\n\n static evaluatorNotProcessable() {\n return new PolicyError(\n 'The evaluator can not process the policy.',\n ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE,\n );\n }\n\n static evaluatorContextInvalid() {\n return new PolicyError(\n 'The evaluator context is not valid.',\n ErrorCode.POLICY_EVALUATOR_CONTEXT_INVALID,\n );\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ErrorCode, isAuthupError, matchesInstanceof } from '@authup/errors';\nimport { POLICY_ERROR_INSTANCE, type PolicyError } from './module';\n\nexport function isPolicyError(input: unknown): input is PolicyError {\n if (matchesInstanceof(input, POLICY_ERROR_INSTANCE)) {\n return true;\n }\n\n if (!isAuthupError(input)) {\n return false;\n }\n\n return input.code === ErrorCode.POLICY_EVALUATOR_NOT_FOUND ||\n input.code === ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE ||\n input.code === ErrorCode.POLICY_EVALUATOR_CONTEXT_INVALID;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ErrorCode } from '@authup/errors';\nimport { defineIssueItem } from '@ebec/core';\nimport type {\n IPolicyEvaluator,\n PolicyEvaluationContext,\n PolicyEvaluationResult,\n PolicyEvaluators,\n} from '../evaluation';\nimport type { PolicyIssue } from '../issue';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../issue';\nimport type { IPolicyEngine } from './types.ts';\nimport { PolicyError, isPolicyError } from '../error';\nimport type { BasePolicy } from '../types.ts';\n\n// Cross-realm-safe extraction of an error message from an unknown thrown\n// value. `instanceof Error` is unreliable across module boundaries (different\n// realms, dual-bundled packages), so we duck-type on the `message` shape.\nfunction errorMessage(value: unknown): string {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'message' in value &&\n typeof (value as { message: unknown }).message === 'string'\n ) {\n return (value as { message: string }).message;\n }\n return String(value);\n}\n\n/**\n * The policy engine is a component that interprets defined policies and makes decisions\n * on whether to allow or deny a particular access.\n */\nexport class PolicyEngine implements IPolicyEngine {\n protected evaluators : Record<string, IPolicyEvaluator>;\n\n constructor(evaluators: PolicyEvaluators = {}) {\n // A COPY, never the caller's object: `registerEvaluator` writes into\n // this map, and every engine is constructed from the shared\n // `PolicyDefaultEvaluators` constant. Held by reference, one engine's\n // registration reached every other engine in the process. Two\n // applications in one process then shared whichever permission-binding\n // evaluator was built last, and the older one evaluated its grants\n // against the newer one's database.\n this.evaluators = { ...evaluators };\n }\n\n public registerEvaluator(\n type: string,\n evaluator: IPolicyEvaluator,\n ) : void {\n this.evaluators[type] = evaluator;\n }\n\n public registerEvaluators(evaluators: PolicyEvaluators) {\n const keys = Object.keys(evaluators);\n for (const key of keys) {\n this.registerEvaluator(key, evaluators[key]!);\n }\n }\n\n /**\n * @param policy\n * @param ctx\n */\n async evaluate(policy: BasePolicy, ctx: PolicyEvaluationContext) : Promise<PolicyEvaluationResult> {\n // Infrastructure errors (no type, no evaluator, evaluator threw) MUST\n // fail closed regardless of `policy.invert`. Inverting an error path\n // would silently grant access on misconfiguration — with `invert: true`\n // an unregistered policy type would return success: true.\n if (!policy.type) {\n return {\n success: false,\n issues: [\n defineIssueItem({\n path: [],\n message: 'The policy can not be handled by any evaluator.',\n code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND,\n }),\n ],\n };\n }\n // When a policy is filtered out via include/exclude, treat it as a\n // neutral pass — do NOT apply `invert`. Inversion only makes sense\n // for an actual evaluation outcome; skipping a policy because it's\n // outside the current context's scope is not an outcome.\n if (\n ctx.exclude &&\n ctx.exclude.length > 0 &&\n ctx.exclude.includes(policy.type)\n ) {\n return { success: true };\n }\n\n if (\n ctx.include &&\n ctx.include.length > 0 &&\n !ctx.include.includes(policy.type)\n ) {\n return { success: true };\n }\n\n const issues : PolicyIssue[] = [];\n\n const evaluator = this.evaluators[policy.type];\n if (!evaluator) {\n issues.push(defineIssueItem({\n path: [policy.type],\n message: `The policy ${policy.type} can not be handled by any evaluator.`,\n code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND,\n }));\n\n return {\n success: false,\n issues,\n };\n }\n\n // Data-availability gate: a policy whose declared data requirements are not\n // satisfied yet is PENDING — not true, not false. Like the include/exclude\n // neutral-pass, `invert` is never applied here (the evaluator is not invoked\n // at all): unknown stays unknown under negation. Wrapped in the same try as\n // the evaluation itself so a throwing `requires()` fails closed (structured\n // deny) instead of rejecting out of `evaluate()`.\n try {\n if (evaluator.requires) {\n const missing = evaluator.requires(policy)\n .filter((key) => !ctx.data || !ctx.data.has(key));\n\n if (missing.length > 0) {\n const result : PolicyEvaluationResult = {\n success: false,\n pending: true,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: `The data propert${missing.length > 1 ? 'ies' : 'y'} ${missing.join(', ')} ${missing.length > 1 ? 'are' : 'is'} missing`,\n path: ctx.path,\n }),\n ],\n };\n\n // Condition form of the pending leaf (WHERE pushdown), on request only.\n // A throwing / null toCondition simply leaves the result condition-less —\n // the consumer falls back to a per-row post-check (fail-safe).\n if (ctx.withConditions && evaluator.toCondition) {\n try {\n const condition = await evaluator.toCondition(policy, ctx);\n if (condition) {\n result.condition = condition;\n }\n } catch {\n // not expressible — stays a post-check\n }\n }\n\n return result;\n }\n }\n\n return await evaluator.evaluate(policy, {\n ...ctx,\n evaluators: {\n ...this.evaluators,\n ...(ctx.evaluators || {}),\n },\n });\n } catch (e) {\n issues.push(defineIssueItem({\n path: [policy.type],\n message: `The ${policy.type} evaluator threw: ${errorMessage(e)}`,\n code: ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE,\n }));\n\n return {\n success: false,\n issues,\n };\n }\n }\n\n async evaluateOrFail(policy: BasePolicy, ctx: PolicyEvaluationContext) : Promise<void> {\n const issues : PolicyIssue[] = [];\n\n try {\n const outcome = await this.evaluate(policy, ctx);\n if (outcome.success) {\n return;\n }\n\n if (outcome.issues) {\n issues.push(...outcome.issues);\n }\n } catch (e) {\n if (isPolicyError(e)) {\n throw e;\n }\n\n // Surface non-PolicyError throws (DB failures, validator crashes, etc.)\n // as issues so the root cause is visible instead of being swallowed\n // behind a generic policy failure.\n issues.push(defineIssueItem({\n path: policy.type ? [policy.type] : [],\n message: errorMessage(e),\n code: ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE,\n }));\n }\n\n throw new PolicyError(`The policy ${policy.type} evaluation failed.`, undefined, issues);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport interface IPolicyData {\n set(key: string, value: unknown) : void;\n has(key: string): boolean;\n get<T = unknown>(key: string) : T;\n delete(key: string) : void;\n\n isValidated(key: string): boolean;\n setValidated(key: string) : void;\n\n clone() : IPolicyData\n}\n\nexport class PolicyData implements IPolicyData {\n protected data: Record<string, any>;\n\n protected validated : Set<string>;\n\n constructor(\n data: Record<string, any> = {},\n validated: Set<string> = new Set(),\n ) {\n this.data = data;\n this.validated = validated;\n }\n\n set<T = unknown>(key: string, value: T) : void {\n this.data[key] = value;\n this.validated.delete(key);\n }\n\n get<T = unknown>(key: string) : T {\n if (key in this.data) {\n return this.data[key];\n }\n\n throw new Error(`Policy data item ${key} does not exist.`);\n }\n\n has(key: string): boolean {\n return key in this.data;\n }\n\n delete(key: string) : void {\n delete this.data[key];\n this.validated.delete(key);\n }\n\n setValidated(key: string) : void {\n this.validated.add(key);\n }\n\n isValidated(key: string) : boolean {\n return this.validated.has(key);\n }\n\n clone() {\n return new PolicyData({ ...this.data }, new Set(this.validated));\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyEvaluationContext, PolicyEvaluationContextInput } from './types.ts';\nimport { PolicyData } from '../../data.ts';\n\nexport function definePolicyEvaluationContext(\n input: PolicyEvaluationContextInput = {},\n) : PolicyEvaluationContext {\n return {\n evaluators: input.evaluators || {},\n path: input.path || [],\n data: input.data || new PolicyData(),\n include: input.include || [],\n exclude: input.exclude || [],\n withConditions: input.withConditions ?? false,\n realmAttributeName: input.realmAttributeName,\n };\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\ntype InvertFn = (input: boolean) => boolean;\n\nexport function maybeInvertPolicyOutcome(\n outcome: boolean,\n invert?: boolean | InvertFn,\n) {\n if (typeof invert === 'undefined') {\n return outcome;\n }\n\n if (typeof invert === 'function') {\n return invert(outcome);\n }\n\n if (!invert) {\n return outcome;\n }\n\n return !outcome;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { AttributeNamesPolicy } from './types';\n\nexport class AttributeNamesPolicyValidator extends Container<AttributeNamesPolicy> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'names',\n createValidator(\n z.array(\n z.string()\n .min(3)\n .max(128),\n ),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { AttributesPolicy } from './types';\n\nexport function defineAttributesPolicy<\n T extends Record<string, any> = Record<string, any>,\n>(\n data: AttributesPolicy<T>,\n) : AttributesPolicy<T> {\n return data;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum BuiltInPolicyType {\n /**\n * Bundles different policies.\n */\n COMPOSITE = 'composite',\n /**\n * Date Based Access Control (DBAC)\n */\n DATE = 'date',\n /**\n * Time Based Access Control (TBAC)\n */\n TIME = 'time',\n /**\n * Attribute Name Based Access Control (ANBAC)\n */\n ATTRIBUTE_NAMES = 'attributeNames',\n /**\n * Attribute Based Access Control (ABAC)\n */\n ATTRIBUTES = 'attributes',\n /**\n * Realm of Identity is for attribute realm.\n */\n REALM_MATCH = 'realmMatch',\n\n /**\n * Restriction based on identity (type, id, ...)\n */\n IDENTITY = 'identity',\n\n /**\n * Restriction based on a binding between identity <-> permission\n */\n PERMISSION_BINDING = 'permissionBinding',\n\n // Location (LBAC)\n // Device (DBAC)\n}\n\nexport const SystemPolicyName = {\n DEFAULT: 'system.default',\n IDENTITY: 'system.identity',\n PERMISSION_BINDING: 'system.permission-binding',\n REALM_MATCH: 'system.realm-match',\n CLIENT_NAMES_SELF_MANAGE: 'system.client-names-self-manage',\n USER_NAMES_SELF_MANAGE: 'system.user-names-self-manage',\n} as const;\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { AttributesPolicy } from './types';\n\nexport class AttributesPolicyValidator<\n T extends Record<string, any> = Record<string, any>,\n> extends Container<AttributesPolicy<T>> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'query',\n createValidator(\n z.looseObject({}),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { not } from '@rapiq/core';\nimport type { Predicate } from '@rapiq/adapter-memory';\nimport { compileFilters } from '@rapiq/adapter-memory';\nimport { MongoFiltersParser } from '@rapiq/parser-mongo';\nimport { isObject } from '@authup/kit';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { BuiltInPolicyType } from '../constants.ts';\nimport type { AttributesPolicy } from './types';\nimport { AttributesPolicyValidator } from './validator';\n\nexport class AttributesPolicyEvaluator<\n T extends Record<string, any> = Record<string, any>,\n> implements IPolicyEvaluator {\n protected validator : AttributesPolicyValidator<T>;\n\n protected parser : MongoFiltersParser;\n\n constructor() {\n this.validator = new AttributesPolicyValidator<T>();\n this.parser = new MongoFiltersParser();\n }\n\n requires() : string[] {\n return [BuiltInPolicyType.ATTRIBUTES];\n }\n\n async toCondition(value: Record<string, any>) : Promise<ICondition | null> {\n let policy : AttributesPolicy<T>;\n let condition : ICondition;\n\n try {\n policy = await this.validator.run(value);\n this.fixQuery(policy.query);\n condition = this.parser.parse(policy.query);\n } catch {\n return null;\n }\n\n // rapiq's not() is the exact null-inclusive complement (tada5hi/rapiq#812) —\n // identical to inverting the compiled predicate's verdict per row.\n return policy.invert ? not(condition) : condition;\n }\n\n async accessData(ctx: PolicyEvaluationContext) : Promise<T | null> {\n if (!ctx.data.has(BuiltInPolicyType.ATTRIBUTES)) {\n return null;\n }\n\n if (ctx.data.isValidated(BuiltInPolicyType.ATTRIBUTES)) {\n return ctx.data.get<T>(BuiltInPolicyType.ATTRIBUTES);\n }\n\n // todo: run validator on attributes (isObject ...)\n const data = ctx.data.get<T>(BuiltInPolicyType.ATTRIBUTES);\n\n ctx.data.set(BuiltInPolicyType.ATTRIBUTES, data);\n ctx.data.setValidated(BuiltInPolicyType.ATTRIBUTES);\n\n return data;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n const policy = await this.validator.run(value);\n\n const data = await this.accessData(ctx);\n if (!data) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property attributes is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n this.fixQuery(policy.query);\n\n let testIt : Predicate;\n\n try {\n const condition = this.parser.parse(policy.query);\n\n // string equality stays byte-exact (the semantics the previous\n // @ucast/mongo2js evaluator enforced)\n testIt = compileFilters(condition, { caseSensitive: true });\n } catch (e) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.FIELD_INVALID,\n message: e instanceof Error ?\n e.message :\n 'The query could not be parsed.',\n path: ctx.path,\n }),\n ],\n };\n }\n\n return { success: maybeInvertPolicyOutcome(testIt(data), policy.invert) };\n }\n\n protected fixQuery(\n query: unknown | unknown[],\n ) {\n if (Array.isArray(query)) {\n for (const element of query) {\n this.fixQuery(element);\n }\n\n return;\n }\n\n if (isObject(query)) {\n const keys = Object.keys(query);\n for (const key of keys) {\n const value = query[key];\n\n if (isObject(value) || Array.isArray(value)) {\n this.fixQuery(value);\n continue;\n }\n\n if (\n key === '$regex' &&\n typeof value === 'string'\n ) {\n const fragments = value.match(/\\/(.*?)\\/([a-z]*)?$/i);\n if (fragments && fragments[1] !== undefined) {\n query[key] = new RegExp(fragments[1], fragments[2] || '');\n }\n }\n }\n }\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { flattenObject } from '@authup/kit';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport type { PolicyIssue } from '../../issue';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { AttributeNamesPolicyValidator } from './validator';\nimport { AttributesPolicyEvaluator } from '../attributes';\nimport { BuiltInPolicyType } from '../constants';\n\nexport class AttributeNamesPolicyEvaluator implements IPolicyEvaluator {\n protected validator : AttributeNamesPolicyValidator;\n\n protected attributesEvaluator : AttributesPolicyEvaluator;\n\n constructor() {\n this.validator = new AttributeNamesPolicyValidator();\n this.attributesEvaluator = new AttributesPolicyEvaluator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // The policy settles against EITHER data key: the ATTRIBUTE_NAMES key carries a\n // plain projection/fieldset (string[]) — \"may this actor project these field\n // names\", answerable before any row exists — while the ATTRIBUTES record keeps\n // its established key semantics. The tri-state lives HERE instead of a\n // `requires()` declaration: the engine's requires-gate is AND-semantics over the\n // declared keys, so declaring both would pend every bag carrying only one of\n // them. Checked before the validator run so gate-style calls with an empty bag\n // stay cheap.\n const hasNames = ctx.data.has(BuiltInPolicyType.ATTRIBUTE_NAMES);\n const hasAttributes = ctx.data.has(BuiltInPolicyType.ATTRIBUTES);\n\n if (!hasNames && !hasAttributes) {\n return {\n success: false,\n pending: true,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property attributeNames or attributes is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n // Conjunctive over the available sources: when both keys are present BOTH are\n // enforced — a reused bag that carries a projection alongside row attributes can\n // never weaken an existing record gate. Keys are deduplicated so a name present\n // in both sources yields one issue.\n const keys = new Set<string>();\n\n if (hasNames) {\n // Non-string entries fail closed as invalid data — silently skipping\n // them would fail open in denylist (invert) mode.\n const data = ctx.data.get(BuiltInPolicyType.ATTRIBUTE_NAMES);\n if (\n !Array.isArray(data) ||\n data.some((entry) => typeof entry !== 'string')\n ) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_INVALID,\n message: 'The data property attributeNames must be a list of attribute names',\n path: ctx.path,\n }),\n ],\n };\n }\n\n for (const entry of data) {\n keys.add(entry);\n }\n }\n\n if (hasAttributes) {\n const data = await this.attributesEvaluator.accessData(ctx);\n if (data) {\n // Nested paths are a deliberate feature: an attribute object like\n // `{user: {name: 'x'}}` flattens to `{'user.name': 'x'}` and is matched\n // against `names` entries with dotted notation. Allowlists/denylists\n // that need to govern nested fields must use the dotted-path form\n // (e.g. `'user.realmId'`); a top-level entry like `'realmId'` will\n // NOT catch a nested `user.realmId` write — that's by design, the\n // policy is precise about which path it covers.\n const attributes = flattenObject(data);\n for (const key of Object.keys(attributes)) {\n keys.add(key);\n }\n }\n }\n\n // `invert` is consumed per-key, NOT at the result level:\n // - allowlist (default): a key NOT in `names` is denied\n // - denylist (invert: true): a key IN `names` is denied\n // Result-level inversion would break the empty-input case (a request\n // with no validated attributes would flip success → fail), and would\n // produce nonsensical \"deny iff all keys are in the list\" semantics\n // for partial inputs.\n const issues : PolicyIssue[] = [];\n for (const key of keys) {\n const inList = policy.names.includes(key);\n const denied = policy.invert ? inList : !inList;\n if (denied) {\n issues.push(definePolicyIssueItem({\n code: PolicyIssueCode.EVALUATION_DENIED,\n message: policy.invert ?\n `The attribute ${key} is denied` :\n `The attribute ${key} is not included`,\n path: [...ctx.path, key],\n }));\n }\n }\n\n return {\n success: issues.length === 0,\n issues,\n };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport { DecisionStrategy } from '@authup/kit';\nimport type { CompositePolicy } from './types';\n\nexport class CompositePolicyValidator extends Container<CompositePolicy> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'decisionStrategy',\n createValidator(\n z.enum(DecisionStrategy)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'children',\n createValidator(\n z.array(z.looseObject({ type: z.string().min(3) })),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { and, not, or } from '@rapiq/core';\nimport { defineIssueGroup } from '@ebec/core';\nimport { DecisionStrategy } from '@authup/kit';\nimport { PolicyEngine } from '../../engine';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport type { PolicyIssue } from '../../issue';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { CompositePolicyValidator } from './validator';\n\nexport class CompositePolicyEvaluator implements IPolicyEvaluator {\n protected validator : CompositePolicyValidator;\n\n constructor() {\n this.validator = new CompositePolicyValidator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n // A composite policy with no children can never be satisfied — an empty\n // UNANIMOUS/CONSENSUS settles false and an empty AFFIRMATIVE settles\n // false — so a permission bound to one is permanently un-grantable.\n // Fail closed with an explicit diagnostic instead of settling `false`\n // with an empty issue list, which reads as an opaque \"stale\" permission\n // (#3304). Like the engine's unregistered-type handling, this\n // misconfiguration fails closed regardless of `invert`.\n if (policy.children.length === 0) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.INVALID,\n message: 'A composite policy must define at least one child policy.',\n path: ctx.path,\n }),\n ],\n };\n }\n\n let count = 0;\n let pending = 0;\n\n const decisionStrategy = policy.decisionStrategy ??\n DecisionStrategy.UNANIMOUS;\n\n const engine = new PolicyEngine(ctx.evaluators);\n const issues : PolicyIssue[] = [];\n const pendingIssues : PolicyIssue[] = [];\n const pendingConditions : ICondition[] = [];\n let pendingWithoutCondition = 0;\n\n for (const childPolicy of policy.children) {\n const path = [\n ...(ctx.path || []),\n ...(childPolicy.type ? [childPolicy.type] : []),\n ];\n\n const outcome = await engine.evaluate(childPolicy, {\n ...ctx,\n path,\n });\n\n // A pending child is UNKNOWN, not a failure: it neither counts nor\n // early-returns. Masking it to a settled value breaks under negation\n // (mask-then-negate ≠ negate-then-mask — issue #3286).\n if (outcome.pending) {\n pending++;\n\n if (outcome.condition) {\n pendingConditions.push(outcome.condition);\n } else {\n pendingWithoutCondition++;\n }\n\n if (outcome.issues && outcome.issues.length > 0) {\n pendingIssues.push(defineIssueGroup({\n message: `The evaluation of child policy ${childPolicy.type} is pending`,\n issues: outcome.issues,\n path,\n }));\n }\n\n continue;\n }\n\n if (outcome.success) {\n if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return {\n success: maybeInvertPolicyOutcome(true, policy.invert),\n issues: [],\n };\n }\n\n count++;\n } else {\n if (outcome.issues) {\n issues.push(defineIssueGroup({\n message: `The evaluation of child policy ${childPolicy.type} failed`,\n issues: outcome.issues || [],\n path,\n }));\n }\n\n if (decisionStrategy === DecisionStrategy.UNANIMOUS) {\n const success = maybeInvertPolicyOutcome(false, policy.invert);\n return {\n success,\n // When `invert` flips a child-failure into success,\n // suppress the issue list — surfacing failure issues\n // alongside `success: true` is misleading.\n issues: success ? [] : [\n defineIssueGroup({\n message: `The evaluation of composite policy failed (${DecisionStrategy.UNANIMOUS})`,\n issues,\n path: ctx.path,\n }),\n ],\n };\n }\n\n count--;\n }\n }\n\n // Settle the remainder: the composite settles despite pending children only\n // when no resolution of those children could change the outcome.\n let settled : boolean | null;\n switch (decisionStrategy) {\n case DecisionStrategy.AFFIRMATIVE: {\n // every settled child failed; any pending child could still succeed\n settled = pending > 0 ? null : false;\n break;\n }\n case DecisionStrategy.UNANIMOUS: {\n // every settled child succeeded; any pending child could still fail\n settled = pending > 0 ? null : count > 0;\n break;\n }\n default: {\n // CONSENSUS: final outcome is `count > 0`, each pending worth ±1\n if (count - pending > 0) {\n settled = true;\n } else if (count + pending <= 0) {\n settled = false;\n } else {\n settled = null;\n }\n }\n }\n\n if (settled === null) {\n // Unknown stays unknown — `invert` is deliberately NOT applied to the\n // pending SUCCESS. The condition form is composed structurally instead:\n // settled children are identity elements and drop out of the residual,\n // so AND residual = and(pending), OR residual = or(pending). Exact-only,\n // all-or-nothing per node: one pending child without a condition makes\n // the whole node non-expressible (an OR pushing a single disjunct would\n // wrongly EXCLUDE rows; a partial AND is a compiler-level optimization,\n // deliberately not done here). CONSENSUS thresholds over row-dependent\n // outcomes never lower. `invert` wraps the residual SYMBOLICALLY via\n // rapiq's null-inclusive-complement not() — negation applies to the\n // condition even though the pending success stays uninverted.\n let condition : ICondition | null = null;\n if (\n pendingWithoutCondition === 0 &&\n ctx.withConditions &&\n pendingConditions.length > 0 &&\n decisionStrategy !== DecisionStrategy.CONSENSUS\n ) {\n if (pendingConditions.length === 1) {\n const [first] = pendingConditions;\n condition = first ?? null;\n } else if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n condition = or(...pendingConditions);\n } else {\n condition = and(...pendingConditions);\n }\n\n if (condition && policy.invert) {\n condition = not(condition);\n }\n }\n\n return {\n success: false,\n pending: true,\n ...(condition ? { condition } : {}),\n issues: pendingIssues,\n };\n }\n\n if (settled) {\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n const success = maybeInvertPolicyOutcome(false, policy.invert);\n return {\n success,\n issues: success ? [] : [\n defineIssueGroup({\n message: `The evaluation of composite policy failed (${decisionStrategy})`,\n issues: issues || [],\n path: ctx.path,\n }),\n ],\n };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyWithType } from '../../types';\nimport { BuiltInPolicyType } from '../constants';\nimport type { CompositePolicy } from './types';\n\nexport function isCompositePolicy(\n input: PolicyWithType,\n) : input is PolicyWithType<CompositePolicy> {\n return input.type === BuiltInPolicyType.COMPOSITE;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { DatePolicy } from './types';\n\nexport class DatePolicyValidator extends Container<DatePolicy> {\n override initialize() {\n super.initialize();\n\n this.mount('start', createValidator(\n z.date()\n .or(z.iso.date())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('end', createValidator(\n z.date()\n .or(z.iso.date())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n\n this.mount('invert', createValidator(\n z.boolean()\n .or(z.undefined())\n .or(z.null())\n .optional(),\n ));\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants.ts';\nimport { DatePolicyValidator } from './validator';\n\nfunction normalizeDate(input: Date) {\n return new Date(input.getFullYear(), input.getMonth(), input.getDate());\n}\n\nfunction toDate(input: Date | string | number) : Date {\n if (typeof input === 'string') {\n return new Date(input);\n }\n\n if (typeof input === 'number') {\n return new Date(input);\n }\n\n return input;\n}\n\nexport class DatePolicyEvaluator implements IPolicyEvaluator {\n protected validator : DatePolicyValidator;\n\n constructor() {\n this.validator = new DatePolicyValidator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n let now : Date;\n\n if (ctx.data.has(BuiltInPolicyType.DATE)) {\n if (ctx.data.isValidated(BuiltInPolicyType.DATE)) {\n now = ctx.data.get<Date>(BuiltInPolicyType.DATE);\n } else {\n // todo: run validator on attributes (isObject ...)\n now = normalizeDate(toDate(ctx.data.get(BuiltInPolicyType.DATE)));\n\n ctx.data.set(BuiltInPolicyType.DATE, now);\n ctx.data.setValidated(BuiltInPolicyType.DATE);\n }\n } else {\n now = normalizeDate(new Date());\n }\n\n if (policy.start) {\n const start = normalizeDate(toDate(policy.start));\n if (now < start) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (policy.end) {\n const end = normalizeDate(toDate(policy.end));\n if (now > end) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2024-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\n\nimport type { IdentityPolicyData } from '../types.ts';\n\nexport class PolicyIdentityDataValidator extends Container<IdentityPolicyData> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'type',\n createValidator(\n z.string().min(3).max(128),\n ),\n );\n\n this.mount(\n 'id',\n createValidator(\n z.uuid(),\n ),\n );\n\n this.mount(\n 'clientId',\n createValidator(\n z.uuid()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'realmId',\n createValidator(\n z.uuid()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'realmName',\n createValidator(\n z.string().min(3).max(128)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { IdentityPolicy } from './types';\n\nexport class IdentityPolicyValidator extends Container<IdentityPolicy> {\n override initialize() {\n this.mount(\n 'types',\n createValidator(\n z.array(z.string())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants';\nimport { PolicyIdentityDataValidator } from './data';\nimport type { IdentityPolicyData } from './types';\nimport { IdentityPolicyValidator } from './validator';\n\nexport class IdentityPolicyEvaluator implements IPolicyEvaluator {\n protected validator : IdentityPolicyValidator;\n\n protected dataValidator : PolicyIdentityDataValidator;\n\n constructor() {\n this.validator = new IdentityPolicyValidator();\n this.dataValidator = new PolicyIdentityDataValidator();\n }\n\n requires() : string[] {\n return [BuiltInPolicyType.IDENTITY];\n }\n\n async accessData(ctx: PolicyEvaluationContext) : Promise<IdentityPolicyData | null> {\n if (!ctx.data.has('identity')) {\n return null;\n }\n\n if (ctx.data.isValidated('identity')) {\n return ctx.data.get<IdentityPolicyData>('identity');\n }\n\n const data = await this.dataValidator.run(ctx.data.get('identity'));\n\n ctx.data.set('identity', data);\n ctx.data.setValidated('identity');\n\n return data;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n const data = await this.accessData(ctx);\n if (!data) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property identity is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n if (!policy.types || policy.types.length === 0) {\n // Empty types is a configuration shorthand for \"no type\n // restriction\" — every identity passes. Do NOT apply `invert`;\n // inverting an empty config would silently deny all identities,\n // which is almost never the user's intent.\n return { success: true };\n }\n\n const typeAllowed = policy.types.includes(data.type);\n if (typeAllowed) {\n return { success: maybeInvertPolicyOutcome(typeAllowed, policy.invert) };\n }\n\n return {\n success: maybeInvertPolicyOutcome(typeAllowed, policy.invert),\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.EVALUATION_DENIED,\n message: `The type ${data.type} is not covered by the policy configuration`,\n path: ctx.path,\n }),\n ],\n };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport { DecisionStrategy } from '@authup/kit';\nimport { RealmScope } from '../../../permission/realm-scope';\nimport type { RealmMatchPolicy } from './types';\n\nexport class RealmMatchPolicyValidator extends Container<RealmMatchPolicy> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'decisionStrategy',\n createValidator(\n z.enum(DecisionStrategy)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'attributeName',\n createValidator(\n z.string()\n .min(3)\n .or(z.array(z.string().min(3)))\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n this.mount(\n 'attributeNameStrict',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n this.mount(\n 'attributeNullMatchAll',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'scope',\n createValidator(\n z.enum(RealmScope)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport {\n eq, \n inArray, \n nin, \n not, \n or,\n} from '@rapiq/core';\nimport { DecisionStrategy, hasOwnProperty } from '@authup/kit';\nimport { RealmScope, normalizeRealmScope, realmScopeMatches } from '../../../permission/realm-scope';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { AttributesPolicyEvaluator } from '../attributes';\nimport { BuiltInPolicyType } from '../constants';\nimport { IdentityPolicyEvaluator } from '../identity';\nimport { RealmMatchPolicyValidator } from './validator';\n\nexport class RealmMatchPolicyEvaluator implements IPolicyEvaluator {\n protected validator : RealmMatchPolicyValidator;\n\n protected identityEvaluator: IdentityPolicyEvaluator;\n\n protected attributesEvaluator : AttributesPolicyEvaluator;\n\n constructor() {\n this.validator = new RealmMatchPolicyValidator();\n this.identityEvaluator = new IdentityPolicyEvaluator();\n this.attributesEvaluator = new AttributesPolicyEvaluator();\n }\n\n requires(value: Record<string, any>) : string[] {\n // SCOPE MODE: the resource realm key (REALM_MATCH) is deliberately NOT\n // required — an absent key is the documented neutral-pass (gate checks /\n // realm-less resources), so requiring it would wrongly pend those runs.\n if (value.scope) {\n return [BuiltInPolicyType.IDENTITY];\n }\n\n return [BuiltInPolicyType.IDENTITY, BuiltInPolicyType.ATTRIBUTES];\n }\n\n /**\n * Condition form over the row's realm column, with the actor realm baked in\n * (mirrors `realmScopeMatches` / the attribute-mode match). Exactness holds for\n * row-shaped data where the referenced field exists (DB rows) — the object-bag\n * \"key absent → neutral-pass\" case has no SQL counterpart. Lowerable configs:\n * scope mode (field = single-string `attributeName`, default `realmId` — scope-mode\n * EVALUATION ignores `attributeName`, lowering reuses it as the column override),\n * and strict attribute mode with a single explicit `attributeName`. Everything\n * else (multi-key / default-key CONSENSUS, non-strict key expansion) is\n * row-shape-dependent and stays a post-check.\n */\n async toCondition(value: Record<string, any>, ctx: PolicyEvaluationContext) : Promise<ICondition | null> {\n let policy;\n try {\n policy = await this.validator.run(value);\n } catch {\n return null;\n }\n\n const identity = await this.identityEvaluator.accessData(ctx);\n if (!identity) {\n return null;\n }\n\n const realmId = identity.realmId ?? null;\n\n if (policy.scope) {\n const scope = normalizeRealmScope(policy.scope);\n const field = typeof policy.attributeName === 'string' ?\n policy.attributeName :\n 'realmId';\n\n let condition : ICondition;\n if (scope === RealmScope.ANY) {\n // constant-true: nin([]) matches everything (rapiq ConstantPlan)\n condition = nin(field, []);\n } else {\n // The lowered column (default `realmId`) holds realm IDs — the resource\n // realm is stamped from `entity.realmId`\n // (AbstractEntityService.resourceRealmMatch), so the WHERE match compares\n // that ID column against the actor's realm ID. The realm NAME is\n // deliberately NOT pushed here: it never appears in a realmId column and\n // would bind a non-uuid literal that postgres/mysql reject against a uuid\n // column (the sqlite-only test suite masks this, since sqlite is untyped).\n // Settled evaluation keeps the name-equality leniency for a name-stamped\n // resource SCALAR — which has no row-column counterpart, so parity holds\n // for realistic row-shaped data (see the exactness caveat above).\n const terms : ICondition[] = [];\n if (realmId !== null && scope !== RealmScope.NONE) {\n terms.push(eq(field, realmId));\n }\n if (scope === RealmScope.OWN_OR_NULL && (realmId !== null || identity.realmName != null)) {\n terms.push(eq(field, null));\n }\n\n if (terms.length === 0) {\n // no reach / realm-less actor with no null branch — constant-false\n condition = inArray(field, []);\n } else if (terms.length === 1) {\n condition = terms[0]!;\n } else {\n condition = or(...terms);\n }\n }\n\n return policy.invert ? not(condition) : condition;\n }\n\n if (\n typeof policy.attributeName !== 'string' ||\n (policy.attributeNameStrict ?? true) === false\n ) {\n return null;\n }\n\n // Mirrors the match loop's strict equality: `attributeValue === identity.realmId`\n // — an identity carrying an explicit `realmId: null` matches null-valued rows\n // (only an UNDEFINED identity value never matches a DB value, so it drops out).\n const key = policy.attributeName;\n const terms : ICondition[] = [];\n if (policy.attributeNullMatchAll) {\n terms.push(eq(key, null));\n }\n if (identity.realmId !== undefined) {\n terms.push(eq(key, identity.realmId));\n }\n if (identity.realmName !== undefined) {\n terms.push(eq(key, identity.realmName));\n }\n\n if (terms.length === 0) {\n return policy.invert ? nin(key, []) : inArray(key, []);\n }\n\n const condition = terms.length === 1 ? terms[0]! : or(...terms);\n return policy.invert ? not(condition) : condition;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n const identity = await this.identityEvaluator.accessData(ctx);\n if (!identity) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property identity is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n // SCOPE MODE: coarse, actor-relative realm reach (the realmScope mechanism lives\n // here). The resource realm is supplied under the REALM_MATCH data key. Key-PRESENCE\n // is the discriminator: an ABSENT realm neutral-passes (gate check / realm-less\n // resource), while a present `null` (global resource) is matched (and `own` correctly\n // denies it). Runs BEFORE the attributes-required guard below, since junction / gate\n // inputs need not carry ATTRIBUTES.\n if (policy.scope) {\n if (!ctx.data || !ctx.data.has(BuiltInPolicyType.REALM_MATCH)) {\n // Non-evaluation (no resource realm) — neutral pass, no `invert`,\n // mirroring the attribute-mode non-evaluation pass below. For a\n // query-build caller (`withConditions`) the resource realm IS the\n // unknown row column, so the reach pends with its condition form\n // instead of neutral-passing.\n if (ctx.withConditions) {\n const condition = await this.toCondition(value, ctx);\n return {\n success: false,\n pending: true,\n ...(condition ? { condition } : {}),\n };\n }\n\n return { success: true };\n }\n\n const resourceRealm = ctx.data.get<string | string[] | null>(BuiltInPolicyType.REALM_MATCH);\n return {\n success: maybeInvertPolicyOutcome(\n realmScopeMatches(\n policy.scope,\n resourceRealm ?? null,\n identity.realmId,\n identity.realmName,\n ),\n policy.invert,\n ),\n };\n }\n\n const attributes = await this.attributesEvaluator.accessData(ctx);\n if (!attributes) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property attributes is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n let keys : string[];\n if (policy.attributeName) {\n if (Array.isArray(policy.attributeName)) {\n keys = policy.attributeName;\n } else {\n keys = [policy.attributeName];\n }\n } else {\n keys = [\n 'realm_id',\n 'realm_name',\n 'realmId',\n 'realmName',\n ];\n\n policy.decisionStrategy = DecisionStrategy.CONSENSUS;\n }\n\n const attributeNameStrict = policy.attributeNameStrict ?? true;\n if (!attributeNameStrict) {\n const resourceKeys = Object.keys(attributes);\n const keysToAdd : string[] = [];\n for (const resourceKey of resourceKeys) {\n let contains : boolean = false;\n\n for (const key of keys) {\n if (\n resourceKey !== key &&\n resourceKey.includes(key)\n ) {\n contains = true;\n break;\n }\n }\n\n if (contains) {\n keysToAdd.push(resourceKey);\n }\n }\n\n if (keysToAdd.length > 0) {\n keys.push(...keysToAdd);\n }\n }\n\n let count = 0;\n let evaluated = false;\n\n for (const key of keys) {\n if (!hasOwnProperty(attributes, key)) {\n continue;\n }\n\n evaluated = true;\n\n let outcome : boolean = false;\n\n const attributeValue = attributes[key];\n\n if (\n (attributeValue === null && policy.attributeNullMatchAll) ||\n attributeValue === identity.realmId ||\n attributeValue === identity.realmName\n ) {\n outcome = true;\n }\n\n if (outcome) {\n if (policy.decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n count++;\n } else {\n if (policy.decisionStrategy === DecisionStrategy.UNANIMOUS) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n\n count--;\n }\n }\n\n if (!evaluated) {\n // No realm key found in attributes — the policy's match logic\n // didn't run. This is a \"non-evaluation\", not an outcome; treat\n // as a neutral pass without applying `invert`. Inverting here\n // would conflate \"policy doesn't apply\" with \"policy denies\".\n return { success: true };\n }\n\n return { success: maybeInvertPolicyOutcome(count > 0, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { PermissionBindingPolicy } from './types';\n\nexport class PermissionBindingPolicyValidator extends Container<PermissionBindingPolicy> {\n override initialize() {\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { and, not, or } from '@rapiq/core';\nimport type { Issue } from '@ebec/core';\nimport type { PermissionPolicyBinding, PermissionPolicyBindingAggregated } from '../../../permission/types';\nimport { aggregatePermissionPolicyBindings } from '../../../permission/helpers';\nimport { RealmScope, normalizeRealmScope } from '../../../permission/realm-scope';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { PolicyEngine } from '../../engine';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { BuiltInPolicyType } from '../constants';\nimport type { IdentityPolicyData } from '../identity';\nimport { IdentityPolicyEvaluator } from '../identity';\nimport { RealmMatchPolicyEvaluator } from '../realm-match';\nimport { PermissionBindingPolicyValidator } from './validator';\n\ntype IdentityPermissionProvider = {\n getFor(identity: IdentityPolicyData): Promise<PermissionPolicyBinding[]>,\n};\n\nexport class IdentityPermissionBindingPolicyEvaluator implements IPolicyEvaluator {\n protected validator : PermissionBindingPolicyValidator;\n\n protected identityEvaluator: IdentityPolicyEvaluator;\n\n protected realmMatchEvaluator : RealmMatchPolicyEvaluator;\n\n protected identityPermissionProvider: IdentityPermissionProvider;\n\n constructor(identityPermissionProvider: IdentityPermissionProvider) {\n this.validator = new PermissionBindingPolicyValidator();\n this.identityEvaluator = new IdentityPolicyEvaluator();\n this.realmMatchEvaluator = new RealmMatchPolicyEvaluator();\n this.identityPermissionProvider = identityPermissionProvider;\n }\n\n requires() : string[] {\n // IDENTITY is deliberately NOT declared: a missing identity must stay a\n // settled DATA_MISSING deny (fail-closed) so a scope-restricted or anonymous\n // bearer still fails the pre-gate through system.default — pending would be\n // permitted there.\n return [BuiltInPolicyType.PERMISSION_BINDING];\n }\n\n async accessData(ctx: PolicyEvaluationContext) : Promise<PermissionPolicyBindingAggregated | null> {\n if (!ctx.data.has(BuiltInPolicyType.PERMISSION_BINDING)) {\n return null;\n }\n\n if (ctx.data.isValidated(BuiltInPolicyType.PERMISSION_BINDING)) {\n return ctx.data.get(BuiltInPolicyType.PERMISSION_BINDING);\n }\n\n const data = ctx.data.get<PermissionPolicyBindingAggregated>(BuiltInPolicyType.PERMISSION_BINDING);\n\n ctx.data.set(BuiltInPolicyType.PERMISSION_BINDING, data);\n ctx.data.setValidated(BuiltInPolicyType.PERMISSION_BINDING);\n\n return data;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n const policy = await this.validator.run(value);\n\n const identity = await this.identityEvaluator.accessData(ctx);\n if (!identity) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property identity is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n const binding = await this.accessData(ctx);\n if (!binding) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property permission is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n const identityBindings = await this.identityPermissionProvider.getFor(identity)\n .then((bindings) => bindings.filter((item) => {\n if (item.permission.name !== binding.permission.name) {\n return false;\n }\n\n return (binding.permission.realmId ?? null) === (item.permission.realmId ?? null) &&\n (binding.permission.clientId ?? null) === (item.permission.clientId ?? null);\n }));\n\n if (identityBindings.length === 0) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n\n const [aggr] = aggregatePermissionPolicyBindings(identityBindings);\n if (!aggr) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n\n // identityBindings is filtered to a single (name, realm_id, client_id) key, so the\n // aggregate yields exactly one entry whose `grants` are the actor's per-grant\n // (realm_scope, policy) disjunction terms; access is the DISJUNCTION over them:\n // ∃ grant . realmScopeMatches(grant.realmScope, resource) ∧ (grant.policy passes)\n // Pairing each grant's realm reach with its OWN policy is what fixes both the mixed\n // policy-free + policy-bound UNDER-grant (a policy-free `own` grant must not mask a\n // policy-bound `any` grant's wider reach) and the symmetric OVER-grant (an `own`\n // grant's passing policy must not ride an `any` grant's wider reach).\n const issues : Issue[] = [];\n const pendingIssues : Issue[] = [];\n const conditions : ICondition[] = [];\n let pending = false;\n let lowerable = true;\n for (const grant of aggr.grants) {\n // Realm reach (coarse, actor-relative) — a SEPARATE factor from the grant's\n // policy, ANDed with it. The realm-match evaluator runs in SCOPE MODE: it reads the\n // resource realm from ctx.data[REALM_MATCH] (fallback ATTRIBUTES.realmId) and\n // neutral-passes when absent (preEvaluate / gate checks / realm-less resources) —\n // key-PRESENCE is the discriminator. Invoked DIRECTLY (not via PolicyEngine) so\n // the reach factor can never be skipped by a caller's include/exclude filters or\n // deferred by the engine's data-availability gate.\n //\n // Under `withConditions` (query-build) with no resource realm present, the\n // reach PENDS with its condition form over the row's realm column instead of\n // neutral-passing — `any` stays unrestricted and `none` reaches nothing, so\n // neither pollutes the composed WHERE with constant terms.\n let reachCondition : ICondition | null = null;\n const realmOutcome = await this.realmMatchEvaluator.evaluate(\n // `attributeName` is read by scope mode only while LOWERING (it names the\n // row column the reach binds); settled evaluation takes the resource realm\n // from the `realmMatch` data key, so passing it cannot move an evaluate()\n // outcome. It is what lets a junction gate on its owner-realm key.\n { scope: grant.realmScope, attributeName: ctx.realmAttributeName },\n ctx,\n );\n if (realmOutcome.pending) {\n const scope = normalizeRealmScope(grant.realmScope);\n if (scope === RealmScope.NONE) {\n continue;\n }\n\n if (scope !== RealmScope.ANY) {\n if (!realmOutcome.condition) {\n pending = true;\n lowerable = false;\n continue;\n }\n\n reachCondition = realmOutcome.condition;\n }\n } else if (!realmOutcome.success) {\n continue;\n }\n\n if (!grant.policy) {\n if (!reachCondition) {\n // Reach matches and this grant carries no further restriction.\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n // Reach is the grant's only restriction — a pure condition term.\n conditions.push(reachCondition);\n pending = true;\n continue;\n }\n\n // Missing evaluators is a misconfiguration: let the engine fail CLOSED with a\n // surfaced POLICY_EVALUATOR_NOT_FOUND issue (new PolicyEngine(undefined) defaults\n // to an empty registry, so grant.policy resolves to no evaluator) rather than\n // swallowing the grant with a silent issue-less deny.\n const engine = new PolicyEngine(ctx.evaluators);\n const outcome = await engine.evaluate(grant.policy, {\n ...ctx,\n path: [\n ...(ctx.path || []),\n ],\n });\n\n if (outcome.success) {\n if (!reachCondition) {\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n conditions.push(reachCondition);\n pending = true;\n continue;\n }\n\n // A PENDING junction policy (required data key absent — e.g. an ATTRIBUTES\n // policy at the pre-gate) leaves this grant term UNKNOWN, not failed: the\n // grant could still pass once the data arrives, so it must not settle the\n // disjunction to false.\n if (outcome.pending) {\n pending = true;\n\n // A caller that names its realm column has told us the row shape is not the\n // default one, and nothing rebases a GRANT policy's own condition onto it.\n // Authup's own junction reads are the case that proves it: the policy is the\n // operator's, written against the ENTITY the permission names, so lowering it\n // emits SQL over columns `auth_role_permissions` and its siblings do not have.\n // We cannot tell a row shape that does carry those fields from one that does\n // not, so refuse the class: the caller falls back to the per-row `post` branch,\n // which evaluates the same policy against the real attributes and reaches the\n // identical verdict wherever the pushdown would not have crashed. The grant's\n // REACH is unaffected — it is built above from the column the caller named, so\n // the policy-free grants that dominate real deployments still push down.\n if (ctx.withConditions && outcome.condition && !ctx.realmAttributeName) {\n conditions.push(\n reachCondition ?\n and(reachCondition, outcome.condition) :\n outcome.condition,\n );\n } else {\n lowerable = false;\n }\n\n if (outcome.issues) {\n pendingIssues.push(...outcome.issues);\n }\n\n continue;\n }\n\n if (outcome.issues) {\n issues.push(...outcome.issues);\n }\n }\n\n // No grant term settled true. If some term is still pending, the disjunction is\n // pending — deliberately uninverted (unknown stays unknown under negation). The\n // condition form composes the grant terms as a disjunction, all-or-nothing: a\n // single non-expressible grant term makes the whole binding non-expressible\n // (pushing a partial OR would wrongly exclude rows).\n if (pending) {\n const result : PolicyEvaluationResult = {\n success: false,\n pending: true,\n issues: pendingIssues,\n };\n\n if (lowerable && ctx.withConditions && conditions.length > 0) {\n const condition = conditions.length === 1 ?\n conditions[0]! :\n or(...conditions);\n result.condition = policy.invert ? not(condition) : condition;\n }\n\n return result;\n }\n\n // No grant term satisfied (reach ∧ policies). Apply `invert` ONCE to the aggregated\n // disjunction outcome — never per term, which would corrupt the quantifier.\n const success = maybeInvertPolicyOutcome(false, policy.invert);\n return {\n success,\n issues: success ? [] : issues,\n };\n }\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants';\nimport { PermissionBindingPolicyValidator } from './validator';\n\nexport class PermissionBindingPolicyEvaluator implements IPolicyEvaluator {\n protected validator: PermissionBindingPolicyValidator;\n\n constructor() {\n this.validator = new PermissionBindingPolicyValidator();\n }\n\n requires() : string[] {\n // IDENTITY is deliberately NOT declared: a missing identity must stay a\n // settled deny (fail-closed), never a pending the pre-gate would permit.\n return [BuiltInPolicyType.PERMISSION_BINDING];\n }\n\n async evaluate(value: Record<string, any>): Promise<PolicyEvaluationResult> {\n const policy = await this.validator.run(value);\n\n // todo: this must be changed when the permission-checker not only checks owned permissions.\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum TimePolicyInterval {\n DAILY = 'daily',\n WEEKLY = 'weekly',\n MONTHLY = 'monthly',\n YEARLY = 'yearly',\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TimePolicyInterval } from './constants';\n\nexport function isIntervalForDayOfWeek(\n interval: string,\n) {\n return interval === TimePolicyInterval.WEEKLY ||\n interval === TimePolicyInterval.MONTHLY ||\n interval === TimePolicyInterval.YEARLY;\n}\n\nexport function isIntervalForDayOfMonth(\n interval: string,\n) {\n return interval === TimePolicyInterval.MONTHLY ||\n interval === TimePolicyInterval.YEARLY;\n}\n\nexport function isIntervalForDayOfYear(\n interval: string,\n) {\n return interval === TimePolicyInterval.YEARLY;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { TimePolicy } from './types';\nimport { TimePolicyInterval } from './constants';\n\nexport class TimePolicyValidator extends Container<TimePolicy> {\n override initialize() {\n super.initialize();\n\n this.mount('dayOfWeek', createValidator(\n z.number()\n .min(0).max(6)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('dayOfMonth', createValidator(\n z.number()\n .min(1)\n .max(31)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('dayOfYear', createValidator(\n z.number()\n .min(1)\n .max(365)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n\n this.mount('start', createValidator(\n z.date()\n .or(z.iso.datetime())\n .or(z.iso.time())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('end', createValidator(\n z.date()\n .or(z.iso.datetime())\n .or(z.iso.time())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n\n this.mount(\n 'interval',\n createValidator(\n z.enum(TimePolicyInterval)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.undefined())\n .or(z.null())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants';\nimport { isIntervalForDayOfMonth, isIntervalForDayOfWeek, isIntervalForDayOfYear } from './helpers';\nimport { TimePolicyValidator } from './validator';\n\nconst timeRegex = /^(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d)?$/;\n\nfunction normalizeDate(input: Date, dateRef?: Date) {\n const date = dateRef ? new Date(dateRef) : new Date();\n date.setHours(input.getHours(), input.getMinutes());\n\n return date;\n}\n\nfunction toDate(\n input: Date | string | number,\n dateRef?: Date,\n) : Date {\n if (typeof input === 'string') {\n if (timeRegex.test(input)) {\n const parts = input.split(':');\n\n const startHours = Number(parts[0]);\n const startMinutes = Number(parts[1]);\n const startSeconds = parts[2] !== undefined ? Number(parts[2]) : 0;\n\n if (\n Number.isFinite(startHours) &&\n Number.isFinite(startMinutes) &&\n Number.isFinite(startSeconds)\n ) {\n const date = dateRef ? new Date(dateRef) : new Date();\n date.setHours(startHours, startMinutes, startSeconds, 0);\n\n return date;\n }\n }\n\n return new Date(input);\n }\n\n if (typeof input === 'number') {\n return new Date(input);\n }\n\n return input;\n}\n\nexport class TimePolicyEvaluator implements IPolicyEvaluator {\n protected validator : TimePolicyValidator;\n\n constructor() {\n this.validator = new TimePolicyValidator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n let now : Date;\n\n if (ctx.data.has(BuiltInPolicyType.TIME)) {\n if (ctx.data.isValidated(BuiltInPolicyType.TIME)) {\n now = ctx.data.get<Date>(BuiltInPolicyType.TIME);\n } else {\n // todo: run validator on attributes (isObject ...)\n now = toDate(ctx.data.get(BuiltInPolicyType.TIME));\n\n ctx.data.set(BuiltInPolicyType.TIME, now);\n ctx.data.setValidated(BuiltInPolicyType.TIME);\n }\n } else {\n now = new Date();\n }\n\n if (policy.start) {\n const start = normalizeDate(toDate(policy.start, now), now);\n if (now < start) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (policy.end) {\n const end = normalizeDate(toDate(policy.end, now), now);\n if (now > end) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (policy.interval) {\n if (\n isIntervalForDayOfWeek(policy.interval) &&\n policy.dayOfWeek\n ) {\n if (now.getDay() !== policy.dayOfWeek) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (\n isIntervalForDayOfMonth(policy.interval) &&\n policy.dayOfMonth\n ) {\n if (now.getDate() !== policy.dayOfMonth) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (\n isIntervalForDayOfYear(policy.interval) &&\n policy.dayOfYear\n ) {\n const start = new Date(now.getFullYear(), 0, 0);\n const diff = (now.getTime() - start.getTime()) +\n ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);\n\n const oneDay = 1000 * 60 * 60 * 24;\n const dayOfYear = Math.floor(diff / oneDay);\n\n if (dayOfYear !== policy.dayOfYear) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n }\n\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyWithType } from '../types';\nimport type { BuiltInPolicyTypeMap } from './types';\n\nexport function definePolicyWithType<\n K extends keyof BuiltInPolicyTypeMap,\n D extends BuiltInPolicyTypeMap<any>[K],\n>(\n type: K,\n data: D,\n) : PolicyWithType<D, K> {\n return {\n ...data,\n type,\n };\n}\n","/*\n * Copyright (c) 2026-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n AttributeNamesPolicyEvaluator,\n AttributesPolicyEvaluator,\n BuiltInPolicyType,\n CompositePolicyEvaluator,\n DatePolicyEvaluator,\n IdentityPolicyEvaluator,\n PermissionBindingPolicyEvaluator,\n RealmMatchPolicyEvaluator,\n TimePolicyEvaluator,\n} from './built-in';\n\nexport const PolicyDefaultEvaluators = {\n [BuiltInPolicyType.COMPOSITE]: new CompositePolicyEvaluator(),\n [BuiltInPolicyType.ATTRIBUTES]: new AttributesPolicyEvaluator(),\n [BuiltInPolicyType.ATTRIBUTE_NAMES]: new AttributeNamesPolicyEvaluator(),\n [BuiltInPolicyType.DATE]: new DatePolicyEvaluator(),\n [BuiltInPolicyType.IDENTITY]: new IdentityPolicyEvaluator(),\n [BuiltInPolicyType.PERMISSION_BINDING]: new PermissionBindingPolicyEvaluator(),\n [BuiltInPolicyType.REALM_MATCH]: new RealmMatchPolicyEvaluator(),\n [BuiltInPolicyType.TIME]: new TimePolicyEvaluator(),\n} as const;\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuiltInPolicyType } from './built-in/constants';\nimport type { IdentityPolicyData } from './built-in/identity/types';\nimport { PolicyData } from './data';\n\n/**\n * Typed seed for a permission evaluation's {@link PolicyData} bag.\n *\n * The well-known context keys are value-typed, so construction is discoverable and a\n * wrong-typed value is a compile error. The trailing index signature keeps the bag **open** —\n * a third-party evaluator may supply its own key without any change to this published type\n * (the `access` evaluator set is deliberately extensible).\n */\nexport interface PolicyInput {\n [BuiltInPolicyType.IDENTITY]?: IdentityPolicyData;\n [BuiltInPolicyType.ATTRIBUTES]?: Record<string, any>;\n [BuiltInPolicyType.REALM_MATCH]?: string | string[] | null;\n [key: string]: any;\n}\n\n/**\n * Build a {@link PolicyData} bag from a typed {@link PolicyInput} seed. Well-known keys\n * (identity / attributes / realmMatch) are type-checked; unknown keys are accepted as-is.\n *\n * Prefer this over `new PolicyData({ ... })` at construction sites so the key vocabulary and\n * per-key value types live in one place.\n */\nexport function definePolicyData(input: PolicyInput = {}): PolicyData {\n return new PolicyData(input);\n}\n","/*\n * Copyright (c) 2021-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { or } from '@rapiq/core';\nimport { ErrorCode } from '@authup/errors';\nimport type { Issue } from '@ebec/core';\nimport { defineIssueItem } from '@ebec/core';\nimport { DecisionStrategy } from '@authup/kit';\nimport type { BasePolicy, CompositePolicy, IPolicyEngine } from '../../policy';\nimport {\n BuiltInPolicyType,\n PolicyData,\n PolicyDefaultEvaluators,\n PolicyEngine,\n definePolicyEvaluationContext,\n definePolicyIssueGroup,\n} from '../../policy';\nimport { PermissionError } from '../error';\nimport type { IPermissionProvider } from '../provider';\n\nimport type { PermissionPolicyBindingAggregated } from '../types.ts';\nimport type {\n IPermissionEvaluator,\n PermissionCompileContext,\n PermissionCompileResult,\n PermissionEvaluationContext,\n PermissionEvaluatorOptions,\n} from './types.ts';\n\nexport class PermissionEvaluator implements IPermissionEvaluator {\n protected provider : IPermissionProvider;\n\n protected policyEngine : IPolicyEngine;\n\n protected clientId?: string | null;\n\n protected realmId?: string | null;\n\n // ----------------------------------------------\n\n constructor(options: PermissionEvaluatorOptions) {\n this.provider = options.provider;\n\n this.clientId = options.clientId || null;\n this.realmId = options.realmId || null;\n\n if (options.policyEngine) {\n this.policyEngine = options.policyEngine;\n } else {\n this.policyEngine = new PolicyEngine(PolicyDefaultEvaluators);\n }\n }\n\n // ----------------------------------------------\n\n protected async findOne(\n input: string,\n overrides: {\n realmId?: string | null,\n clientId?: string | null\n } = {},\n ) : Promise<PermissionPolicyBindingAggregated | null> {\n return this.provider.findOne({\n name: input,\n clientId: overrides.clientId ?? this.clientId,\n realmId: overrides.realmId ?? this.realmId,\n });\n }\n\n // ----------------------------------------------\n\n async evaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n if (!Array.isArray(ctx.name)) {\n await this.evaluate({\n ...ctx,\n name: [ctx.name],\n });\n return;\n }\n\n const { options = {} } = ctx;\n\n const decisionStrategy = options.decisionStrategy ??\n DecisionStrategy.UNANIMOUS;\n\n const issues : Issue[] = [];\n\n let count = 0;\n\n const dataBase = ctx.data || new PolicyData();\n\n for (const name of ctx.name) {\n const binding = await this.findOne(name, {\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n });\n if (!binding) {\n issues.push(defineIssueItem({\n code: ErrorCode.PERMISSION_NOT_FOUND,\n message: `The ${name} permission could not be resolved`,\n path: [name],\n }));\n\n if (decisionStrategy === DecisionStrategy.UNANIMOUS) {\n throw PermissionError.evaluationFailed(ctx.name, issues);\n }\n\n continue;\n }\n\n // The actor's grants for this permission form a disjunction: a single policy-free\n // grant is unrestricted, otherwise the permission passes iff ANY grant's policy\n // passes (AFFIRMATIVE). Each grant's policy already carries its own decisionStrategy\n // (a composite for multi-policy Layer-1 bindings, the raw policy for single).\n const grantPolicies = binding.grants\n .map((grant) => grant.policy)\n .filter((grantPolicy): grantPolicy is BasePolicy => !!grantPolicy);\n\n if (grantPolicies.length < binding.grants.length) {\n // some grant is policy-free => unrestricted\n if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return;\n }\n\n count++;\n\n continue;\n }\n\n const data = dataBase.clone();\n data.set(BuiltInPolicyType.PERMISSION_BINDING, binding);\n\n const compositePolicy : CompositePolicy = {\n type: BuiltInPolicyType.COMPOSITE,\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n children: grantPolicies,\n };\n\n const evaluationResult = await this.policyEngine.evaluate(\n compositePolicy,\n definePolicyEvaluationContext({\n include: options.policiesIncluded,\n exclude: options.policiesExcluded,\n data,\n }),\n );\n\n // A pending evaluation (missing data keys) is settled by the caller's\n // phase: the full evaluate denies (fail-closed default), the pre-gate\n // permits — the enriched-bag evaluate is the backstop.\n const passed = evaluationResult.success || (\n options.pendingPolicies === 'permit' &&\n !!evaluationResult.pending\n );\n\n if (passed) {\n if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return;\n }\n\n count++;\n } else {\n issues.push(definePolicyIssueGroup({\n code: ErrorCode.PERMISSION_EVALUATION_FAILED,\n issues: evaluationResult.issues || [],\n message: `The ${binding.permission.name} permissions policy evaluation failed`,\n path: [binding.permission.name],\n }));\n\n if (decisionStrategy === DecisionStrategy.UNANIMOUS) {\n throw PermissionError.evaluationFailed(binding.permission.name, issues);\n }\n\n count--;\n }\n }\n\n if (count > 0) {\n return;\n }\n\n if (issues.length === 0) {\n throw PermissionError.deniedAll(ctx.name);\n } else {\n throw PermissionError.evaluationFailed(ctx.name, issues);\n }\n }\n\n async evaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return this.evaluate({\n ...ctx,\n options: {\n ...(ctx.options || {}),\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n },\n });\n }\n\n // ----------------------------------------------\n\n async preEvaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n // The pre-gate is DERIVED from data availability (issue #3286): policies whose\n // required data keys are absent from the bag stay pending and are permitted —\n // only a tree that settles false with the current bag denies. This replaces the\n // former hand-maintained type exclusion list (ATTRIBUTES / ATTRIBUTE_NAMES /\n // REALM_MATCH), whose mask-to-true encoding broke under `invert`.\n return this.evaluate({\n ...ctx,\n options: {\n ...(ctx.options || {}),\n pendingPolicies: 'permit',\n },\n });\n }\n\n async preEvaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return this.preEvaluate({\n ...ctx,\n options: {\n ...(ctx.options || {}),\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n },\n });\n }\n\n // ----------------------------------------------\n\n /**\n * Compile the permission's policy trees against the knowns bag into a\n * {@link PermissionCompileResult} — the query-build counterpart of\n * {@link evaluate} (issue #3286 phase 3). Runs the SAME evaluation walk with\n * `withConditions` enabled: policies that settle with the knowns settle here,\n * pending subtrees contribute their exact condition form. Multiple names are\n * a disjunction (any-of), so a single non-expressible name degrades the whole\n * compilation to `post` — pushing only some disjuncts would wrongly exclude\n * rows another name would admit.\n */\n async compile(ctx: PermissionCompileContext) : Promise<PermissionCompileResult> {\n const names = Array.isArray(ctx.name) ? ctx.name : [ctx.name];\n\n const dataBase = ctx.data || new PolicyData();\n\n const conditions : ICondition[] = [];\n let post = false;\n\n for (const name of names) {\n const binding = await this.findOne(name, {\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n });\n if (!binding) {\n // unresolvable permission — a settled-false disjunct, drops out\n continue;\n }\n\n const grantPolicies = binding.grants\n .map((grant) => grant.policy)\n .filter((grantPolicy): grantPolicy is BasePolicy => !!grantPolicy);\n\n if (grantPolicies.length < binding.grants.length) {\n // some grant is policy-free => unrestricted\n return { verdict: 'allow' };\n }\n\n const data = dataBase.clone();\n data.set(BuiltInPolicyType.PERMISSION_BINDING, binding);\n\n const compositePolicy : CompositePolicy = {\n type: BuiltInPolicyType.COMPOSITE,\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n children: grantPolicies,\n };\n\n const evaluationResult = await this.policyEngine.evaluate(\n compositePolicy,\n definePolicyEvaluationContext({\n data,\n withConditions: true,\n realmAttributeName: ctx.realmAttributeName,\n }),\n );\n\n if (evaluationResult.success) {\n return { verdict: 'allow' };\n }\n\n if (evaluationResult.pending) {\n if (evaluationResult.condition) {\n conditions.push(evaluationResult.condition);\n } else {\n post = true;\n }\n }\n // settled false — the disjunct drops out\n }\n\n if (post) {\n return { verdict: 'post' };\n }\n\n if (conditions.length === 0) {\n return { verdict: 'deny' };\n }\n\n if (conditions.length === 1) {\n const [condition] = conditions;\n return { verdict: 'conditional', condition: condition! };\n }\n\n return { verdict: 'conditional', condition: or(...conditions) };\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { AuthupError, markInstanceof } from '@authup/errors';\n\nexport const AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE = Symbol.for('@authup/access/AuthorizationCatalogStaleError');\n\n/**\n * A grant references a definition or a policy the supplied catalog does not\n * carry: the caller's cached catalog predates the definition or the junction\n * row and must be refetched. A definition the catalog carries with\n * `policies: null`, and one whose tree this copy cannot project, are not\n * stale but unevaluable, and a grant of either is dropped.\n *\n * Recognize it with `isAuthorizationCatalogStaleError`, never `instanceof`:\n * this package is a plain caret dependency of several workspaces, so a\n * consumer tree may resolve two copies of it and turn the one recoverable\n * state into an unrecoverable one.\n */\nexport class AuthorizationCatalogStaleError extends AuthupError {\n constructor(message: string) {\n super({ message });\n\n this.name = 'AuthorizationCatalogStaleError';\n markInstanceof(this, AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { matchesInstanceof } from '@authup/errors';\nimport type { AuthorizationCatalogStaleError } from './error';\nimport { AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE } from './error';\n\n/**\n * Marker-only: the error carries no code of its own, and it never crosses a\n * wire boundary, so there is no shape to fall back to.\n */\nexport function isAuthorizationCatalogStaleError(input: unknown) : input is AuthorizationCatalogStaleError {\n return matchesInstanceof(input, AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE);\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueItem } from '@ebec/core';\nimport { DecisionStrategy } from '@authup/kit';\nimport { createValidator } from '@validup/zod';\nimport { Container, ValidupError } from 'validup';\nimport { z } from 'zod';\nimport { RealmScope } from '../realm-scope';\nimport type {\n AuthorizationCatalog,\n AuthorizationEvaluatorInput,\n AuthorizationGrant,\n} from './types';\n\nconst id = z.string().min(1);\nconst namespaceId = id.nullable();\n\n/**\n * A policy node as it travels. Deliberately LOOSE: every key beyond `type` is\n * that type's own configuration, and `projectAuthorizationPolicy` is what\n * validates it, by running the type's own validator. Mounting a node in a\n * validup container would strip every key the container does not mount, and\n * the whole configuration would go with it.\n */\nexport const authorizationPolicySchema = z.looseObject({ type: z.string().min(1) });\n\n/**\n * One permission definition. `policies` carries the ids of its\n * definition-layer trees, or `null` when the server could not project one.\n */\nexport const authorizationDefinitionSchema = z.object({\n name: z.string().min(1),\n realm_id: namespaceId,\n client_id: namespaceId,\n decision_strategy: z.enum(DecisionStrategy).nullable(),\n policies: z.array(id).nullable(),\n});\n\nexport const authorizationCatalogSchema = z.object({\n policies: z.record(id, authorizationPolicySchema),\n permissions: z.array(authorizationDefinitionSchema),\n});\n\n/**\n * One grant of the identity, as the introspection endpoints report it.\n * Whether a grant's policy ids are declared is checked against the catalog\n * the consumer holds, since the two travel separately.\n */\nexport const authorizationGrantSchema = z.object({\n name: z.string().min(1),\n realm_id: namespaceId.optional(),\n client_id: namespaceId.optional(),\n realm_scope: z.enum(RealmScope).nullish(),\n policies: z.array(id).nullish(),\n});\n\nexport const authorizationIdentitySchema = z.object({\n id: z.string().min(1),\n type: z.enum(['user', 'client']),\n realmId: z.string().nullish(),\n realmName: z.string().nullish(),\n clientId: z.string().nullish(),\n});\n\n/**\n * The whole input `createAuthorizationEvaluator` takes: the catalog\n * `GET /authorization` serves, the grants an introspection reports and the\n * identity it names. A validup container over zod mounts, the shape every\n * validator in this package uses, so a consumer can reuse or override one\n * member's rules instead of restating the document.\n */\nexport class AuthorizationEvaluatorInputValidator extends Container<AuthorizationEvaluatorInput> {\n override initialize() {\n super.initialize();\n\n this.mount('catalog', createValidator(authorizationCatalogSchema));\n this.mount('grants', createValidator(z.array(authorizationGrantSchema).optional()));\n this.mount('identity', createValidator(authorizationIdentitySchema.optional()));\n }\n}\n\nconst validator = new AuthorizationEvaluatorInputValidator();\n\nexport type AuthorizationEvaluatorInputParsed = {\n catalog: AuthorizationCatalog,\n grants: AuthorizationGrant[],\n identity: AuthorizationEvaluatorInput['identity'],\n};\n\n/**\n * Validate the evaluator's input, plus the two rules per-key validators\n * cannot express.\n *\n * Every id a definition names must be a key of `policies`: a dangling id\n * resolves to `undefined`, which reads as \"this layer carries no policy\", so\n * a catalog that merely omitted a tree would grant unrestricted access rather\n * than fail. The lookup is own-property only, so an id such as `constructor`\n * cannot be answered by a member of `Object.prototype`.\n *\n * And the identity and its grants travel together: grants without an identity\n * belong to nobody, while an identity without a grant list is the shape an\n * INACTIVE introspection produces (`permissions` is absent unless the\n * credential is active), which read as \"holds nothing\" would authorize every\n * definition that carries no binding check. An identity holding no grant says\n * so with an empty array.\n */\nexport async function parseAuthorizationEvaluatorInput(\n input: AuthorizationEvaluatorInput,\n) : Promise<AuthorizationEvaluatorInputParsed> {\n const identityGiven = typeof input.identity !== 'undefined';\n const grantsGiven = typeof input.grants !== 'undefined';\n if (!identityGiven && grantsGiven) {\n throw new ValidupError([defineIssueItem({\n message: 'Grants require the identity they belong to.',\n path: ['identity'],\n })]);\n }\n\n if (identityGiven && !grantsGiven) {\n throw new ValidupError([defineIssueItem({\n message: 'An identity requires its grant list; pass an empty array for an identity holding none.',\n path: ['grants'],\n })]);\n }\n\n // Detach: a later mutation of a cached HTTP response cannot widen grants\n // after validation (attribute queries carry arbitrary nested data).\n //\n // The cast is the container's boundary: its generic describes the INPUT,\n // whose wire members are `unknown` by design, while what a run returns is\n // what the mounted schemas accepted (the `parseThemeManifest` idiom).\n const {\n catalog, \n grants, \n identity, \n } = await validator.run(\n structuredClone(input) as Record<string, any>,\n ) as {\n catalog: AuthorizationCatalog,\n grants?: AuthorizationGrant[],\n identity?: AuthorizationEvaluatorInput['identity'],\n };\n\n for (const [i, definition] of catalog.permissions.entries()) {\n for (const [j, policyId] of (definition.policies ?? []).entries()) {\n if (Object.hasOwn(catalog.policies, policyId)) {\n continue;\n }\n\n throw new ValidupError([defineIssueItem({\n message: `The policy ${policyId} is not declared by the catalog.`,\n path: ['catalog', 'permissions', i, 'policies', j],\n })]);\n }\n }\n\n return {\n catalog,\n grants: grants ?? [],\n identity,\n };\n}\n\n/**\n * One verdict: the permission namespace and the requested realms it holds in.\n * A realm value is a realm key the caller itself supplied, or `null` for the\n * global rows, so nothing here is resolved or looked up.\n */\nexport const authorizationCheckPermissionSchema = z.object({\n name: z.string().min(1),\n realms: z.array(z.string().min(1).nullable()).min(1),\n});\n\nexport const authorizationCheckPermissionsSchema = z.array(authorizationCheckPermissionSchema);\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueItem } from '@ebec/core';\nimport { createValidator } from '@validup/zod';\nimport { Container, ValidupError } from 'validup';\nimport { authorizationCheckPermissionsSchema, authorizationIdentitySchema } from './schema';\nimport type { AuthorizationCheckEvaluatorInput, AuthorizationCheckPermissions } from './types';\n\n/**\n * The whole input `createAuthorizationCheckEvaluator` takes: the answer\n * `POST /authorization/check` served and the identity it belongs to. Same\n * validup-over-zod shape as the catalog's input, so a consumer can override\n * one member's rules instead of restating the answer.\n */\nexport class AuthorizationCheckEvaluatorInputValidator extends Container<AuthorizationCheckEvaluatorInput> {\n override initialize() {\n super.initialize();\n\n this.mount('permissions', createValidator(authorizationCheckPermissionsSchema));\n this.mount('identity', createValidator(authorizationIdentitySchema.optional()));\n }\n}\n\nconst checkValidator = new AuthorizationCheckEvaluatorInputValidator();\n\nexport type AuthorizationCheckEvaluatorInputParsed = {\n permissions: AuthorizationCheckPermissions,\n identity: AuthorizationCheckEvaluatorInput['identity'],\n};\n\n/**\n * Validate the check evaluator's input, plus the one rule a per-key validator\n * cannot express: a permission namespace appears at most once. Two entries for\n * one name would make the answer depend on which the consumer looked up first,\n * and the server emits one entry per name by construction.\n */\nexport async function parseAuthorizationCheckEvaluatorInput(\n input: AuthorizationCheckEvaluatorInput,\n) : Promise<AuthorizationCheckEvaluatorInputParsed> {\n // Detach for the reason the catalog's input is detached: a later mutation\n // of a cached HTTP response cannot widen verdicts after validation.\n const {\n permissions,\n identity,\n } = await checkValidator.run(\n structuredClone(input) as Record<string, any>,\n ) as {\n permissions: AuthorizationCheckPermissions,\n identity?: AuthorizationCheckEvaluatorInput['identity'],\n };\n\n const seen = new Set<string>();\n for (const [i, permission] of permissions.entries()) {\n if (seen.has(permission.name)) {\n throw new ValidupError([defineIssueItem({\n message: `The permission ${permission.name} is answered more than once.`,\n path: ['permissions', i, 'name'],\n })]);\n }\n\n seen.add(permission.name);\n }\n\n return { permissions, identity };\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * The node a policy tree travels as when the server withholds it, because the\n * caller's realm reach does not cover the row it was read from.\n *\n * It is deliberately a type no consumer can project: `projectAuthorizationPolicy`\n * refuses it, which is already the state a definition referencing it denies\n * through and a grant naming it is dropped through, so withholding a body needs\n * no rule of its own on the consumer side. That is a contract between the two\n * halves rather than a server detail, which is why it is declared HERE, next to\n * the projection that has to keep refusing it, and pinned by this package's own\n * test.\n */\nexport const AUTHORIZATION_POLICY_WITHHELD_TYPE = 'withheld';\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { prefixIssuePath } from '@ebec/core';\nimport { createValidator } from '@validup/zod';\nimport { Container, ValidupError, isValidupError } from 'validup';\nimport { z } from 'zod';\nimport {\n AttributeNamesPolicyValidator,\n AttributesPolicyValidator,\n BuiltInPolicyType,\n CompositePolicyValidator,\n DatePolicyValidator,\n IdentityPolicyValidator,\n PermissionBindingPolicyValidator,\n RealmMatchPolicyValidator,\n TimePolicyValidator,\n} from '../../policy';\nimport type { AuthorizationPolicy } from './types';\n\ntype AuthorizationPolicyHead = {\n type: BuiltInPolicyType,\n children?: unknown[],\n};\n\n/**\n * The two keys a node carries whatever its type is. Deliberately NOT the whole\n * node: every other key is that type's own configuration, which the type's own\n * validator reads, and a container strips every key it does not mount.\n */\nclass AuthorizationPolicyHeadValidator extends Container<AuthorizationPolicyHead> {\n override initialize() {\n super.initialize();\n\n this.mount('type', createValidator(z.enum(BuiltInPolicyType)));\n this.mount('children', createValidator(z.array(z.unknown()).optional()));\n }\n}\n\nfunction createValidators() : Record<BuiltInPolicyType, Container<Record<string, any>>> {\n return {\n [BuiltInPolicyType.ATTRIBUTES]: new AttributesPolicyValidator(),\n [BuiltInPolicyType.ATTRIBUTE_NAMES]: new AttributeNamesPolicyValidator(),\n [BuiltInPolicyType.COMPOSITE]: new CompositePolicyValidator(),\n [BuiltInPolicyType.DATE]: new DatePolicyValidator(),\n [BuiltInPolicyType.TIME]: new TimePolicyValidator(),\n [BuiltInPolicyType.IDENTITY]: new IdentityPolicyValidator(),\n [BuiltInPolicyType.PERMISSION_BINDING]: new PermissionBindingPolicyValidator(),\n [BuiltInPolicyType.REALM_MATCH]: new RealmMatchPolicyValidator(),\n };\n}\n\n/**\n * The one definition of what a policy looks like on the wire, used by the server\n * to build a document and by the consumer to validate one. A node is the OUTPUT\n * of its type's validator (validup strips every unmounted key, so entity columns\n * such as `id`, `name`, `builtIn` or `createdAt` never travel), plus its type\n * and, for a composite, its projected children.\n *\n * Every refusal is a `ValidupError`, the node's head and the type's own\n * validator alike, and a child's issues are rebased onto the position it sits\n * at, so one message names the node in the tree that is wrong.\n */\nexport async function projectAuthorizationPolicy(input: unknown) : Promise<AuthorizationPolicy> {\n const headValidator = new AuthorizationPolicyHeadValidator();\n const validators = createValidators();\n\n const project = async (value: unknown) : Promise<AuthorizationPolicy> => {\n const head = await headValidator.run(value as Record<string, any>);\n const validated = await validators[head.type].run(value as Record<string, any>) as Record<string, unknown>;\n\n const output : AuthorizationPolicy = { ...validated, type: head.type };\n for (const key of Object.keys(output)) {\n if (typeof output[key] === 'undefined') {\n delete output[key];\n }\n }\n\n if (head.type === BuiltInPolicyType.COMPOSITE) {\n output.children = await Promise.all(\n (head.children ?? []).map((child, index) => projectChild(child, index)),\n );\n } else {\n delete output.children;\n }\n\n return output;\n };\n\n const projectChild = async (child: unknown, index: number) : Promise<AuthorizationPolicy> => {\n try {\n return await project(child);\n } catch (e) {\n if (isValidupError(e)) {\n throw new ValidupError(e.issues.map((issue) => prefixIssuePath(issue, ['children', index])));\n }\n\n throw e;\n }\n };\n\n return project(input);\n}\n\n/**\n * Whether a projected tree evaluates the permission binding at any depth. A\n * grant policy carrying one would re-enter its own permission's grants, so\n * `createAuthorizationEvaluator` drops the grant that names it and evaluates\n * the permission from the rest. Its one caller is that consumer: the tree is\n * legal in a definition, where the binding check is what reach is enforced\n * by, so the producer carries it and only the grant side is refused.\n */\nexport function containsBindingCheck(policy: AuthorizationPolicy) : boolean {\n if (policy.type === BuiltInPolicyType.PERMISSION_BINDING) {\n return true;\n }\n\n return (policy.children ?? []).some((child) => containsBindingCheck(child));\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { type Issue, defineIssueItem, prefixIssuePath } from '@ebec/core';\nimport { InternalError } from '@authup/errors';\nimport { buildIssuesForZodError } from '@validup/zod';\nimport { ValidupError } from 'validup';\nimport { z } from 'zod';\nimport type { BasePolicy } from '../../policy';\nimport {\n BuiltInPolicyType,\n IdentityPermissionBindingPolicyEvaluator,\n PolicyData,\n PolicyDefaultEvaluators,\n PolicyEngine,\n} from '../../policy';\nimport type {\n IPermissionEvaluator,\n PermissionCompileContext,\n PermissionCompileResult,\n PermissionEvaluationContext,\n} from '../evaluator';\nimport { PermissionEvaluator } from '../evaluator';\nimport { PermissionError } from '../error';\nimport { buildPermissionKey } from '../helpers';\nimport { PermissionMemoryProvider } from '../provider';\nimport { normalizeRealmScope } from '../realm-scope';\nimport type { BasePermission, PermissionPolicyBinding } from '../types';\nimport { AuthorizationCatalogStaleError } from './error';\nimport { containsBindingCheck, projectAuthorizationPolicy } from './policy';\nimport { parseAuthorizationCheckEvaluatorInput } from './check-schema';\nimport { parseAuthorizationEvaluatorInput } from './schema';\nimport type {\n AuthorizationCheckEvaluatorInput,\n AuthorizationEvaluatorInput,\n AuthorizationPolicy,\n} from './types';\n\nconst realmMatchSchema = z.union([z.string().min(1), z.array(z.string().min(1)).min(1), z.null()]);\n\n/**\n * Every refusal of the DOCUMENT is a `ValidupError` carrying the path of the\n * member at fault, the shape `parseAuthorizationEvaluatorInput` raises and the\n * one a consumer can render. A bare `Error` carries neither a code nor a path,\n * so nothing downstream can normalize it.\n */\nfunction refuseDocument(message: string, path: PropertyKey[]) : never {\n throw new ValidupError([defineIssueItem({ message, path })]);\n}\n\nfunction refuseDocumentWithIssues(issues: Issue[]) : never {\n throw new ValidupError(issues);\n}\n\nfunction toPolicy(tree: AuthorizationPolicy) : BasePolicy {\n const {\n invert,\n children,\n ...policy\n } = tree;\n\n return {\n ...policy,\n ...(typeof invert === 'boolean' ? { invert } : {}),\n ...(children ? { children: children.map((child) => toPolicy(child)) } : {}),\n };\n}\n\n/**\n * Build a resource-server (or console) evaluator from the catalog\n * `GET /authorization` serves, the identity's grants as the introspection\n * endpoints report them, and the identity itself. Rejects legacy, incomplete\n * and unsupported input. A grant referencing a definition or a policy the\n * catalog lacks throws `AuthorizationCatalogStaleError`, the signal to\n * refetch the catalog: the grants come from a fresh introspection while the\n * catalog may predate the definition or the junction row. A definition the\n * server could not project travels with `policies: null` instead of being\n * left out, so a grant of it is dropped rather than reported stale: the\n * definition layer cannot be evaluated here, a refetch changes nothing, and\n * the permission denies until the policy is fixed.\n *\n * A tree THIS copy cannot project is the same condition read from the other\n * side, and it is per tree: a policy type newer than this package (the\n * built-in type enum is closed while the column is a free string) or a\n * configuration its validator refuses denies the definitions that reference\n * it, exactly as `policies: null` does, and drops a grant that names it,\n * exactly as a binding check does. One such tree never takes the evaluator\n * down for the permissions that do not use it. A malformed catalog still\n * throws: a duplicate permission namespace is not a data condition.\n *\n * Both the identity and the grants are optional. Without an identity no grant\n * is bound and any IDENTITY key the caller supplied is REMOVED, so the\n * binding evaluator answers with missing data exactly as the server does for\n * an anonymous request, only a definition whose policies need no identity can\n * pass, and a caller can never inject an identity the document did not prove.\n * Grants without the identity they belong to are refused.\n *\n * The REALM_MATCH data key follows the server's own three-way rule: a\n * resource that carries a realm passes it (null for a global row, which\n * `own` denies), a resource with no realm dimension passes nothing and reach\n * neutral-passes. `preEvaluate` / `preEvaluateOneOf` are the pre-gate and\n * enforce reach only when that key is present. `compile` returns the\n * allow/deny/conditional/post contract; a `post` collection query must be\n * rejected or evaluated over every candidate before paging. The supplied\n * identity is authoritative; `options.decisionStrategy` is forwarded and the\n * policy include, exclude and pending options are refused.\n */\nexport async function createAuthorizationEvaluator(input: AuthorizationEvaluatorInput) : Promise<IPermissionEvaluator> {\n const {\n catalog, \n grants, \n identity, \n } = await parseAuthorizationEvaluatorInput(input);\n\n const trees = new Map<string, AuthorizationPolicy>();\n const unevaluable = new Set<string>();\n for (const [id, raw] of Object.entries(catalog.policies)) {\n try {\n trees.set(id, await projectAuthorizationPolicy(raw));\n } catch {\n unevaluable.add(id);\n }\n }\n\n const definitions : PermissionPolicyBinding[] = [];\n const permissions = new Map<string, BasePermission | null>();\n for (const [index, entry] of catalog.permissions.entries()) {\n const permission : BasePermission = {\n name: entry.name,\n realmId: entry.realm_id,\n clientId: entry.client_id,\n decisionStrategy: entry.decision_strategy ?? undefined,\n };\n const key = buildPermissionKey(permission);\n if (permissions.has(key)) {\n refuseDocument(\n `The catalog defines the permission ${key} more than once.`,\n ['catalog', 'permissions', index],\n );\n }\n if (entry.policies === null || entry.policies.some((id) => unevaluable.has(id))) {\n permissions.set(key, null);\n continue;\n }\n permissions.set(key, permission);\n\n const policies : BasePolicy[] = [];\n for (const [i, id] of entry.policies.entries()) {\n const tree = trees.get(id);\n if (!tree) {\n refuseDocument(\n `The catalog does not declare the policy ${id}.`,\n ['catalog', 'permissions', index, 'policies', i],\n );\n }\n policies.push(toPolicy(tree));\n }\n\n definitions.push({ permission, policies: policies.length > 0 ? policies : undefined });\n }\n\n const bindings : PermissionPolicyBinding[] = [];\n for (const grant of grants) {\n const key = buildPermissionKey({\n name: grant.name,\n realmId: grant.realm_id ?? null,\n clientId: grant.client_id ?? null,\n });\n const permission = permissions.get(key);\n if (typeof permission === 'undefined') {\n throw new AuthorizationCatalogStaleError(`The catalog does not define the permission ${key}.`);\n }\n if (permission === null) {\n continue;\n }\n\n const policies : BasePolicy[] = [];\n let evaluable = true;\n for (const id of grant.policies ?? []) {\n if (unevaluable.has(id)) {\n evaluable = false;\n break;\n }\n const tree = trees.get(id);\n if (!tree) {\n throw new AuthorizationCatalogStaleError(`The catalog does not declare the policy ${id}.`);\n }\n if (containsBindingCheck(tree)) {\n evaluable = false;\n break;\n }\n policies.push(toPolicy(tree));\n }\n if (!evaluable) {\n continue;\n }\n\n bindings.push({\n permission,\n realmScope: normalizeRealmScope(grant.realm_scope),\n policies: policies.length > 0 ? policies : undefined,\n });\n }\n\n const engine = new PolicyEngine(PolicyDefaultEvaluators);\n engine.registerEvaluator(\n BuiltInPolicyType.PERMISSION_BINDING,\n new IdentityPermissionBindingPolicyEvaluator({ getFor: async () => bindings }),\n );\n const evaluator = new PermissionEvaluator({\n provider: new PermissionMemoryProvider(definitions),\n policyEngine: engine,\n });\n\n const withIdentity = (input?: PolicyData) : PolicyData => {\n const data = input?.clone() ?? new PolicyData();\n if (!identity) {\n // symmetrical with the branch below, which overwrites the key:\n // the document proved no identity, so the caller may not supply\n // one either\n data.delete(BuiltInPolicyType.IDENTITY);\n\n return data;\n }\n\n data.set(BuiltInPolicyType.IDENTITY, {\n id: identity.id,\n type: identity.type,\n realmId: identity.realmId ?? undefined,\n realmName: identity.realmName ?? undefined,\n clientId: identity.clientId ?? null,\n });\n\n return data;\n };\n\n const forGate = (ctx: PermissionEvaluationContext) : PermissionEvaluationContext => {\n if (\n ctx.options?.policiesIncluded ||\n ctx.options?.policiesExcluded ||\n ctx.options?.pendingPolicies\n ) {\n throw new InternalError('The authorization evaluator does not accept policy bypass options.');\n }\n\n return {\n name: ctx.name,\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n data: withIdentity(ctx.data),\n ...(ctx.options?.decisionStrategy ?\n { options: { decisionStrategy: ctx.options.decisionStrategy } } :\n {}),\n };\n };\n\n const forResource = (ctx: PermissionEvaluationContext) : PermissionEvaluationContext => {\n const next = forGate(ctx);\n if (next.data!.has(BuiltInPolicyType.REALM_MATCH)) {\n const value = next.data!.get(BuiltInPolicyType.REALM_MATCH);\n const outcome = realmMatchSchema.safeParse(value);\n if (!outcome.success) {\n refuseDocumentWithIssues(\n buildIssuesForZodError(outcome.error, value)\n .map((issue) => prefixIssuePath(issue, ['data', BuiltInPolicyType.REALM_MATCH])),\n );\n }\n }\n\n return next;\n };\n\n return {\n async evaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.evaluate(forResource(ctx));\n },\n async evaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.evaluateOneOf(forResource(ctx));\n },\n async preEvaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.preEvaluate(forGate(ctx));\n },\n async preEvaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.preEvaluateOneOf(forGate(ctx));\n },\n async compile(ctx: PermissionCompileContext) : Promise<PermissionCompileResult> {\n if (ctx.data?.has(BuiltInPolicyType.REALM_MATCH) || ctx.data?.has(BuiltInPolicyType.ATTRIBUTES)) {\n throw new InternalError('Compile authorization without resource realm or row attributes.');\n }\n\n return evaluator.compile({\n name: ctx.name,\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n data: withIdentity(ctx.data),\n realmAttributeName: ctx.realmAttributeName,\n });\n },\n };\n}\n\n/**\n * An `IPermissionEvaluator` over the answer `POST /authorization/check`\n * served: the caller's own verdicts, paired with the realms they hold in.\n *\n * It is what a PUBLIC client gets where the catalog is out of reach. A public\n * client holds no secret, so it can obtain no `client_credentials` token and\n * has no credential of its own for the catalog's gate to be satisfied by;\n * publishing every policy predicate to it instead would be the wrong trade.\n * The verdicts are computed by the server from the same grants and the same\n * evaluators a request runs, so this is authoritative where the name-only\n * fallback it replaces is merely coarse.\n *\n * Two properties follow from the answer being a pre-gate:\n *\n * It is an UPPER BOUND, so `evaluate` and `evaluateOneOf` answer exactly what\n * the pre-gate pair answers. A check that depends on a resource row belongs to\n * whoever holds the row, and the server decides it there; answering such a\n * check here would mean inventing a verdict. That is the same bound the\n * name-only fallback already had, so nothing that gates on it loosens.\n *\n * And a resource realm is matched against what the REQUEST asked about: a\n * `realmMatch` naming a realm the request never carried is in no entry's list\n * and therefore denies. That is fail-closed by construction rather than by a\n * rule, and it is why a caller must ask about the realms its UI will ask\n * about.\n */\nexport async function createAuthorizationCheckEvaluator(\n input: AuthorizationCheckEvaluatorInput,\n) : Promise<IPermissionEvaluator> {\n const { permissions, identity } = await parseAuthorizationCheckEvaluatorInput(input);\n\n const verdicts = new Map<string, Set<string | null>>();\n for (const permission of permissions) {\n verdicts.set(permission.name, new Set<string | null>(permission.realms));\n }\n\n // The server resolves `own` / `ownOrNull` to the identity's realm ID, while\n // a caller may name its own realm either way: the reach comparison the\n // server makes accepts the id or the name, so the consumer has to as well,\n // or a check carrying the realm NAME would deny against an answer keyed by\n // the id.\n const ownKeys = new Set<string>();\n if (identity?.realmId) {\n ownKeys.add(identity.realmId);\n }\n if (identity?.realmName) {\n ownKeys.add(identity.realmName);\n }\n\n const matchesRealm = (realms: Set<string | null>, value: string | null) : boolean => {\n if (realms.has(value)) {\n return true;\n }\n\n if (value === null || !ownKeys.has(value)) {\n return false;\n }\n\n for (const key of ownKeys) {\n if (realms.has(key)) {\n return true;\n }\n }\n\n return false;\n };\n\n const holds = (name: string, data?: PolicyData) : boolean => {\n const realms = verdicts.get(name);\n if (!realms) {\n return false;\n }\n\n if (!data || !data.has(BuiltInPolicyType.REALM_MATCH)) {\n // No resource realm named, so the question is whether the\n // permission is held at all, which it is: an entry only exists\n // when at least one requested realm passed.\n return true;\n }\n\n const value = data.get<string | string[] | null>(BuiltInPolicyType.REALM_MATCH);\n if (Array.isArray(value)) {\n // A resource spanning several realms needs every one of them,\n // fail-closed on the empty set, the rule `realmScopeMatches` applies.\n if (value.length === 0) {\n return false;\n }\n\n return value.every((entry) => matchesRealm(realms, entry ?? null));\n }\n\n return matchesRealm(realms, value ?? null);\n };\n\n const names = (ctx: PermissionEvaluationContext) : string[] => (Array.isArray(ctx.name) ?\n ctx.name :\n [ctx.name]);\n\n const assertEvery = async (ctx: PermissionEvaluationContext) : Promise<void> => {\n for (const name of names(ctx)) {\n if (!holds(name, ctx.data)) {\n throw PermissionError.evaluationFailed(ctx.name);\n }\n }\n };\n\n const assertSome = async (ctx: PermissionEvaluationContext) : Promise<void> => {\n const list = names(ctx);\n for (const name of list) {\n if (holds(name, ctx.data)) {\n return;\n }\n }\n\n throw PermissionError.evaluationFailed(ctx.name);\n };\n\n return {\n evaluate: assertEvery,\n evaluateOneOf: assertSome,\n preEvaluate: assertEvery,\n preEvaluateOneOf: assertSome,\n async compile(ctx: PermissionCompileContext) : Promise<PermissionCompileResult> {\n // A verdict set carries no row predicate, so nothing here can be\n // lowered into a query. `deny` is still sound and worth answering:\n // a name held in no requested realm cannot match a row either.\n const list = Array.isArray(ctx.name) ? ctx.name : [ctx.name];\n if (list.some((name) => holds(name, ctx.data))) {\n return { verdict: 'post' };\n }\n\n return { verdict: 'deny' };\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["normalizeDate","toDate"],"sources":["../src/permission/error/module.ts","../src/permission/error/check.ts","../src/permission/realm-scope/constants.ts","../src/permission/realm-scope/helpers.ts","../src/permission/helpers/key.ts","../src/permission/helpers/aggregate.ts","../src/permission/helpers/equal.ts","../src/permission/helpers/grant.ts","../src/permission/provider/memory.ts","../src/policy/issue/constants.ts","../src/policy/issue/define.ts","../src/policy/error/module.ts","../src/policy/error/check.ts","../src/policy/engine/module.ts","../src/policy/data.ts","../src/policy/evaluation/context/define.ts","../src/policy/evaluation/context/transition.ts","../src/policy/helpers/invert.ts","../src/policy/built-in/attribute-names/validator.ts","../src/policy/built-in/attributes/define.ts","../src/policy/built-in/constants.ts","../src/policy/built-in/attributes/validator.ts","../src/policy/built-in/attributes/evaluator.ts","../src/policy/built-in/attribute-names/evaluator.ts","../src/policy/built-in/composite/validator.ts","../src/policy/built-in/composite/evaluator.ts","../src/policy/built-in/composite/helper.ts","../src/policy/built-in/date/validator.ts","../src/policy/built-in/date/evaluator.ts","../src/policy/built-in/identity/data/validator.ts","../src/policy/built-in/identity/validator.ts","../src/policy/built-in/identity/evaluator.ts","../src/policy/built-in/realm-match/validator.ts","../src/policy/built-in/realm-match/evaluator.ts","../src/policy/built-in/permission-binding/validator.ts","../src/policy/built-in/permission-binding/identity-evaluator.ts","../src/policy/built-in/permission-binding/module.ts","../src/policy/built-in/time/constants.ts","../src/policy/built-in/time/helpers.ts","../src/policy/built-in/time/validator.ts","../src/policy/built-in/time/evaluator.ts","../src/policy/built-in/define.ts","../src/policy/constants.ts","../src/policy/input.ts","../src/permission/evaluator/module.ts","../src/permission/authorization/error.ts","../src/permission/authorization/check.ts","../src/permission/authorization/schema.ts","../src/permission/authorization/check-schema.ts","../src/permission/authorization/constants.ts","../src/permission/authorization/policy.ts","../src/permission/authorization/module.ts"],"sourcesContent":["/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { AuthupErrorOptions } from '@authup/errors';\nimport { AuthupError, ErrorCode, markInstanceof } from '@authup/errors';\nimport type { PolicyIssue } from '../../policy';\n\nexport const PERMISSION_ERROR_INSTANCE = Symbol.for('@authup/access/PermissionError');\n\nexport class PermissionError extends AuthupError {\n constructor(options: AuthupErrorOptions = {}) {\n super({\n ...options,\n message: options.message || 'A permission error occurred.',\n code: options.code || ErrorCode.PERMISSION_DENIED,\n });\n markInstanceof(this, PERMISSION_ERROR_INSTANCE);\n }\n\n static notFound(name: string) {\n return new PermissionError({\n message: `The permission ${name} was not found.`,\n code: ErrorCode.PERMISSION_NOT_FOUND,\n });\n }\n\n static denied(name: string) {\n return new PermissionError({\n message: `The permission ${name} has not been granted.`,\n code: ErrorCode.PERMISSION_DENIED,\n });\n }\n\n static deniedAll(names: string[]) {\n return new PermissionError({\n message: `None of the permissions ${names.join(', ')} has been granted.`,\n code: ErrorCode.PERMISSION_DENIED,\n });\n }\n\n static evaluationFailed(name: string | string[], issues?: PolicyIssue[]) {\n if (Array.isArray(name)) {\n return new PermissionError({\n message: `The evaluation of permissions ${name.join(', ')} failed`,\n code: ErrorCode.PERMISSION_EVALUATION_FAILED,\n issues,\n });\n }\n\n return new PermissionError({\n message: `The evaluation of permission ${name} failed`,\n code: ErrorCode.PERMISSION_EVALUATION_FAILED,\n issues,\n });\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ErrorCode, isAuthupError, matchesInstanceof } from '@authup/errors';\nimport { PERMISSION_ERROR_INSTANCE, type PermissionError } from './module';\n\nexport function isPermissionError(input: unknown): input is PermissionError {\n if (matchesInstanceof(input, PERMISSION_ERROR_INSTANCE)) {\n return true;\n }\n\n if (!isAuthupError(input)) {\n return false;\n }\n\n return input.code === ErrorCode.PERMISSION_NOT_FOUND ||\n input.code === ErrorCode.PERMISSION_DENIED ||\n input.code === ErrorCode.PERMISSION_EVALUATION_FAILED;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * Actor-relative realm reach of a permission grant.\n *\n * Total order (least -> most permissive): none < own < ownOrNull < any.\n * A missing/unknown column coerces to `own` (fail-closed); `none` is only ever an\n * explicit value (the grant reaches no realm at all).\n */\nexport enum RealmScope {\n /** No reach — the grant matches no resource realm. */\n NONE = 'none',\n /** Own realm only — resource realm must equal the actor's realm. */\n OWN = 'own',\n /** Own realm or null/global resources (realmId === null). */\n OWN_OR_NULL = 'ownOrNull',\n /** Any realm, including null/global. */\n ANY = 'any',\n}\n\n/** Numeric restrictiveness order — internal to the fold/compare helpers. */\nexport const REALM_SCOPE_ORDER: Record<`${RealmScope}`, number> = {\n [RealmScope.NONE]: 0,\n [RealmScope.OWN]: 1,\n [RealmScope.OWN_OR_NULL]: 2,\n [RealmScope.ANY]: 3,\n};\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { REALM_SCOPE_ORDER, RealmScope } from './constants';\n\n/**\n * Coerce an arbitrary value to a RealmScope, defaulting to `own` for missing /\n * null / unknown input (fail-closed). `none` is honoured only when explicit.\n */\nexport function normalizeRealmScope(value?: `${RealmScope}` | null): `${RealmScope}` {\n return value === RealmScope.ANY ||\n value === RealmScope.OWN_OR_NULL ||\n value === RealmScope.NONE ?\n value :\n RealmScope.OWN;\n}\n\n/**\n * Numeric comparison of two realm scopes by restrictiveness.\n * Negative when `a` is more restrictive than `b`, positive when less.\n */\nexport function compareRealmScope(\n a?: `${RealmScope}` | null,\n b?: `${RealmScope}` | null,\n): number {\n return REALM_SCOPE_ORDER[normalizeRealmScope(a)] - REALM_SCOPE_ORDER[normalizeRealmScope(b)];\n}\n\n/** Fold scopes to the MOST permissive (ordered max). Empty folds to `own`. */\nexport function maxRealmScope(values: Array<`${RealmScope}` | null | undefined>): `${RealmScope}` {\n let max: `${RealmScope}` = RealmScope.NONE;\n let seen = false;\n for (const value of values) {\n seen = true;\n const scope = normalizeRealmScope(value);\n if (REALM_SCOPE_ORDER[scope] > REALM_SCOPE_ORDER[max]) {\n max = scope;\n }\n }\n // Empty input is fail-closed `own` (not `none`).\n return seen ? max : RealmScope.OWN;\n}\n\n/** Fold scopes to the MORE restrictive (ordered min) — used to CAP a grant. Empty folds to `own`. */\nexport function minRealmScope(values: Array<`${RealmScope}` | null | undefined>): `${RealmScope}` {\n let min: `${RealmScope}` = RealmScope.ANY;\n let seen = false;\n for (const value of values) {\n seen = true;\n const scope = normalizeRealmScope(value);\n if (REALM_SCOPE_ORDER[scope] < REALM_SCOPE_ORDER[min]) {\n min = scope;\n }\n }\n return seen ? min : RealmScope.OWN;\n}\n\n/**\n * Whether `scope` reaches a single resource realm `resourceRealmId` for an actor whose\n * realm is `identityRealmId`/`identityRealmName`.\n *\n * - `any` -> always.\n * - `none` -> never.\n * - realm-less actor (no realmId and no realmName) -> never `own`/`ownOrNull`.\n * - resource realm `null` (global) -> only `ownOrNull`.\n * - concrete resource realm -> must equal the actor's own realm (by id or name).\n */\nfunction matchesSingle(\n normalized: `${RealmScope}`,\n resourceRealmId: string | null,\n identityRealmId: string | null,\n identityRealmName: string | null,\n): boolean {\n if (resourceRealmId === null) {\n return normalized === RealmScope.OWN_OR_NULL;\n }\n return resourceRealmId === identityRealmId || resourceRealmId === identityRealmName;\n}\n\n/**\n * Whether `scope` reaches the resource. The resource realm may be presented as a single\n * id, `null` (global), or an array of realm ids — the array form (a resource that spans\n * multiple realms) requires the scope to reach EVERY listed realm (unanimous, fail-closed),\n * so any app/entity can express its realm via one or many keys under the canonical contract.\n */\nexport function realmScopeMatches(\n scope: `${RealmScope}` | null | undefined,\n resourceRealmId: string | Array<string | null> | null | undefined,\n identityRealmId: string | null | undefined,\n identityRealmName?: string | null,\n): boolean {\n const normalized = normalizeRealmScope(scope);\n if (normalized === RealmScope.ANY) {\n return true;\n }\n if (normalized === RealmScope.NONE) {\n return false;\n }\n\n const realmId = identityRealmId ?? null;\n const realmName = identityRealmName ?? null;\n if (realmId === null && realmName === null) {\n return false;\n }\n\n if (Array.isArray(resourceRealmId)) {\n // Fail closed: an empty realm set is unreachable for a scoped actor (`any`\n // already returned above). `[].every()` would otherwise vacuously pass.\n if (resourceRealmId.length === 0) {\n return false;\n }\n return resourceRealmId.every((id) => matchesSingle(normalized, id ?? null, realmId, realmName));\n }\n\n return matchesSingle(normalized, resourceRealmId ?? null, realmId, realmName);\n}\n","/*\n * Copyright (c) 2025-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n\nimport type { BasePermission } from '../types.ts';\n\nfunction formatKeySegment(value?: string | null): string {\n return value || '*';\n}\n\nexport function buildPermissionKey(\n input: BasePermission,\n) {\n return `${formatKeySegment(input.realmId)}/${formatKeySegment(input.clientId)}/${input.name}`;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { DecisionStrategy } from '@authup/kit';\nimport type { BasePolicy } from '../../policy';\nimport { normalizeRealmScope } from '../realm-scope';\nimport type {\n PermissionGrant,\n PermissionPolicyBinding,\n PermissionPolicyBindingAggregated,\n} from '../types';\nimport { buildPermissionKey } from './key';\n\ntype CompositePolicy = BasePolicy & {\n decisionStrategy?: `${DecisionStrategy}`,\n children: BasePolicy[],\n};\n\n/**\n * One disjunction term per raw binding: the grant's realm reach (fail-closed `own` default)\n * paired with its policy — the raw single policy (its `id` preserved for junction propagation),\n * a composite over multiple policies (Layer-1 permission policies, combined under the\n * permission's decisionStrategy), or `undefined` when the grant is unrestricted.\n */\nfunction buildGrant(binding: PermissionPolicyBinding): PermissionGrant {\n let policy: BasePolicy | undefined;\n if (binding.policies && binding.policies.length === 1) {\n policy = binding.policies[0];\n } else if (binding.policies && binding.policies.length > 1) {\n const composite: CompositePolicy = {\n type: 'composite',\n decisionStrategy: binding.permission.decisionStrategy || DecisionStrategy.UNANIMOUS,\n children: binding.policies,\n };\n policy = composite;\n }\n\n return {\n realmScope: normalizeRealmScope(binding.realmScope),\n policy,\n };\n}\n\n/**\n * Group raw permission-policy bindings by permission key into the actor's disjunction of\n * `(realmScope, policy)` grants per permission — with NO lossy collapse. Every consumer\n * (the binding evaluator, isSuperset, junction propagation, the memory provider) evaluates the\n * grant disjunction directly, so each grant's realm reach stays paired with the policy that\n * gates it.\n */\nexport function aggregatePermissionPolicyBindings(\n input: PermissionPolicyBinding[],\n): PermissionPolicyBindingAggregated[] {\n const grouped: Record<string, PermissionPolicyBinding[]> = input\n .reduce((previous, current) => {\n const key = buildPermissionKey(current.permission);\n if (!previous[key]) {\n previous[key] = [];\n }\n\n previous[key].push(current);\n\n return previous;\n }, {} as Record<string, PermissionPolicyBinding[]>);\n\n const output: PermissionPolicyBindingAggregated[] = [];\n for (const group of Object.values(grouped)) {\n output.push({\n permission: group[0]!.permission,\n grants: group.map(buildGrant),\n });\n }\n\n return output;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BasePermission } from '../types';\n\nexport function isPermissionPolicyBindingEqual(\n a: { permission: BasePermission },\n b: { permission: BasePermission },\n): boolean {\n if (a.permission.name !== b.permission.name) {\n return false;\n }\n\n if ((a.permission.realmId ?? null) !== (b.permission.realmId ?? null)) {\n return false;\n }\n\n if ((a.permission.clientId ?? null) !== (b.permission.clientId ?? null)) {\n return false;\n }\n\n return true;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isEqual } from 'smob';\nimport type { BasePolicy } from '../../policy';\nimport { compareRealmScope } from '../realm-scope';\nimport type { PermissionGrant } from '../types';\n\n/**\n * Policy fields that do NOT affect evaluation — persisted identity, audit and label columns plus\n * the loaded `parent` / `realm` relation objects. They are stripped before the structural compare\n * in isPolicyEquivalent so two DISTINCT rows with identical configuration still match. Verified\n * against every built-in evaluator, which read only `type`, `invert`, `decisionStrategy`,\n * `children` and the type-specific config (query / names / types / start / end / interval /\n * dayOf* / attributeName* / scope). `parent` is additionally a circular back-reference and\n * `realm` a nested object with its own id, so leaving either in would break the deep compare.\n *\n * SECURITY INVARIANT: every key here MUST stay non-evaluation-affecting. Adding an\n * evaluation-relevant field would silently widen equivalence into an over-permit. New *config*\n * fields need NOT be added — they are compared by default, which is the fail-closed direction.\n */\nconst NON_SEMANTIC_POLICY_KEYS = new Set<string>([\n 'id',\n 'builtIn',\n 'name',\n 'displayName',\n 'description',\n 'parentId',\n 'parent',\n 'realmId',\n 'realm',\n 'createdAt',\n 'updatedAt',\n]);\n\n/**\n * Project a policy node onto its evaluation-relevant configuration: drop the non-semantic keys\n * and recurse through `children` (the only field that carries nested policy nodes). Config values\n * (e.g. an `attributes` `query`) are left untouched, so a semantic `id` / `name` key *inside* a\n * query is never mistaken for the policy's own identity column.\n */\nfunction normalizePolicyForEquality(policy: BasePolicy): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(policy as Record<string, unknown>)) {\n if (NON_SEMANTIC_POLICY_KEYS.has(key)) {\n continue;\n }\n\n if (\n key === 'children' &&\n Array.isArray(value)\n ) {\n result[key] = value.map((child) => normalizePolicyForEquality(child as BasePolicy));\n continue;\n }\n\n result[key] = value;\n }\n\n return result;\n}\n\n/**\n * Whether two restriction policies are provably the SAME policy for domination purposes — by\n * persisted identity OR by identical configuration, never by evaluated effect. Fast path: equal\n * primary-key `id` means the same persisted row (the `typeof … === 'string'` guards keep an\n * id-less / missing-id policy out of it — never `undefined === undefined`). Otherwise fall back to\n * a structural value-compare of the configuration (`normalizePolicyForEquality` strips the\n * non-semantic identity / audit / relation columns, `isEqual` deep-compares the rest), so two\n * distinct rows with identical config — the same predicate — still dominate. Comparing by\n * *effect* is undecidable (a policy is a predicate over PolicyData), so we accept ONLY provable\n * identity or provable structural equality; a genuinely different configuration is treated as\n * distinct (fail-closed) — isSuperset must never assume one restriction covers a different one.\n */\nfunction isPolicyEquivalent(parent: BasePolicy, child: BasePolicy): boolean {\n const parentId = (parent as { id?: unknown }).id;\n const childId = (child as { id?: unknown }).id;\n\n if (\n typeof parentId === 'string' &&\n typeof childId === 'string' &&\n parentId === childId\n ) {\n return true;\n }\n\n return isEqual(normalizePolicyForEquality(parent), normalizePolicyForEquality(child));\n}\n\n/**\n * Whether the actor's `parent` policy provably covers the target's `child` policy on a shared\n * permission. Conservative / fail-closed:\n * - an unrestricted parent (no policy) covers any child;\n * - a restricted parent NEVER covers an unrestricted child — it cannot confer the wider,\n * policy-free reach it does not itself hold;\n * - two restricted grants cover one another only when their policies are provably equivalent.\n * A DIFFERENT policy is NOT assumed to be a subset (#3159: the predecessor treated any two\n * policy-bound grants as mutually dominating, a latent over-permit across disjoint policy\n * scopes — e.g. an actor restricted to `department=X` conferring a `department=Y` grant).\n */\nfunction policyDominates(parent?: BasePolicy, child?: BasePolicy): boolean {\n if (!parent) {\n return true;\n }\n\n if (!child) {\n return false;\n }\n\n return isPolicyEquivalent(parent, child);\n}\n\n/**\n * Whether the actor's `parent` grant covers the target's `child` grant: it reaches at least as\n * far (ordered none < own < ownOrNull < any) AND its policy provably covers the child's\n * (see `policyDominates`). Used per grant by `isSuperset` over the aggregated disjunction —\n * every child grant must be dominated by SOME parent grant.\n */\nexport function grantDominates(parent: PermissionGrant, child: PermissionGrant): boolean {\n if (compareRealmScope(parent.realmScope, child.realmScope) < 0) {\n return false;\n }\n\n return policyDominates(parent.policy, child.policy);\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { aggregatePermissionPolicyBindings, buildPermissionKey } from '../helpers';\nimport type { PermissionPolicyBinding, PermissionPolicyBindingAggregated } from '../types';\nimport type { IPermissionProvider, PermissionGetOptions } from './types';\n\nexport class PermissionMemoryProvider implements IPermissionProvider {\n protected items : Record<string, PermissionPolicyBindingAggregated> = {};\n\n constructor(items: PermissionPolicyBinding[] = []) {\n this.setMany(items);\n }\n\n async findOne(\n options: PermissionGetOptions,\n ): Promise<PermissionPolicyBindingAggregated | null> {\n const key = buildPermissionKey({\n name: options.name,\n clientId: options.clientId,\n realmId: options.realmId,\n });\n\n const entry = this.items[key];\n if (entry) {\n return entry;\n }\n\n return null;\n }\n\n setMany(input: PermissionPolicyBinding[]) {\n this.items = aggregatePermissionPolicyBindings(input)\n .reduce((prev, current) => {\n const key = buildPermissionKey(current.permission);\n prev[key] = current;\n return prev;\n }, {} as Record<string, PermissionPolicyBindingAggregated>);\n }\n}\n","/*\n * Copyright (c) 2026-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum PolicyIssueSeverity {\n WARNING = 'warning',\n ERROR = 'error',\n}\n\nexport enum PolicyIssueCode {\n // Data/Input\n DATA_MISSING = 'DATA_MISSING',\n DATA_INVALID = 'DATA_INVALID',\n\n // Policy Spec / Config\n INVALID = 'INVALID',\n TYPE_UNKNOWN = 'TYPE_UNKNOWN',\n FIELD_MISSING = 'FIELD_MISSING',\n FIELD_INVALID = 'FIELD_INVALID',\n\n // Composite / Tree evaluation\n CHILD_INVALID = 'CHILD_INVALID',\n CHILD_EVALUATION_FAILED = 'CHILD_EVALUATION_FAILED',\n\n // Engine / Evaluator registry\n EVALUATION_DENIED = 'EVALUATION_DENIED',\n EVALUATOR_NOT_FOUND = 'EVALUATOR_NOT_FOUND',\n EVALUATOR_ERROR = 'EVALUATOR_ERROR',\n\n // Execution control\n SKIPPED_EXCLUDED = 'SKIPPED_EXCLUDED',\n SKIPPED_NOT_INCLUDED = 'SKIPPED_NOT_INCLUDED',\n\n // Internal / unexpected\n INTERNAL_ERROR = 'INTERNAL_ERROR',\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueGroup, defineIssueItem } from '@ebec/core';\nimport type { PolicyIssueGroup, PolicyIssueItem } from './types.ts';\n\nexport function definePolicyIssueItem(input: Omit<PolicyIssueItem, 'type'>) : PolicyIssueItem {\n return defineIssueItem(input);\n}\n\nexport function definePolicyIssueGroup(input: Omit<PolicyIssueGroup, 'type'>) : PolicyIssueGroup {\n return defineIssueGroup(input);\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { AuthupError, ErrorCode, markInstanceof } from '@authup/errors';\nimport type { PolicyIssue } from '../issue';\n\nexport const POLICY_ERROR_INSTANCE = Symbol.for('@authup/access/PolicyError');\n\nexport class PolicyError extends AuthupError {\n constructor(message?: string, code?: string | null, issues?: PolicyIssue[]) {\n super({\n message,\n code: code ?? undefined,\n issues,\n });\n markInstanceof(this, POLICY_ERROR_INSTANCE);\n }\n\n static evaluatorNotFound(type: string) {\n return new PolicyError(\n `No evaluator is registered to handle the policy: ${type}`,\n ErrorCode.POLICY_EVALUATOR_NOT_FOUND,\n );\n }\n\n static evaluatorNotProcessable() {\n return new PolicyError(\n 'The evaluator can not process the policy.',\n ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE,\n );\n }\n\n static evaluatorContextInvalid() {\n return new PolicyError(\n 'The evaluator context is not valid.',\n ErrorCode.POLICY_EVALUATOR_CONTEXT_INVALID,\n );\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ErrorCode, isAuthupError, matchesInstanceof } from '@authup/errors';\nimport { POLICY_ERROR_INSTANCE, type PolicyError } from './module';\n\nexport function isPolicyError(input: unknown): input is PolicyError {\n if (matchesInstanceof(input, POLICY_ERROR_INSTANCE)) {\n return true;\n }\n\n if (!isAuthupError(input)) {\n return false;\n }\n\n return input.code === ErrorCode.POLICY_EVALUATOR_NOT_FOUND ||\n input.code === ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE ||\n input.code === ErrorCode.POLICY_EVALUATOR_CONTEXT_INVALID;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { ErrorCode } from '@authup/errors';\nimport { defineIssueItem } from '@ebec/core';\nimport type {\n IPolicyEvaluator,\n PolicyEvaluationContext,\n PolicyEvaluationResult,\n PolicyEvaluators,\n} from '../evaluation';\nimport type { PolicyIssue } from '../issue';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../issue';\nimport type { IPolicyEngine } from './types.ts';\nimport { PolicyError, isPolicyError } from '../error';\nimport type { BasePolicy } from '../types.ts';\n\n// Cross-realm-safe extraction of an error message from an unknown thrown\n// value. `instanceof Error` is unreliable across module boundaries (different\n// realms, dual-bundled packages), so we duck-type on the `message` shape.\nfunction errorMessage(value: unknown): string {\n if (\n typeof value === 'object' &&\n value !== null &&\n 'message' in value &&\n typeof (value as { message: unknown }).message === 'string'\n ) {\n return (value as { message: string }).message;\n }\n return String(value);\n}\n\n/**\n * The policy engine is a component that interprets defined policies and makes decisions\n * on whether to allow or deny a particular access.\n */\nexport class PolicyEngine implements IPolicyEngine {\n protected evaluators : Record<string, IPolicyEvaluator>;\n\n constructor(evaluators: PolicyEvaluators = {}) {\n // A COPY, never the caller's object: `registerEvaluator` writes into\n // this map, and every engine is constructed from the shared\n // `PolicyDefaultEvaluators` constant. Held by reference, one engine's\n // registration reached every other engine in the process. Two\n // applications in one process then shared whichever permission-binding\n // evaluator was built last, and the older one evaluated its grants\n // against the newer one's database.\n this.evaluators = { ...evaluators };\n }\n\n public registerEvaluator(\n type: string,\n evaluator: IPolicyEvaluator,\n ) : void {\n this.evaluators[type] = evaluator;\n }\n\n public registerEvaluators(evaluators: PolicyEvaluators) {\n const keys = Object.keys(evaluators);\n for (const key of keys) {\n this.registerEvaluator(key, evaluators[key]!);\n }\n }\n\n /**\n * @param policy\n * @param ctx\n */\n async evaluate(policy: BasePolicy, ctx: PolicyEvaluationContext) : Promise<PolicyEvaluationResult> {\n // Infrastructure errors (no type, no evaluator, evaluator threw) MUST\n // fail closed regardless of `policy.invert`. Inverting an error path\n // would silently grant access on misconfiguration — with `invert: true`\n // an unregistered policy type would return success: true.\n if (!policy.type) {\n return {\n success: false,\n issues: [\n defineIssueItem({\n path: [],\n message: 'The policy can not be handled by any evaluator.',\n code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND,\n }),\n ],\n };\n }\n // When a policy is filtered out via include/exclude, treat it as a\n // neutral pass — do NOT apply `invert`. Inversion only makes sense\n // for an actual evaluation outcome; skipping a policy because it's\n // outside the current context's scope is not an outcome.\n if (\n ctx.exclude &&\n ctx.exclude.length > 0 &&\n ctx.exclude.includes(policy.type)\n ) {\n return { success: true };\n }\n\n if (\n ctx.include &&\n ctx.include.length > 0 &&\n !ctx.include.includes(policy.type)\n ) {\n return { success: true };\n }\n\n const issues : PolicyIssue[] = [];\n\n const evaluator = this.evaluators[policy.type];\n if (!evaluator) {\n issues.push(defineIssueItem({\n path: [policy.type],\n message: `The policy ${policy.type} can not be handled by any evaluator.`,\n code: ErrorCode.POLICY_EVALUATOR_NOT_FOUND,\n }));\n\n return {\n success: false,\n issues,\n };\n }\n\n // Data-availability gate: a policy whose declared data requirements are not\n // satisfied yet is PENDING — not true, not false. Like the include/exclude\n // neutral-pass, `invert` is never applied here (the evaluator is not invoked\n // at all): unknown stays unknown under negation. Wrapped in the same try as\n // the evaluation itself so a throwing `requires()` fails closed (structured\n // deny) instead of rejecting out of `evaluate()`.\n try {\n if (evaluator.requires) {\n const missing = evaluator.requires(policy)\n .filter((key) => !ctx.data || !ctx.data.has(key));\n\n if (missing.length > 0) {\n const result : PolicyEvaluationResult = {\n success: false,\n pending: true,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: `The data propert${missing.length > 1 ? 'ies' : 'y'} ${missing.join(', ')} ${missing.length > 1 ? 'are' : 'is'} missing`,\n path: ctx.path,\n }),\n ],\n };\n\n // Condition form of the pending leaf (WHERE pushdown), on request only.\n // A throwing / null toCondition simply leaves the result condition-less —\n // the consumer falls back to a per-row post-check (fail-safe).\n if (ctx.withConditions && evaluator.toCondition) {\n try {\n const condition = await evaluator.toCondition(policy, ctx);\n if (condition) {\n result.condition = condition;\n }\n } catch {\n // not expressible — stays a post-check\n }\n }\n\n return result;\n }\n }\n\n return await evaluator.evaluate(policy, {\n ...ctx,\n evaluators: {\n ...this.evaluators,\n ...(ctx.evaluators || {}),\n },\n });\n } catch (e) {\n issues.push(defineIssueItem({\n path: [policy.type],\n message: `The ${policy.type} evaluator threw: ${errorMessage(e)}`,\n code: ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE,\n }));\n\n return {\n success: false,\n issues,\n };\n }\n }\n\n async evaluateOrFail(policy: BasePolicy, ctx: PolicyEvaluationContext) : Promise<void> {\n const issues : PolicyIssue[] = [];\n\n try {\n const outcome = await this.evaluate(policy, ctx);\n if (outcome.success) {\n return;\n }\n\n if (outcome.issues) {\n issues.push(...outcome.issues);\n }\n } catch (e) {\n if (isPolicyError(e)) {\n throw e;\n }\n\n // Surface non-PolicyError throws (DB failures, validator crashes, etc.)\n // as issues so the root cause is visible instead of being swallowed\n // behind a generic policy failure.\n issues.push(defineIssueItem({\n path: policy.type ? [policy.type] : [],\n message: errorMessage(e),\n code: ErrorCode.POLICY_EVALUATOR_NOT_PROCESSABLE,\n }));\n }\n\n throw new PolicyError(`The policy ${policy.type} evaluation failed.`, undefined, issues);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport interface IPolicyData {\n set(key: string, value: unknown) : void;\n has(key: string): boolean;\n get<T = unknown>(key: string) : T;\n delete(key: string) : void;\n\n isValidated(key: string): boolean;\n setValidated(key: string) : void;\n\n clone() : IPolicyData\n}\n\nexport class PolicyData implements IPolicyData {\n protected data: Record<string, any>;\n\n protected validated : Set<string>;\n\n constructor(\n data: Record<string, any> = {},\n validated: Set<string> = new Set(),\n ) {\n this.data = data;\n this.validated = validated;\n }\n\n set<T = unknown>(key: string, value: T) : void {\n this.data[key] = value;\n this.validated.delete(key);\n }\n\n get<T = unknown>(key: string) : T {\n if (key in this.data) {\n return this.data[key];\n }\n\n throw new Error(`Policy data item ${key} does not exist.`);\n }\n\n has(key: string): boolean {\n return key in this.data;\n }\n\n delete(key: string) : void {\n delete this.data[key];\n this.validated.delete(key);\n }\n\n setValidated(key: string) : void {\n this.validated.add(key);\n }\n\n isValidated(key: string) : boolean {\n return this.validated.has(key);\n }\n\n clone() {\n return new PolicyData({ ...this.data }, new Set(this.validated));\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyEvaluationContext, PolicyEvaluationContextInput } from './types.ts';\nimport { PolicyData } from '../../data.ts';\n\nexport function definePolicyEvaluationContext(\n input: PolicyEvaluationContextInput = {},\n) : PolicyEvaluationContext {\n return {\n evaluators: input.evaluators || {},\n path: input.path || [],\n data: input.data || new PolicyData(),\n include: input.include || [],\n exclude: input.exclude || [],\n withConditions: input.withConditions ?? false,\n realmAttributeName: input.realmAttributeName,\n transitions: input.transitions,\n };\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyTransitionSink } from './types.ts';\n\nexport type PolicyTransitionCollector = PolicyTransitionSink & {\n /**\n * The earliest reported instant, or undefined when nothing reported one.\n */\n readonly next: Date | undefined\n};\n\n/**\n * A sink keeping the earliest reported instant, which is the moment an answer\n * built from every evaluation it was handed to stops being current.\n */\nexport function createPolicyTransitionCollector() : PolicyTransitionCollector {\n let next : Date | undefined;\n\n return {\n report(at: Date) {\n if (!next || at.getTime() < next.getTime()) {\n next = at;\n }\n },\n get next() {\n return next;\n },\n };\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\ntype InvertFn = (input: boolean) => boolean;\n\nexport function maybeInvertPolicyOutcome(\n outcome: boolean,\n invert?: boolean | InvertFn,\n) {\n if (typeof invert === 'undefined') {\n return outcome;\n }\n\n if (typeof invert === 'function') {\n return invert(outcome);\n }\n\n if (!invert) {\n return outcome;\n }\n\n return !outcome;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { AttributeNamesPolicy } from './types';\n\nexport class AttributeNamesPolicyValidator extends Container<AttributeNamesPolicy> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'names',\n createValidator(\n z.array(\n z.string()\n .min(3)\n .max(128),\n ),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { AttributesPolicy } from './types';\n\nexport function defineAttributesPolicy<\n T extends Record<string, any> = Record<string, any>,\n>(\n data: AttributesPolicy<T>,\n) : AttributesPolicy<T> {\n return data;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum BuiltInPolicyType {\n /**\n * Bundles different policies.\n */\n COMPOSITE = 'composite',\n /**\n * Date Based Access Control (DBAC)\n */\n DATE = 'date',\n /**\n * Time Based Access Control (TBAC)\n */\n TIME = 'time',\n /**\n * Attribute Name Based Access Control (ANBAC)\n */\n ATTRIBUTE_NAMES = 'attributeNames',\n /**\n * Attribute Based Access Control (ABAC)\n */\n ATTRIBUTES = 'attributes',\n /**\n * Realm of Identity is for attribute realm.\n */\n REALM_MATCH = 'realmMatch',\n\n /**\n * Restriction based on identity (type, id, ...)\n */\n IDENTITY = 'identity',\n\n /**\n * Restriction based on a binding between identity <-> permission\n */\n PERMISSION_BINDING = 'permissionBinding',\n\n // Location (LBAC)\n // Device (DBAC)\n}\n\nexport const SystemPolicyName = {\n DEFAULT: 'system.default',\n IDENTITY: 'system.identity',\n PERMISSION_BINDING: 'system.permission-binding',\n REALM_MATCH: 'system.realm-match',\n CLIENT_NAMES_SELF_MANAGE: 'system.client-names-self-manage',\n USER_NAMES_SELF_MANAGE: 'system.user-names-self-manage',\n} as const;\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { AttributesPolicy } from './types';\n\nexport class AttributesPolicyValidator<\n T extends Record<string, any> = Record<string, any>,\n> extends Container<AttributesPolicy<T>> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'query',\n createValidator(\n z.looseObject({}),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { not } from '@rapiq/core';\nimport type { Predicate } from '@rapiq/adapter-memory';\nimport { compileFilters } from '@rapiq/adapter-memory';\nimport { MongoFiltersParser } from '@rapiq/parser-mongo';\nimport { isObject } from '@authup/kit';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { BuiltInPolicyType } from '../constants.ts';\nimport type { AttributesPolicy } from './types';\nimport { AttributesPolicyValidator } from './validator';\n\nexport class AttributesPolicyEvaluator<\n T extends Record<string, any> = Record<string, any>,\n> implements IPolicyEvaluator {\n protected validator : AttributesPolicyValidator<T>;\n\n protected parser : MongoFiltersParser;\n\n constructor() {\n this.validator = new AttributesPolicyValidator<T>();\n this.parser = new MongoFiltersParser();\n }\n\n requires() : string[] {\n return [BuiltInPolicyType.ATTRIBUTES];\n }\n\n async toCondition(value: Record<string, any>) : Promise<ICondition | null> {\n let policy : AttributesPolicy<T>;\n let condition : ICondition;\n\n try {\n policy = await this.validator.run(value);\n this.fixQuery(policy.query);\n condition = this.parser.parse(policy.query);\n } catch {\n return null;\n }\n\n // rapiq's not() is the exact null-inclusive complement (tada5hi/rapiq#812) —\n // identical to inverting the compiled predicate's verdict per row.\n return policy.invert ? not(condition) : condition;\n }\n\n async accessData(ctx: PolicyEvaluationContext) : Promise<T | null> {\n if (!ctx.data.has(BuiltInPolicyType.ATTRIBUTES)) {\n return null;\n }\n\n if (ctx.data.isValidated(BuiltInPolicyType.ATTRIBUTES)) {\n return ctx.data.get<T>(BuiltInPolicyType.ATTRIBUTES);\n }\n\n // todo: run validator on attributes (isObject ...)\n const data = ctx.data.get<T>(BuiltInPolicyType.ATTRIBUTES);\n\n ctx.data.set(BuiltInPolicyType.ATTRIBUTES, data);\n ctx.data.setValidated(BuiltInPolicyType.ATTRIBUTES);\n\n return data;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n const policy = await this.validator.run(value);\n\n const data = await this.accessData(ctx);\n if (!data) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property attributes is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n this.fixQuery(policy.query);\n\n let testIt : Predicate;\n\n try {\n const condition = this.parser.parse(policy.query);\n\n // string equality stays byte-exact (the semantics the previous\n // @ucast/mongo2js evaluator enforced)\n testIt = compileFilters(condition, { caseSensitive: true });\n } catch (e) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.FIELD_INVALID,\n message: e instanceof Error ?\n e.message :\n 'The query could not be parsed.',\n path: ctx.path,\n }),\n ],\n };\n }\n\n return { success: maybeInvertPolicyOutcome(testIt(data), policy.invert) };\n }\n\n protected fixQuery(\n query: unknown | unknown[],\n ) {\n if (Array.isArray(query)) {\n for (const element of query) {\n this.fixQuery(element);\n }\n\n return;\n }\n\n if (isObject(query)) {\n const keys = Object.keys(query);\n for (const key of keys) {\n const value = query[key];\n\n if (isObject(value) || Array.isArray(value)) {\n this.fixQuery(value);\n continue;\n }\n\n if (\n key === '$regex' &&\n typeof value === 'string'\n ) {\n const fragments = value.match(/\\/(.*?)\\/([a-z]*)?$/i);\n if (fragments && fragments[1] !== undefined) {\n query[key] = new RegExp(fragments[1], fragments[2] || '');\n }\n }\n }\n }\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { flattenObject } from '@authup/kit';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport type { PolicyIssue } from '../../issue';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { AttributeNamesPolicyValidator } from './validator';\nimport { AttributesPolicyEvaluator } from '../attributes';\nimport { BuiltInPolicyType } from '../constants';\n\nexport class AttributeNamesPolicyEvaluator implements IPolicyEvaluator {\n protected validator : AttributeNamesPolicyValidator;\n\n protected attributesEvaluator : AttributesPolicyEvaluator;\n\n constructor() {\n this.validator = new AttributeNamesPolicyValidator();\n this.attributesEvaluator = new AttributesPolicyEvaluator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // The policy settles against EITHER data key: the ATTRIBUTE_NAMES key carries a\n // plain projection/fieldset (string[]) — \"may this actor project these field\n // names\", answerable before any row exists — while the ATTRIBUTES record keeps\n // its established key semantics. The tri-state lives HERE instead of a\n // `requires()` declaration: the engine's requires-gate is AND-semantics over the\n // declared keys, so declaring both would pend every bag carrying only one of\n // them. Checked before the validator run so gate-style calls with an empty bag\n // stay cheap.\n const hasNames = ctx.data.has(BuiltInPolicyType.ATTRIBUTE_NAMES);\n const hasAttributes = ctx.data.has(BuiltInPolicyType.ATTRIBUTES);\n\n if (!hasNames && !hasAttributes) {\n return {\n success: false,\n pending: true,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property attributeNames or attributes is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n // Conjunctive over the available sources: when both keys are present BOTH are\n // enforced — a reused bag that carries a projection alongside row attributes can\n // never weaken an existing record gate. Keys are deduplicated so a name present\n // in both sources yields one issue.\n const keys = new Set<string>();\n\n if (hasNames) {\n // Non-string entries fail closed as invalid data — silently skipping\n // them would fail open in denylist (invert) mode.\n const data = ctx.data.get(BuiltInPolicyType.ATTRIBUTE_NAMES);\n if (\n !Array.isArray(data) ||\n data.some((entry) => typeof entry !== 'string')\n ) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_INVALID,\n message: 'The data property attributeNames must be a list of attribute names',\n path: ctx.path,\n }),\n ],\n };\n }\n\n for (const entry of data) {\n keys.add(entry);\n }\n }\n\n if (hasAttributes) {\n const data = await this.attributesEvaluator.accessData(ctx);\n if (data) {\n // Nested paths are a deliberate feature: an attribute object like\n // `{user: {name: 'x'}}` flattens to `{'user.name': 'x'}` and is matched\n // against `names` entries with dotted notation. Allowlists/denylists\n // that need to govern nested fields must use the dotted-path form\n // (e.g. `'user.realmId'`); a top-level entry like `'realmId'` will\n // NOT catch a nested `user.realmId` write — that's by design, the\n // policy is precise about which path it covers.\n const attributes = flattenObject(data);\n for (const key of Object.keys(attributes)) {\n keys.add(key);\n }\n }\n }\n\n // `invert` is consumed per-key, NOT at the result level:\n // - allowlist (default): a key NOT in `names` is denied\n // - denylist (invert: true): a key IN `names` is denied\n // Result-level inversion would break the empty-input case (a request\n // with no validated attributes would flip success → fail), and would\n // produce nonsensical \"deny iff all keys are in the list\" semantics\n // for partial inputs.\n const issues : PolicyIssue[] = [];\n for (const key of keys) {\n const inList = policy.names.includes(key);\n const denied = policy.invert ? inList : !inList;\n if (denied) {\n issues.push(definePolicyIssueItem({\n code: PolicyIssueCode.EVALUATION_DENIED,\n message: policy.invert ?\n `The attribute ${key} is denied` :\n `The attribute ${key} is not included`,\n path: [...ctx.path, key],\n }));\n }\n }\n\n return {\n success: issues.length === 0,\n issues,\n };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport { DecisionStrategy } from '@authup/kit';\nimport type { CompositePolicy } from './types';\n\nexport class CompositePolicyValidator extends Container<CompositePolicy> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'decisionStrategy',\n createValidator(\n z.enum(DecisionStrategy)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'children',\n createValidator(\n z.array(z.looseObject({ type: z.string().min(1) })),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { and, not, or } from '@rapiq/core';\nimport { defineIssueGroup } from '@ebec/core';\nimport { DecisionStrategy } from '@authup/kit';\nimport { PolicyEngine } from '../../engine';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport type { PolicyIssue } from '../../issue';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { CompositePolicyValidator } from './validator';\n\nexport class CompositePolicyEvaluator implements IPolicyEvaluator {\n protected validator : CompositePolicyValidator;\n\n constructor() {\n this.validator = new CompositePolicyValidator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n // A composite policy with no children can never be satisfied — an empty\n // UNANIMOUS/CONSENSUS settles false and an empty AFFIRMATIVE settles\n // false — so a permission bound to one is permanently un-grantable.\n // Fail closed with an explicit diagnostic instead of settling `false`\n // with an empty issue list, which reads as an opaque \"stale\" permission\n // (#3304). Like the engine's unregistered-type handling, this\n // misconfiguration fails closed regardless of `invert`.\n if (policy.children.length === 0) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.INVALID,\n message: 'A composite policy must define at least one child policy.',\n path: ctx.path,\n }),\n ],\n };\n }\n\n let count = 0;\n let pending = 0;\n\n const decisionStrategy = policy.decisionStrategy ??\n DecisionStrategy.UNANIMOUS;\n\n const engine = new PolicyEngine(ctx.evaluators);\n const issues : PolicyIssue[] = [];\n const pendingIssues : PolicyIssue[] = [];\n const pendingConditions : ICondition[] = [];\n let pendingWithoutCondition = 0;\n\n for (const childPolicy of policy.children) {\n const path = [\n ...(ctx.path || []),\n ...(childPolicy.type ? [childPolicy.type] : []),\n ];\n\n const outcome = await engine.evaluate(childPolicy, {\n ...ctx,\n path,\n });\n\n // A pending child is UNKNOWN, not a failure: it neither counts nor\n // early-returns. Masking it to a settled value breaks under negation\n // (mask-then-negate ≠ negate-then-mask — issue #3286).\n if (outcome.pending) {\n pending++;\n\n if (outcome.condition) {\n pendingConditions.push(outcome.condition);\n } else {\n pendingWithoutCondition++;\n }\n\n if (outcome.issues && outcome.issues.length > 0) {\n pendingIssues.push(defineIssueGroup({\n message: `The evaluation of child policy ${childPolicy.type} is pending`,\n issues: outcome.issues,\n path,\n }));\n }\n\n continue;\n }\n\n if (outcome.success) {\n if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return {\n success: maybeInvertPolicyOutcome(true, policy.invert),\n issues: [],\n };\n }\n\n count++;\n } else {\n if (outcome.issues) {\n issues.push(defineIssueGroup({\n message: `The evaluation of child policy ${childPolicy.type} failed`,\n issues: outcome.issues || [],\n path,\n }));\n }\n\n if (decisionStrategy === DecisionStrategy.UNANIMOUS) {\n const success = maybeInvertPolicyOutcome(false, policy.invert);\n return {\n success,\n // When `invert` flips a child-failure into success,\n // suppress the issue list — surfacing failure issues\n // alongside `success: true` is misleading.\n issues: success ? [] : [\n defineIssueGroup({\n message: `The evaluation of composite policy failed (${DecisionStrategy.UNANIMOUS})`,\n issues,\n path: ctx.path,\n }),\n ],\n };\n }\n\n count--;\n }\n }\n\n // Settle the remainder: the composite settles despite pending children only\n // when no resolution of those children could change the outcome.\n let settled : boolean | null;\n switch (decisionStrategy) {\n case DecisionStrategy.AFFIRMATIVE: {\n // every settled child failed; any pending child could still succeed\n settled = pending > 0 ? null : false;\n break;\n }\n case DecisionStrategy.UNANIMOUS: {\n // every settled child succeeded; any pending child could still fail\n settled = pending > 0 ? null : count > 0;\n break;\n }\n default: {\n // CONSENSUS: final outcome is `count > 0`, each pending worth ±1\n if (count - pending > 0) {\n settled = true;\n } else if (count + pending <= 0) {\n settled = false;\n } else {\n settled = null;\n }\n }\n }\n\n if (settled === null) {\n // Unknown stays unknown — `invert` is deliberately NOT applied to the\n // pending SUCCESS. The condition form is composed structurally instead:\n // settled children are identity elements and drop out of the residual,\n // so AND residual = and(pending), OR residual = or(pending). Exact-only,\n // all-or-nothing per node: one pending child without a condition makes\n // the whole node non-expressible (an OR pushing a single disjunct would\n // wrongly EXCLUDE rows; a partial AND is a compiler-level optimization,\n // deliberately not done here). CONSENSUS thresholds over row-dependent\n // outcomes never lower. `invert` wraps the residual SYMBOLICALLY via\n // rapiq's null-inclusive-complement not() — negation applies to the\n // condition even though the pending success stays uninverted.\n let condition : ICondition | null = null;\n if (\n pendingWithoutCondition === 0 &&\n ctx.withConditions &&\n pendingConditions.length > 0 &&\n decisionStrategy !== DecisionStrategy.CONSENSUS\n ) {\n if (pendingConditions.length === 1) {\n const [first] = pendingConditions;\n condition = first ?? null;\n } else if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n condition = or(...pendingConditions);\n } else {\n condition = and(...pendingConditions);\n }\n\n if (condition && policy.invert) {\n condition = not(condition);\n }\n }\n\n return {\n success: false,\n pending: true,\n ...(condition ? { condition } : {}),\n issues: pendingIssues,\n };\n }\n\n if (settled) {\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n const success = maybeInvertPolicyOutcome(false, policy.invert);\n return {\n success,\n issues: success ? [] : [\n defineIssueGroup({\n message: `The evaluation of composite policy failed (${decisionStrategy})`,\n issues: issues || [],\n path: ctx.path,\n }),\n ],\n };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyWithType } from '../../types';\nimport { BuiltInPolicyType } from '../constants';\nimport type { CompositePolicy } from './types';\n\nexport function isCompositePolicy(\n input: PolicyWithType,\n) : input is PolicyWithType<CompositePolicy> {\n return input.type === BuiltInPolicyType.COMPOSITE;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { DatePolicy } from './types';\n\nexport class DatePolicyValidator extends Container<DatePolicy> {\n override initialize() {\n super.initialize();\n\n this.mount('start', createValidator(\n z.date()\n .or(z.iso.date())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('end', createValidator(\n z.date()\n .or(z.iso.date())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n\n this.mount('invert', createValidator(\n z.boolean()\n .or(z.undefined())\n .or(z.null())\n .optional(),\n ));\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants.ts';\nimport type { DatePolicy } from './types';\nimport { DatePolicyValidator } from './validator';\n\nfunction normalizeDate(input: Date) {\n return new Date(input.getFullYear(), input.getMonth(), input.getDate());\n}\n\nfunction toDate(input: Date | string | number) : Date {\n if (typeof input === 'string') {\n return new Date(input);\n }\n\n if (typeof input === 'number') {\n return new Date(input);\n }\n\n return input;\n}\n\n/**\n * The next instant at which a date policy's verdict could change, seen from the\n * (day-normalized) `now`: the start day while it is still ahead, else the\n * midnight after the end day while that day has not passed. Nothing once the\n * end day is behind, since the verdict is final from then on.\n */\nfunction nextDateTransition(policy: DatePolicy, now: Date) : Date | undefined {\n if (policy.start) {\n const start = normalizeDate(toDate(policy.start));\n if (now < start) {\n return start;\n }\n }\n\n if (policy.end) {\n const end = normalizeDate(toDate(policy.end));\n if (now <= end) {\n return new Date(end.getFullYear(), end.getMonth(), end.getDate() + 1);\n }\n }\n\n return undefined;\n}\n\nexport class DatePolicyEvaluator implements IPolicyEvaluator {\n protected validator : DatePolicyValidator;\n\n constructor() {\n this.validator = new DatePolicyValidator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n let now : Date;\n\n if (ctx.data.has(BuiltInPolicyType.DATE)) {\n if (ctx.data.isValidated(BuiltInPolicyType.DATE)) {\n now = ctx.data.get<Date>(BuiltInPolicyType.DATE);\n } else {\n // todo: run validator on attributes (isObject ...)\n now = normalizeDate(toDate(ctx.data.get(BuiltInPolicyType.DATE)));\n\n ctx.data.set(BuiltInPolicyType.DATE, now);\n ctx.data.setValidated(BuiltInPolicyType.DATE);\n }\n } else {\n now = normalizeDate(new Date());\n\n // Only a verdict read off the real clock expires; a supplied date is fixed.\n if (ctx.transitions) {\n const next = nextDateTransition(policy, now);\n if (next) {\n ctx.transitions.report(next);\n }\n }\n }\n\n if (policy.start) {\n const start = normalizeDate(toDate(policy.start));\n if (now < start) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (policy.end) {\n const end = normalizeDate(toDate(policy.end));\n if (now > end) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2024-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\n\nimport type { IdentityPolicyData } from '../types.ts';\n\nexport class PolicyIdentityDataValidator extends Container<IdentityPolicyData> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'type',\n createValidator(\n z.string().min(3).max(128),\n ),\n );\n\n this.mount(\n 'id',\n createValidator(\n z.uuid(),\n ),\n );\n\n this.mount(\n 'clientId',\n createValidator(\n z.uuid()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'realmId',\n createValidator(\n z.uuid()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'realmName',\n createValidator(\n z.string().min(3).max(128)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { IdentityPolicy } from './types';\n\nexport class IdentityPolicyValidator extends Container<IdentityPolicy> {\n override initialize() {\n this.mount(\n 'types',\n createValidator(\n z.array(z.string())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants';\nimport { PolicyIdentityDataValidator } from './data';\nimport type { IdentityPolicyData } from './types';\nimport { IdentityPolicyValidator } from './validator';\n\nexport class IdentityPolicyEvaluator implements IPolicyEvaluator {\n protected validator : IdentityPolicyValidator;\n\n protected dataValidator : PolicyIdentityDataValidator;\n\n constructor() {\n this.validator = new IdentityPolicyValidator();\n this.dataValidator = new PolicyIdentityDataValidator();\n }\n\n requires() : string[] {\n return [BuiltInPolicyType.IDENTITY];\n }\n\n async accessData(ctx: PolicyEvaluationContext) : Promise<IdentityPolicyData | null> {\n if (!ctx.data.has('identity')) {\n return null;\n }\n\n if (ctx.data.isValidated('identity')) {\n return ctx.data.get<IdentityPolicyData>('identity');\n }\n\n const data = await this.dataValidator.run(ctx.data.get('identity'));\n\n ctx.data.set('identity', data);\n ctx.data.setValidated('identity');\n\n return data;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n const data = await this.accessData(ctx);\n if (!data) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property identity is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n if (!policy.types || policy.types.length === 0) {\n // Empty types is a configuration shorthand for \"no type\n // restriction\" — every identity passes. Do NOT apply `invert`;\n // inverting an empty config would silently deny all identities,\n // which is almost never the user's intent.\n return { success: true };\n }\n\n const typeAllowed = policy.types.includes(data.type);\n if (typeAllowed) {\n return { success: maybeInvertPolicyOutcome(typeAllowed, policy.invert) };\n }\n\n return {\n success: maybeInvertPolicyOutcome(typeAllowed, policy.invert),\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.EVALUATION_DENIED,\n message: `The type ${data.type} is not covered by the policy configuration`,\n path: ctx.path,\n }),\n ],\n };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport { DecisionStrategy } from '@authup/kit';\nimport { RealmScope } from '../../../permission/realm-scope';\nimport type { RealmMatchPolicy } from './types';\n\nexport class RealmMatchPolicyValidator extends Container<RealmMatchPolicy> {\n override initialize() {\n super.initialize();\n\n this.mount(\n 'decisionStrategy',\n createValidator(\n z.enum(DecisionStrategy)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'attributeName',\n createValidator(\n z.string()\n .min(3)\n .or(z.array(z.string().min(3)))\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n this.mount(\n 'attributeNameStrict',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n this.mount(\n 'attributeNullMatchAll',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'scope',\n createValidator(\n z.enum(RealmScope)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport {\n eq, \n inArray, \n nin, \n not, \n or,\n} from '@rapiq/core';\nimport { DecisionStrategy, hasOwnProperty } from '@authup/kit';\nimport { RealmScope, normalizeRealmScope, realmScopeMatches } from '../../../permission/realm-scope';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { AttributesPolicyEvaluator } from '../attributes';\nimport { BuiltInPolicyType } from '../constants';\nimport { IdentityPolicyEvaluator } from '../identity';\nimport { RealmMatchPolicyValidator } from './validator';\n\nexport class RealmMatchPolicyEvaluator implements IPolicyEvaluator {\n protected validator : RealmMatchPolicyValidator;\n\n protected identityEvaluator: IdentityPolicyEvaluator;\n\n protected attributesEvaluator : AttributesPolicyEvaluator;\n\n constructor() {\n this.validator = new RealmMatchPolicyValidator();\n this.identityEvaluator = new IdentityPolicyEvaluator();\n this.attributesEvaluator = new AttributesPolicyEvaluator();\n }\n\n requires(value: Record<string, any>) : string[] {\n // SCOPE MODE: the resource realm key (REALM_MATCH) is deliberately NOT\n // required — an absent key is the documented neutral-pass (gate checks /\n // realm-less resources), so requiring it would wrongly pend those runs.\n if (value.scope) {\n return [BuiltInPolicyType.IDENTITY];\n }\n\n return [BuiltInPolicyType.IDENTITY, BuiltInPolicyType.ATTRIBUTES];\n }\n\n /**\n * Condition form over the row's realm column, with the actor realm baked in\n * (mirrors `realmScopeMatches` / the attribute-mode match). Exactness holds for\n * row-shaped data where the referenced field exists (DB rows) — the object-bag\n * \"key absent → neutral-pass\" case has no SQL counterpart. Lowerable configs:\n * scope mode (field = single-string `attributeName`, default `realmId` — scope-mode\n * EVALUATION ignores `attributeName`, lowering reuses it as the column override),\n * and strict attribute mode with a single explicit `attributeName`. Everything\n * else (multi-key / default-key CONSENSUS, non-strict key expansion) is\n * row-shape-dependent and stays a post-check.\n */\n async toCondition(value: Record<string, any>, ctx: PolicyEvaluationContext) : Promise<ICondition | null> {\n let policy;\n try {\n policy = await this.validator.run(value);\n } catch {\n return null;\n }\n\n const identity = await this.identityEvaluator.accessData(ctx);\n if (!identity) {\n return null;\n }\n\n const realmId = identity.realmId ?? null;\n\n if (policy.scope) {\n const scope = normalizeRealmScope(policy.scope);\n const field = typeof policy.attributeName === 'string' ?\n policy.attributeName :\n 'realmId';\n\n let condition : ICondition;\n if (scope === RealmScope.ANY) {\n // constant-true: nin([]) matches everything (rapiq ConstantPlan)\n condition = nin(field, []);\n } else {\n // The lowered column (default `realmId`) holds realm IDs — the resource\n // realm is stamped from `entity.realmId`\n // (AbstractEntityService.resourceRealmMatch), so the WHERE match compares\n // that ID column against the actor's realm ID. The realm NAME is\n // deliberately NOT pushed here: it never appears in a realmId column and\n // would bind a non-uuid literal that postgres/mysql reject against a uuid\n // column (the sqlite-only test suite masks this, since sqlite is untyped).\n // Settled evaluation keeps the name-equality leniency for a name-stamped\n // resource SCALAR — which has no row-column counterpart, so parity holds\n // for realistic row-shaped data (see the exactness caveat above).\n const terms : ICondition[] = [];\n if (realmId !== null && scope !== RealmScope.NONE) {\n terms.push(eq(field, realmId));\n }\n if (scope === RealmScope.OWN_OR_NULL && (realmId !== null || identity.realmName != null)) {\n terms.push(eq(field, null));\n }\n\n if (terms.length === 0) {\n // no reach / realm-less actor with no null branch — constant-false\n condition = inArray(field, []);\n } else if (terms.length === 1) {\n condition = terms[0]!;\n } else {\n condition = or(...terms);\n }\n }\n\n return policy.invert ? not(condition) : condition;\n }\n\n if (\n typeof policy.attributeName !== 'string' ||\n (policy.attributeNameStrict ?? true) === false\n ) {\n return null;\n }\n\n // Mirrors the match loop's strict equality: `attributeValue === identity.realmId`\n // — an identity carrying an explicit `realmId: null` matches null-valued rows\n // (only an UNDEFINED identity value never matches a DB value, so it drops out).\n const key = policy.attributeName;\n const terms : ICondition[] = [];\n if (policy.attributeNullMatchAll) {\n terms.push(eq(key, null));\n }\n if (identity.realmId !== undefined) {\n terms.push(eq(key, identity.realmId));\n }\n if (identity.realmName !== undefined) {\n terms.push(eq(key, identity.realmName));\n }\n\n if (terms.length === 0) {\n return policy.invert ? nin(key, []) : inArray(key, []);\n }\n\n const condition = terms.length === 1 ? terms[0]! : or(...terms);\n return policy.invert ? not(condition) : condition;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n const identity = await this.identityEvaluator.accessData(ctx);\n if (!identity) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property identity is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n // SCOPE MODE: coarse, actor-relative realm reach (the realmScope mechanism lives\n // here). The resource realm is supplied under the REALM_MATCH data key. Key-PRESENCE\n // is the discriminator: an ABSENT realm neutral-passes (gate check / realm-less\n // resource), while a present `null` (global resource) is matched (and `own` correctly\n // denies it). Runs BEFORE the attributes-required guard below, since junction / gate\n // inputs need not carry ATTRIBUTES.\n if (policy.scope) {\n if (!ctx.data || !ctx.data.has(BuiltInPolicyType.REALM_MATCH)) {\n // Non-evaluation (no resource realm) — neutral pass, no `invert`,\n // mirroring the attribute-mode non-evaluation pass below. For a\n // query-build caller (`withConditions`) the resource realm IS the\n // unknown row column, so the reach pends with its condition form\n // instead of neutral-passing.\n if (ctx.withConditions) {\n const condition = await this.toCondition(value, ctx);\n return {\n success: false,\n pending: true,\n ...(condition ? { condition } : {}),\n };\n }\n\n return { success: true };\n }\n\n const resourceRealm = ctx.data.get<string | string[] | null>(BuiltInPolicyType.REALM_MATCH);\n return {\n success: maybeInvertPolicyOutcome(\n realmScopeMatches(\n policy.scope,\n resourceRealm ?? null,\n identity.realmId,\n identity.realmName,\n ),\n policy.invert,\n ),\n };\n }\n\n const attributes = await this.attributesEvaluator.accessData(ctx);\n if (!attributes) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property attributes is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n let keys : string[];\n if (policy.attributeName) {\n if (Array.isArray(policy.attributeName)) {\n keys = policy.attributeName;\n } else {\n keys = [policy.attributeName];\n }\n } else {\n keys = [\n 'realm_id',\n 'realm_name',\n 'realmId',\n 'realmName',\n ];\n\n policy.decisionStrategy = DecisionStrategy.CONSENSUS;\n }\n\n const attributeNameStrict = policy.attributeNameStrict ?? true;\n if (!attributeNameStrict) {\n const resourceKeys = Object.keys(attributes);\n const keysToAdd : string[] = [];\n for (const resourceKey of resourceKeys) {\n let contains : boolean = false;\n\n for (const key of keys) {\n if (\n resourceKey !== key &&\n resourceKey.includes(key)\n ) {\n contains = true;\n break;\n }\n }\n\n if (contains) {\n keysToAdd.push(resourceKey);\n }\n }\n\n if (keysToAdd.length > 0) {\n keys.push(...keysToAdd);\n }\n }\n\n let count = 0;\n let evaluated = false;\n\n for (const key of keys) {\n if (!hasOwnProperty(attributes, key)) {\n continue;\n }\n\n evaluated = true;\n\n let outcome : boolean = false;\n\n const attributeValue = attributes[key];\n\n if (\n (attributeValue === null && policy.attributeNullMatchAll) ||\n attributeValue === identity.realmId ||\n attributeValue === identity.realmName\n ) {\n outcome = true;\n }\n\n if (outcome) {\n if (policy.decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n count++;\n } else {\n if (policy.decisionStrategy === DecisionStrategy.UNANIMOUS) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n\n count--;\n }\n }\n\n if (!evaluated) {\n // No realm key found in attributes — the policy's match logic\n // didn't run. This is a \"non-evaluation\", not an outcome; treat\n // as a neutral pass without applying `invert`. Inverting here\n // would conflate \"policy doesn't apply\" with \"policy denies\".\n return { success: true };\n }\n\n return { success: maybeInvertPolicyOutcome(count > 0, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { PermissionBindingPolicy } from './types';\n\nexport class PermissionBindingPolicyValidator extends Container<PermissionBindingPolicy> {\n override initialize() {\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { and, not, or } from '@rapiq/core';\nimport type { Issue } from '@ebec/core';\nimport type { PermissionPolicyBinding, PermissionPolicyBindingAggregated } from '../../../permission/types';\nimport { aggregatePermissionPolicyBindings } from '../../../permission/helpers';\nimport { RealmScope, normalizeRealmScope } from '../../../permission/realm-scope';\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { PolicyEngine } from '../../engine';\nimport type { PolicyWithType } from '../../types';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { PolicyIssueCode, definePolicyIssueItem } from '../../issue';\nimport { BuiltInPolicyType } from '../constants';\nimport type { IdentityPolicyData } from '../identity';\nimport { IdentityPolicyEvaluator } from '../identity';\nimport { RealmMatchPolicyEvaluator } from '../realm-match';\nimport { PermissionBindingPolicyValidator } from './validator';\n\ntype IdentityPermissionProvider = {\n getFor(identity: IdentityPolicyData): Promise<PermissionPolicyBinding[]>,\n};\n\nfunction containsPermissionBinding(policy: PolicyWithType) : boolean {\n if (policy.type === BuiltInPolicyType.PERMISSION_BINDING) {\n return true;\n }\n\n // only a composite evaluates its children, and the projection a consumer\n // walks (`containsBindingCheck`) keeps `children` on a composite alone\n if (policy.type !== BuiltInPolicyType.COMPOSITE) {\n return false;\n }\n\n const children = policy.children as unknown;\n\n return Array.isArray(children) &&\n children.some((child) => !!child && typeof child === 'object' && containsPermissionBinding(child));\n}\n\nexport class IdentityPermissionBindingPolicyEvaluator implements IPolicyEvaluator {\n protected validator : PermissionBindingPolicyValidator;\n\n protected identityEvaluator: IdentityPolicyEvaluator;\n\n protected realmMatchEvaluator : RealmMatchPolicyEvaluator;\n\n protected identityPermissionProvider: IdentityPermissionProvider;\n\n constructor(identityPermissionProvider: IdentityPermissionProvider) {\n this.validator = new PermissionBindingPolicyValidator();\n this.identityEvaluator = new IdentityPolicyEvaluator();\n this.realmMatchEvaluator = new RealmMatchPolicyEvaluator();\n this.identityPermissionProvider = identityPermissionProvider;\n }\n\n requires() : string[] {\n // IDENTITY is deliberately NOT declared: a missing identity must stay a\n // settled DATA_MISSING deny (fail-closed) so a scope-restricted or anonymous\n // bearer still fails the pre-gate through system.default — pending would be\n // permitted there.\n return [BuiltInPolicyType.PERMISSION_BINDING];\n }\n\n async accessData(ctx: PolicyEvaluationContext) : Promise<PermissionPolicyBindingAggregated | null> {\n if (!ctx.data.has(BuiltInPolicyType.PERMISSION_BINDING)) {\n return null;\n }\n\n if (ctx.data.isValidated(BuiltInPolicyType.PERMISSION_BINDING)) {\n return ctx.data.get(BuiltInPolicyType.PERMISSION_BINDING);\n }\n\n const data = ctx.data.get<PermissionPolicyBindingAggregated>(BuiltInPolicyType.PERMISSION_BINDING);\n\n ctx.data.set(BuiltInPolicyType.PERMISSION_BINDING, data);\n ctx.data.setValidated(BuiltInPolicyType.PERMISSION_BINDING);\n\n return data;\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n const policy = await this.validator.run(value);\n\n const identity = await this.identityEvaluator.accessData(ctx);\n if (!identity) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property identity is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n const binding = await this.accessData(ctx);\n if (!binding) {\n return {\n success: false,\n issues: [\n definePolicyIssueItem({\n code: PolicyIssueCode.DATA_MISSING,\n message: 'The data property permission is missing',\n path: ctx.path,\n }),\n ],\n };\n }\n\n const identityBindings = await this.identityPermissionProvider.getFor(identity)\n .then((bindings) => bindings.filter((item) => {\n if (item.permission.name !== binding.permission.name) {\n return false;\n }\n\n return (binding.permission.realmId ?? null) === (item.permission.realmId ?? null) &&\n (binding.permission.clientId ?? null) === (item.permission.clientId ?? null);\n }));\n\n if (identityBindings.length === 0) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n\n const [aggr] = aggregatePermissionPolicyBindings(identityBindings);\n if (!aggr) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n\n // identityBindings is filtered to a single (name, realm_id, client_id) key, so the\n // aggregate yields exactly one entry whose `grants` are the actor's per-grant\n // (realm_scope, policy) disjunction terms; access is the DISJUNCTION over them:\n // ∃ grant . realmScopeMatches(grant.realmScope, resource) ∧ (grant.policy passes)\n // Pairing each grant's realm reach with its OWN policy is what fixes both the mixed\n // policy-free + policy-bound UNDER-grant (a policy-free `own` grant must not mask a\n // policy-bound `any` grant's wider reach) and the symmetric OVER-grant (an `own`\n // grant's passing policy must not ride an `any` grant's wider reach).\n const issues : Issue[] = [];\n const pendingIssues : Issue[] = [];\n const conditions : ICondition[] = [];\n let pending = false;\n let lowerable = true;\n for (const grant of aggr.grants) {\n // Realm reach (coarse, actor-relative) — a SEPARATE factor from the grant's\n // policy, ANDed with it. The realm-match evaluator runs in SCOPE MODE: it reads the\n // resource realm from ctx.data[REALM_MATCH] (fallback ATTRIBUTES.realmId) and\n // neutral-passes when absent (preEvaluate / gate checks / realm-less resources) —\n // key-PRESENCE is the discriminator. Invoked DIRECTLY (not via PolicyEngine) so\n // the reach factor can never be skipped by a caller's include/exclude filters or\n // deferred by the engine's data-availability gate.\n //\n // Under `withConditions` (query-build) with no resource realm present, the\n // reach PENDS with its condition form over the row's realm column instead of\n // neutral-passing — `any` stays unrestricted and `none` reaches nothing, so\n // neither pollutes the composed WHERE with constant terms.\n let reachCondition : ICondition | null = null;\n const realmOutcome = await this.realmMatchEvaluator.evaluate(\n // `attributeName` is read by scope mode only while LOWERING (it names the\n // row column the reach binds); settled evaluation takes the resource realm\n // from the `realmMatch` data key, so passing it cannot move an evaluate()\n // outcome. It is what lets a junction gate on its owner-realm key.\n { scope: grant.realmScope, attributeName: ctx.realmAttributeName },\n ctx,\n );\n if (realmOutcome.pending) {\n const scope = normalizeRealmScope(grant.realmScope);\n if (scope === RealmScope.NONE) {\n continue;\n }\n\n if (scope !== RealmScope.ANY) {\n if (!realmOutcome.condition) {\n pending = true;\n lowerable = false;\n continue;\n }\n\n reachCondition = realmOutcome.condition;\n }\n } else if (!realmOutcome.success) {\n continue;\n }\n\n if (!grant.policy) {\n if (!reachCondition) {\n // Reach matches and this grant carries no further restriction.\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n // Reach is the grant's only restriction — a pure condition term.\n conditions.push(reachCondition);\n pending = true;\n continue;\n }\n\n // A grant policy carrying a binding node re-enters this evaluator with the\n // same data, which loads the same grants and evaluates the same tree again,\n // without bound (issue #3633). The consumer side drops such a grant\n // (`containsBindingCheck`); the term settles false here so the two agree.\n if (containsPermissionBinding(grant.policy)) {\n issues.push(definePolicyIssueItem({\n code: PolicyIssueCode.INVALID,\n message: 'A grant policy must not evaluate the permission binding.',\n path: ctx.path,\n }));\n\n continue;\n }\n\n // Missing evaluators is a misconfiguration: let the engine fail CLOSED with a\n // surfaced POLICY_EVALUATOR_NOT_FOUND issue (new PolicyEngine(undefined) defaults\n // to an empty registry, so grant.policy resolves to no evaluator) rather than\n // swallowing the grant with a silent issue-less deny.\n const engine = new PolicyEngine(ctx.evaluators);\n const outcome = await engine.evaluate(grant.policy, {\n ...ctx,\n path: [\n ...(ctx.path || []),\n ],\n });\n\n if (outcome.success) {\n if (!reachCondition) {\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n\n conditions.push(reachCondition);\n pending = true;\n continue;\n }\n\n // A PENDING junction policy (required data key absent — e.g. an ATTRIBUTES\n // policy at the pre-gate) leaves this grant term UNKNOWN, not failed: the\n // grant could still pass once the data arrives, so it must not settle the\n // disjunction to false.\n if (outcome.pending) {\n pending = true;\n\n // A caller that names its realm column has told us the row shape is not the\n // default one, and nothing rebases a GRANT policy's own condition onto it.\n // Authup's own junction reads are the case that proves it: the policy is the\n // operator's, written against the ENTITY the permission names, so lowering it\n // emits SQL over columns `auth_role_permissions` and its siblings do not have.\n // We cannot tell a row shape that does carry those fields from one that does\n // not, so refuse the class: the caller falls back to the per-row `post` branch,\n // which evaluates the same policy against the real attributes and reaches the\n // identical verdict wherever the pushdown would not have crashed. The grant's\n // REACH is unaffected — it is built above from the column the caller named, so\n // the policy-free grants that dominate real deployments still push down.\n if (ctx.withConditions && outcome.condition && !ctx.realmAttributeName) {\n conditions.push(\n reachCondition ?\n and(reachCondition, outcome.condition) :\n outcome.condition,\n );\n } else {\n lowerable = false;\n }\n\n if (outcome.issues) {\n pendingIssues.push(...outcome.issues);\n }\n\n continue;\n }\n\n if (outcome.issues) {\n issues.push(...outcome.issues);\n }\n }\n\n // No grant term settled true. If some term is still pending, the disjunction is\n // pending — deliberately uninverted (unknown stays unknown under negation). The\n // condition form composes the grant terms as a disjunction, all-or-nothing: a\n // single non-expressible grant term makes the whole binding non-expressible\n // (pushing a partial OR would wrongly exclude rows).\n if (pending) {\n const result : PolicyEvaluationResult = {\n success: false,\n pending: true,\n issues: pendingIssues,\n };\n\n if (lowerable && ctx.withConditions && conditions.length > 0) {\n const condition = conditions.length === 1 ?\n conditions[0]! :\n or(...conditions);\n result.condition = policy.invert ? not(condition) : condition;\n }\n\n return result;\n }\n\n // No grant term satisfied (reach ∧ policies). Apply `invert` ONCE to the aggregated\n // disjunction outcome — never per term, which would corrupt the quantifier.\n const success = maybeInvertPolicyOutcome(false, policy.invert);\n return {\n success,\n issues: success ? [] : issues,\n };\n }\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants';\nimport { PermissionBindingPolicyValidator } from './validator';\n\nexport class PermissionBindingPolicyEvaluator implements IPolicyEvaluator {\n protected validator: PermissionBindingPolicyValidator;\n\n constructor() {\n this.validator = new PermissionBindingPolicyValidator();\n }\n\n requires() : string[] {\n // IDENTITY is deliberately NOT declared: a missing identity must stay a\n // settled deny (fail-closed), never a pending the pre-gate would permit.\n return [BuiltInPolicyType.PERMISSION_BINDING];\n }\n\n async evaluate(value: Record<string, any>): Promise<PolicyEvaluationResult> {\n const policy = await this.validator.run(value);\n\n // todo: this must be changed when the permission-checker not only checks owned permissions.\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport enum TimePolicyInterval {\n DAILY = 'daily',\n WEEKLY = 'weekly',\n MONTHLY = 'monthly',\n YEARLY = 'yearly',\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TimePolicyInterval } from './constants';\n\nexport function isIntervalForDayOfWeek(\n interval: string,\n) {\n return interval === TimePolicyInterval.WEEKLY ||\n interval === TimePolicyInterval.MONTHLY ||\n interval === TimePolicyInterval.YEARLY;\n}\n\nexport function isIntervalForDayOfMonth(\n interval: string,\n) {\n return interval === TimePolicyInterval.MONTHLY ||\n interval === TimePolicyInterval.YEARLY;\n}\n\nexport function isIntervalForDayOfYear(\n interval: string,\n) {\n return interval === TimePolicyInterval.YEARLY;\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createValidator } from '@validup/zod';\nimport { Container } from 'validup';\nimport { z } from 'zod';\nimport type { TimePolicy } from './types';\nimport { TimePolicyInterval } from './constants';\n\nexport class TimePolicyValidator extends Container<TimePolicy> {\n override initialize() {\n super.initialize();\n\n this.mount('dayOfWeek', createValidator(\n z.number()\n .min(0).max(6)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('dayOfMonth', createValidator(\n z.number()\n .min(1)\n .max(31)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('dayOfYear', createValidator(\n z.number()\n .min(1)\n .max(365)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n\n this.mount('start', createValidator(\n z.date()\n .or(z.iso.datetime())\n .or(z.iso.time())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n this.mount('end', createValidator(\n z.date()\n .or(z.iso.datetime())\n .or(z.iso.time())\n .or(z.number())\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ));\n\n this.mount(\n 'interval',\n createValidator(\n z.enum(TimePolicyInterval)\n .or(z.null())\n .or(z.undefined())\n .optional(),\n ),\n );\n\n this.mount(\n 'invert',\n createValidator(\n z.boolean()\n .or(z.undefined())\n .or(z.null())\n .optional(),\n ),\n );\n }\n}\n","/*\n * Copyright (c) 2024-2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { IPolicyEvaluator, PolicyEvaluationContext, PolicyEvaluationResult } from '../../evaluation';\nimport { maybeInvertPolicyOutcome } from '../../helpers';\nimport { BuiltInPolicyType } from '../constants';\nimport { isIntervalForDayOfMonth, isIntervalForDayOfWeek, isIntervalForDayOfYear } from './helpers';\nimport type { TimePolicy } from './types';\nimport { TimePolicyValidator } from './validator';\n\nconst timeRegex = /^(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d)?$/;\n\nfunction normalizeDate(input: Date, dateRef?: Date) {\n const date = dateRef ? new Date(dateRef) : new Date();\n date.setHours(input.getHours(), input.getMinutes());\n\n return date;\n}\n\nfunction toDate(\n input: Date | string | number,\n dateRef?: Date,\n) : Date {\n if (typeof input === 'string') {\n if (timeRegex.test(input)) {\n const parts = input.split(':');\n\n const startHours = Number(parts[0]);\n const startMinutes = Number(parts[1]);\n const startSeconds = parts[2] !== undefined ? Number(parts[2]) : 0;\n\n if (\n Number.isFinite(startHours) &&\n Number.isFinite(startMinutes) &&\n Number.isFinite(startSeconds)\n ) {\n const date = dateRef ? new Date(dateRef) : new Date();\n date.setHours(startHours, startMinutes, startSeconds, 0);\n\n return date;\n }\n }\n\n return new Date(input);\n }\n\n if (typeof input === 'number') {\n return new Date(input);\n }\n\n return input;\n}\n\n/**\n * The next instant at which a time policy's verdict could change, seen from\n * `now`: today's start while it is ahead, the minute after today's end while\n * that is ahead, and the next local midnight, where the daily window moves on\n * and the day-of-week/month/year checks roll over. The earliest of those; a\n * policy with no constraint never changes.\n *\n * `normalizeDate` keeps the seconds and milliseconds of the instant it is\n * evaluated at and drops the policy's own, so the comparisons below are made\n * at minute precision: `now < start` stops holding at HH:MM:00.000 of the\n * start, and `now > end` starts holding at the following minute. Reading the\n * candidates off `normalizeDate` instead would report the seconds of this\n * evaluation, up to a minute after the verdict already flipped.\n */\nfunction nextTimeTransition(policy: TimePolicy, now: Date) : Date | undefined {\n const candidates : Date[] = [];\n const atMinute = (input: Date) => new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n input.getHours(),\n input.getMinutes(),\n );\n\n if (policy.start) {\n candidates.push(atMinute(toDate(policy.start, now)));\n }\n\n if (policy.end) {\n // One minute of ELAPSED time after the end, not the local wall-clock\n // minute after it: on a DST fall-back day the end can sit just before\n // the repeated hour, and `H:(M+1)` then names the second occurrence of\n // that hour while the evaluator already flips after the first one.\n candidates.push(new Date(atMinute(toDate(policy.end, now)).getTime() + 60_000));\n }\n\n if (policy.start || policy.end || policy.interval) {\n candidates.push(new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1));\n }\n\n let next : Date | undefined;\n for (const candidate of candidates) {\n if (\n candidate.getTime() > now.getTime() &&\n (!next || candidate.getTime() < next.getTime())\n ) {\n next = candidate;\n }\n }\n\n return next;\n}\n\nexport class TimePolicyEvaluator implements IPolicyEvaluator {\n protected validator : TimePolicyValidator;\n\n constructor() {\n this.validator = new TimePolicyValidator();\n }\n\n async evaluate(value: Record<string, any>, ctx: PolicyEvaluationContext): Promise<PolicyEvaluationResult> {\n // todo: catch errors + transform to issue(s)\n const policy = await this.validator.run(value);\n\n let now : Date;\n\n if (ctx.data.has(BuiltInPolicyType.TIME)) {\n if (ctx.data.isValidated(BuiltInPolicyType.TIME)) {\n now = ctx.data.get<Date>(BuiltInPolicyType.TIME);\n } else {\n // todo: run validator on attributes (isObject ...)\n now = toDate(ctx.data.get(BuiltInPolicyType.TIME));\n\n ctx.data.set(BuiltInPolicyType.TIME, now);\n ctx.data.setValidated(BuiltInPolicyType.TIME);\n }\n } else {\n now = new Date();\n\n // Only a verdict read off the real clock expires; a supplied time is fixed.\n if (ctx.transitions) {\n const next = nextTimeTransition(policy, now);\n if (next) {\n ctx.transitions.report(next);\n }\n }\n }\n\n if (policy.start) {\n const start = normalizeDate(toDate(policy.start, now), now);\n if (now < start) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (policy.end) {\n const end = normalizeDate(toDate(policy.end, now), now);\n if (now > end) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (policy.interval) {\n if (\n isIntervalForDayOfWeek(policy.interval) &&\n policy.dayOfWeek\n ) {\n if (now.getDay() !== policy.dayOfWeek) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (\n isIntervalForDayOfMonth(policy.interval) &&\n policy.dayOfMonth\n ) {\n if (now.getDate() !== policy.dayOfMonth) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n\n if (\n isIntervalForDayOfYear(policy.interval) &&\n policy.dayOfYear\n ) {\n const start = new Date(now.getFullYear(), 0, 0);\n const diff = (now.getTime() - start.getTime()) +\n ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);\n\n const oneDay = 1000 * 60 * 60 * 24;\n const dayOfYear = Math.floor(diff / oneDay);\n\n if (dayOfYear !== policy.dayOfYear) {\n return { success: maybeInvertPolicyOutcome(false, policy.invert) };\n }\n }\n }\n\n return { success: maybeInvertPolicyOutcome(true, policy.invert) };\n }\n}\n","/*\n * Copyright (c) 2025.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { PolicyWithType } from '../types';\nimport type { BuiltInPolicyTypeMap } from './types';\n\nexport function definePolicyWithType<\n K extends keyof BuiltInPolicyTypeMap,\n D extends BuiltInPolicyTypeMap<any>[K],\n>(\n type: K,\n data: D,\n) : PolicyWithType<D, K> {\n return {\n ...data,\n type,\n };\n}\n","/*\n * Copyright (c) 2026-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n AttributeNamesPolicyEvaluator,\n AttributeNamesPolicyValidator,\n AttributesPolicyEvaluator,\n AttributesPolicyValidator,\n BuiltInPolicyType,\n CompositePolicyEvaluator,\n CompositePolicyValidator,\n DatePolicyEvaluator,\n DatePolicyValidator,\n IdentityPolicyEvaluator,\n IdentityPolicyValidator,\n PermissionBindingPolicyEvaluator,\n PermissionBindingPolicyValidator,\n RealmMatchPolicyEvaluator,\n RealmMatchPolicyValidator,\n TimePolicyEvaluator,\n TimePolicyValidator,\n} from './built-in';\nimport type { PolicyValidators } from './types.ts';\n\nexport const PolicyDefaultEvaluators = {\n [BuiltInPolicyType.COMPOSITE]: new CompositePolicyEvaluator(),\n [BuiltInPolicyType.ATTRIBUTES]: new AttributesPolicyEvaluator(),\n [BuiltInPolicyType.ATTRIBUTE_NAMES]: new AttributeNamesPolicyEvaluator(),\n [BuiltInPolicyType.DATE]: new DatePolicyEvaluator(),\n [BuiltInPolicyType.IDENTITY]: new IdentityPolicyEvaluator(),\n [BuiltInPolicyType.PERMISSION_BINDING]: new PermissionBindingPolicyEvaluator(),\n [BuiltInPolicyType.REALM_MATCH]: new RealmMatchPolicyEvaluator(),\n [BuiltInPolicyType.TIME]: new TimePolicyEvaluator(),\n} as const;\n\n/**\n * The configuration validator of every built-in policy type, keyed like\n * `PolicyDefaultEvaluators`. It is what `projectAuthorizationPolicy` runs a\n * node through, so a type absent here cannot travel in the authorization\n * catalog. The registry is open like the evaluator one (#3635): spread it and\n * add a custom type's validator to let that type travel. It is frozen, since\n * a write into it would make the type projectable for every caller in the\n * process.\n */\nexport const PolicyDefaultValidators : Readonly<PolicyValidators> = Object.freeze({\n [BuiltInPolicyType.COMPOSITE]: new CompositePolicyValidator(),\n [BuiltInPolicyType.ATTRIBUTES]: new AttributesPolicyValidator(),\n [BuiltInPolicyType.ATTRIBUTE_NAMES]: new AttributeNamesPolicyValidator(),\n [BuiltInPolicyType.DATE]: new DatePolicyValidator(),\n [BuiltInPolicyType.IDENTITY]: new IdentityPolicyValidator(),\n [BuiltInPolicyType.PERMISSION_BINDING]: new PermissionBindingPolicyValidator(),\n [BuiltInPolicyType.REALM_MATCH]: new RealmMatchPolicyValidator(),\n [BuiltInPolicyType.TIME]: new TimePolicyValidator(),\n});\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { BuiltInPolicyType } from './built-in/constants';\nimport type { IdentityPolicyData } from './built-in/identity/types';\nimport { PolicyData } from './data';\n\n/**\n * Typed seed for a permission evaluation's {@link PolicyData} bag.\n *\n * The well-known context keys are value-typed, so construction is discoverable and a\n * wrong-typed value is a compile error. The trailing index signature keeps the bag **open** —\n * a third-party evaluator may supply its own key without any change to this published type\n * (the `access` evaluator set is deliberately extensible).\n */\nexport interface PolicyInput {\n [BuiltInPolicyType.IDENTITY]?: IdentityPolicyData;\n [BuiltInPolicyType.ATTRIBUTES]?: Record<string, any>;\n [BuiltInPolicyType.REALM_MATCH]?: string | string[] | null;\n [key: string]: any;\n}\n\n/**\n * Build a {@link PolicyData} bag from a typed {@link PolicyInput} seed. Well-known keys\n * (identity / attributes / realmMatch) are type-checked; unknown keys are accepted as-is.\n *\n * Prefer this over `new PolicyData({ ... })` at construction sites so the key vocabulary and\n * per-key value types live in one place.\n */\nexport function definePolicyData(input: PolicyInput = {}): PolicyData {\n return new PolicyData(input);\n}\n","/*\n * Copyright (c) 2021-2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { ICondition } from '@rapiq/core';\nimport { or } from '@rapiq/core';\nimport { ErrorCode } from '@authup/errors';\nimport type { Issue } from '@ebec/core';\nimport { defineIssueItem } from '@ebec/core';\nimport { DecisionStrategy } from '@authup/kit';\nimport type { BasePolicy, CompositePolicy, IPolicyEngine } from '../../policy';\nimport {\n BuiltInPolicyType,\n PolicyData,\n PolicyDefaultEvaluators,\n PolicyEngine,\n definePolicyEvaluationContext,\n definePolicyIssueGroup,\n} from '../../policy';\nimport { PermissionError } from '../error';\nimport type { IPermissionProvider } from '../provider';\n\nimport type { PermissionPolicyBindingAggregated } from '../types.ts';\nimport type {\n IPermissionEvaluator,\n PermissionCompileContext,\n PermissionCompileResult,\n PermissionEvaluationContext,\n PermissionEvaluatorOptions,\n} from './types.ts';\n\nexport class PermissionEvaluator implements IPermissionEvaluator {\n protected provider : IPermissionProvider;\n\n protected policyEngine : IPolicyEngine;\n\n protected clientId?: string | null;\n\n protected realmId?: string | null;\n\n // ----------------------------------------------\n\n constructor(options: PermissionEvaluatorOptions) {\n this.provider = options.provider;\n\n this.clientId = options.clientId || null;\n this.realmId = options.realmId || null;\n\n if (options.policyEngine) {\n this.policyEngine = options.policyEngine;\n } else {\n this.policyEngine = new PolicyEngine(PolicyDefaultEvaluators);\n }\n }\n\n // ----------------------------------------------\n\n protected async findOne(\n input: string,\n overrides: {\n realmId?: string | null,\n clientId?: string | null\n } = {},\n ) : Promise<PermissionPolicyBindingAggregated | null> {\n return this.provider.findOne({\n name: input,\n clientId: overrides.clientId ?? this.clientId,\n realmId: overrides.realmId ?? this.realmId,\n });\n }\n\n // ----------------------------------------------\n\n async evaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n if (!Array.isArray(ctx.name)) {\n await this.evaluate({\n ...ctx,\n name: [ctx.name],\n });\n return;\n }\n\n const { options = {} } = ctx;\n\n const decisionStrategy = options.decisionStrategy ??\n DecisionStrategy.UNANIMOUS;\n\n const issues : Issue[] = [];\n\n let count = 0;\n\n const dataBase = ctx.data || new PolicyData();\n\n for (const name of ctx.name) {\n const binding = await this.findOne(name, {\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n });\n if (!binding) {\n issues.push(defineIssueItem({\n code: ErrorCode.PERMISSION_NOT_FOUND,\n message: `The ${name} permission could not be resolved`,\n path: [name],\n }));\n\n if (decisionStrategy === DecisionStrategy.UNANIMOUS) {\n throw PermissionError.evaluationFailed(ctx.name, issues);\n }\n\n continue;\n }\n\n // The actor's grants for this permission form a disjunction: a single policy-free\n // grant is unrestricted, otherwise the permission passes iff ANY grant's policy\n // passes (AFFIRMATIVE). Each grant's policy already carries its own decisionStrategy\n // (a composite for multi-policy Layer-1 bindings, the raw policy for single).\n const grantPolicies = binding.grants\n .map((grant) => grant.policy)\n .filter((grantPolicy): grantPolicy is BasePolicy => !!grantPolicy);\n\n if (grantPolicies.length < binding.grants.length) {\n // some grant is policy-free => unrestricted\n if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return;\n }\n\n count++;\n\n continue;\n }\n\n const data = dataBase.clone();\n data.set(BuiltInPolicyType.PERMISSION_BINDING, binding);\n\n const compositePolicy : CompositePolicy = {\n type: BuiltInPolicyType.COMPOSITE,\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n children: grantPolicies,\n };\n\n const evaluationResult = await this.policyEngine.evaluate(\n compositePolicy,\n definePolicyEvaluationContext({\n include: options.policiesIncluded,\n exclude: options.policiesExcluded,\n transitions: options.transitions,\n data,\n }),\n );\n\n // A pending evaluation (missing data keys) is settled by the caller's\n // phase: the full evaluate denies (fail-closed default), the pre-gate\n // permits — the enriched-bag evaluate is the backstop.\n const passed = evaluationResult.success || (\n options.pendingPolicies === 'permit' &&\n !!evaluationResult.pending\n );\n\n if (passed) {\n if (decisionStrategy === DecisionStrategy.AFFIRMATIVE) {\n return;\n }\n\n count++;\n } else {\n issues.push(definePolicyIssueGroup({\n code: ErrorCode.PERMISSION_EVALUATION_FAILED,\n issues: evaluationResult.issues || [],\n message: `The ${binding.permission.name} permissions policy evaluation failed`,\n path: [binding.permission.name],\n }));\n\n if (decisionStrategy === DecisionStrategy.UNANIMOUS) {\n throw PermissionError.evaluationFailed(binding.permission.name, issues);\n }\n\n count--;\n }\n }\n\n if (count > 0) {\n return;\n }\n\n if (issues.length === 0) {\n throw PermissionError.deniedAll(ctx.name);\n } else {\n throw PermissionError.evaluationFailed(ctx.name, issues);\n }\n }\n\n async evaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return this.evaluate({\n ...ctx,\n options: {\n ...(ctx.options || {}),\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n },\n });\n }\n\n // ----------------------------------------------\n\n async preEvaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n // The pre-gate is DERIVED from data availability (issue #3286): policies whose\n // required data keys are absent from the bag stay pending and are permitted —\n // only a tree that settles false with the current bag denies. This replaces the\n // former hand-maintained type exclusion list (ATTRIBUTES / ATTRIBUTE_NAMES /\n // REALM_MATCH), whose mask-to-true encoding broke under `invert`.\n return this.evaluate({\n ...ctx,\n options: {\n ...(ctx.options || {}),\n pendingPolicies: 'permit',\n },\n });\n }\n\n async preEvaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return this.preEvaluate({\n ...ctx,\n options: {\n ...(ctx.options || {}),\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n },\n });\n }\n\n // ----------------------------------------------\n\n /**\n * Compile the permission's policy trees against the knowns bag into a\n * {@link PermissionCompileResult} — the query-build counterpart of\n * {@link evaluate} (issue #3286 phase 3). Runs the SAME evaluation walk with\n * `withConditions` enabled: policies that settle with the knowns settle here,\n * pending subtrees contribute their exact condition form. Multiple names are\n * a disjunction (any-of), so a single non-expressible name degrades the whole\n * compilation to `post` — pushing only some disjuncts would wrongly exclude\n * rows another name would admit.\n */\n async compile(ctx: PermissionCompileContext) : Promise<PermissionCompileResult> {\n const names = Array.isArray(ctx.name) ? ctx.name : [ctx.name];\n\n const dataBase = ctx.data || new PolicyData();\n\n const conditions : ICondition[] = [];\n let post = false;\n\n for (const name of names) {\n const binding = await this.findOne(name, {\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n });\n if (!binding) {\n // unresolvable permission — a settled-false disjunct, drops out\n continue;\n }\n\n const grantPolicies = binding.grants\n .map((grant) => grant.policy)\n .filter((grantPolicy): grantPolicy is BasePolicy => !!grantPolicy);\n\n if (grantPolicies.length < binding.grants.length) {\n // some grant is policy-free => unrestricted\n return { verdict: 'allow' };\n }\n\n const data = dataBase.clone();\n data.set(BuiltInPolicyType.PERMISSION_BINDING, binding);\n\n const compositePolicy : CompositePolicy = {\n type: BuiltInPolicyType.COMPOSITE,\n decisionStrategy: DecisionStrategy.AFFIRMATIVE,\n children: grantPolicies,\n };\n\n const evaluationResult = await this.policyEngine.evaluate(\n compositePolicy,\n definePolicyEvaluationContext({\n data,\n withConditions: true,\n realmAttributeName: ctx.realmAttributeName,\n }),\n );\n\n if (evaluationResult.success) {\n return { verdict: 'allow' };\n }\n\n if (evaluationResult.pending) {\n if (evaluationResult.condition) {\n conditions.push(evaluationResult.condition);\n } else {\n post = true;\n }\n }\n // settled false — the disjunct drops out\n }\n\n if (post) {\n return { verdict: 'post' };\n }\n\n if (conditions.length === 0) {\n return { verdict: 'deny' };\n }\n\n if (conditions.length === 1) {\n const [condition] = conditions;\n return { verdict: 'conditional', condition: condition! };\n }\n\n return { verdict: 'conditional', condition: or(...conditions) };\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { AuthupError, markInstanceof } from '@authup/errors';\n\nexport const AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE = Symbol.for('@authup/access/AuthorizationCatalogStaleError');\n\n/**\n * A grant references a definition or a policy the supplied catalog does not\n * carry: the caller's cached catalog predates the definition or the junction\n * row and must be refetched. A definition the catalog carries with\n * `policies: null`, and one whose tree this copy cannot project, are not\n * stale but unevaluable, and a grant of either is dropped.\n *\n * Recognize it with `isAuthorizationCatalogStaleError`, never `instanceof`:\n * this package is a plain caret dependency of several workspaces, so a\n * consumer tree may resolve two copies of it and turn the one recoverable\n * state into an unrecoverable one.\n */\nexport class AuthorizationCatalogStaleError extends AuthupError {\n constructor(message: string) {\n super({ message });\n\n this.name = 'AuthorizationCatalogStaleError';\n markInstanceof(this, AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { matchesInstanceof } from '@authup/errors';\nimport type { AuthorizationCatalogStaleError } from './error';\nimport { AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE } from './error';\n\n/**\n * Marker-only: the error carries no code of its own, and it never crosses a\n * wire boundary, so there is no shape to fall back to.\n */\nexport function isAuthorizationCatalogStaleError(input: unknown) : input is AuthorizationCatalogStaleError {\n return matchesInstanceof(input, AUTHORIZATION_CATALOG_STALE_ERROR_INSTANCE);\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueItem } from '@ebec/core';\nimport { DecisionStrategy } from '@authup/kit';\nimport { createValidator } from '@validup/zod';\nimport { Container, ValidupError } from 'validup';\nimport { z } from 'zod';\nimport { RealmScope } from '../realm-scope';\nimport type {\n AuthorizationCatalog,\n AuthorizationEvaluatorInput,\n AuthorizationGrant,\n} from './types';\n\nconst id = z.string().min(1);\nconst namespaceId = id.nullable();\n\n/**\n * A policy node as it travels. Deliberately LOOSE: every key beyond `type` is\n * that type's own configuration, and `projectAuthorizationPolicy` is what\n * validates it, by running the type's own validator. Mounting a node in a\n * validup container would strip every key the container does not mount, and\n * the whole configuration would go with it.\n */\nexport const authorizationPolicySchema = z.looseObject({ type: z.string().min(1) });\n\n/**\n * One permission definition. `policies` carries the ids of its\n * definition-layer trees, or `null` when the server could not project one.\n */\nexport const authorizationDefinitionSchema = z.object({\n name: z.string().min(1),\n realm_id: namespaceId,\n client_id: namespaceId,\n decision_strategy: z.enum(DecisionStrategy).nullable(),\n policies: z.array(id).nullable(),\n});\n\nexport const authorizationCatalogSchema = z.object({\n policies: z.record(id, authorizationPolicySchema),\n permissions: z.array(authorizationDefinitionSchema),\n});\n\n/**\n * One grant of the identity, as the introspection endpoints report it.\n * Whether a grant's policy ids are declared is checked against the catalog\n * the consumer holds, since the two travel separately.\n */\nexport const authorizationGrantSchema = z.object({\n name: z.string().min(1),\n realm_id: namespaceId.optional(),\n client_id: namespaceId.optional(),\n realm_scope: z.enum(RealmScope).nullish(),\n policies: z.array(id).nullish(),\n});\n\nexport const authorizationIdentitySchema = z.object({\n id: z.string().min(1),\n type: z.enum(['user', 'client']),\n realmId: z.string().nullish(),\n realmName: z.string().nullish(),\n clientId: z.string().nullish(),\n});\n\n/**\n * The whole input `createAuthorizationEvaluator` takes: the catalog\n * `GET /authorization` serves, the grants an introspection reports and the\n * identity it names. A validup container over zod mounts, the shape every\n * validator in this package uses, so a consumer can reuse or override one\n * member's rules instead of restating the document.\n */\nexport class AuthorizationEvaluatorInputValidator extends Container<AuthorizationEvaluatorInput> {\n override initialize() {\n super.initialize();\n\n this.mount('catalog', createValidator(authorizationCatalogSchema));\n this.mount('grants', createValidator(z.array(authorizationGrantSchema).optional()));\n this.mount('identity', createValidator(authorizationIdentitySchema.optional()));\n }\n}\n\nconst validator = new AuthorizationEvaluatorInputValidator();\n\nexport type AuthorizationEvaluatorInputParsed = {\n catalog: AuthorizationCatalog,\n grants: AuthorizationGrant[],\n identity: AuthorizationEvaluatorInput['identity'],\n};\n\n/**\n * Validate the evaluator's input, plus the two rules per-key validators\n * cannot express.\n *\n * Every id a definition names must be a key of `policies`: a dangling id\n * resolves to `undefined`, which reads as \"this layer carries no policy\", so\n * a catalog that merely omitted a tree would grant unrestricted access rather\n * than fail. The lookup is own-property only, so an id such as `constructor`\n * cannot be answered by a member of `Object.prototype`.\n *\n * And the identity and its grants travel together: grants without an identity\n * belong to nobody, while an identity without a grant list is the shape an\n * INACTIVE introspection produces (`permissions` is absent unless the\n * credential is active), which read as \"holds nothing\" would authorize every\n * definition that carries no binding check. An identity holding no grant says\n * so with an empty array.\n */\nexport async function parseAuthorizationEvaluatorInput(\n input: AuthorizationEvaluatorInput,\n) : Promise<AuthorizationEvaluatorInputParsed> {\n const identityGiven = typeof input.identity !== 'undefined';\n const grantsGiven = typeof input.grants !== 'undefined';\n if (!identityGiven && grantsGiven) {\n throw new ValidupError([defineIssueItem({\n message: 'Grants require the identity they belong to.',\n path: ['identity'],\n })]);\n }\n\n if (identityGiven && !grantsGiven) {\n throw new ValidupError([defineIssueItem({\n message: 'An identity requires its grant list; pass an empty array for an identity holding none.',\n path: ['grants'],\n })]);\n }\n\n // Detach: a later mutation of a cached HTTP response cannot widen grants\n // after validation (attribute queries carry arbitrary nested data).\n //\n // The cast is the container's boundary: its generic describes the INPUT,\n // whose wire members are `unknown` by design, while what a run returns is\n // what the mounted schemas accepted (the `parseThemeManifest` idiom).\n const {\n catalog, \n grants, \n identity, \n } = await validator.run(\n structuredClone(input) as Record<string, any>,\n ) as {\n catalog: AuthorizationCatalog,\n grants?: AuthorizationGrant[],\n identity?: AuthorizationEvaluatorInput['identity'],\n };\n\n for (const [i, definition] of catalog.permissions.entries()) {\n for (const [j, policyId] of (definition.policies ?? []).entries()) {\n if (Object.hasOwn(catalog.policies, policyId)) {\n continue;\n }\n\n throw new ValidupError([defineIssueItem({\n message: `The policy ${policyId} is not declared by the catalog.`,\n path: ['catalog', 'permissions', i, 'policies', j],\n })]);\n }\n }\n\n return {\n catalog,\n grants: grants ?? [],\n identity,\n };\n}\n\n/**\n * One verdict: the permission namespace and the requested realms it holds in.\n * A realm value is a realm key the caller itself supplied, or `null` for the\n * global rows, so nothing here is resolved or looked up.\n */\nexport const authorizationCheckPermissionSchema = z.object({\n name: z.string().min(1),\n realms: z.array(z.string().min(1).nullable()).min(1),\n});\n\nexport const authorizationCheckPermissionsSchema = z.array(authorizationCheckPermissionSchema);\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueItem } from '@ebec/core';\nimport { createValidator } from '@validup/zod';\nimport { Container, ValidupError } from 'validup';\nimport { authorizationCheckPermissionsSchema, authorizationIdentitySchema } from './schema';\nimport type { AuthorizationCheckEvaluatorInput, AuthorizationCheckPermissions } from './types';\n\n/**\n * The whole input `createAuthorizationCheckEvaluator` takes: the answer\n * `POST /authorization/check` served and the identity it belongs to. Same\n * validup-over-zod shape as the catalog's input, so a consumer can override\n * one member's rules instead of restating the answer.\n */\nexport class AuthorizationCheckEvaluatorInputValidator extends Container<AuthorizationCheckEvaluatorInput> {\n override initialize() {\n super.initialize();\n\n this.mount('permissions', createValidator(authorizationCheckPermissionsSchema));\n this.mount('identity', createValidator(authorizationIdentitySchema.optional()));\n }\n}\n\nconst checkValidator = new AuthorizationCheckEvaluatorInputValidator();\n\nexport type AuthorizationCheckEvaluatorInputParsed = {\n permissions: AuthorizationCheckPermissions,\n identity: AuthorizationCheckEvaluatorInput['identity'],\n};\n\n/**\n * Validate the check evaluator's input, plus the one rule a per-key validator\n * cannot express: a permission namespace appears at most once. Two entries for\n * one name would make the answer depend on which the consumer looked up first,\n * and the server emits one entry per name by construction.\n */\nexport async function parseAuthorizationCheckEvaluatorInput(\n input: AuthorizationCheckEvaluatorInput,\n) : Promise<AuthorizationCheckEvaluatorInputParsed> {\n // Detach for the reason the catalog's input is detached: a later mutation\n // of a cached HTTP response cannot widen verdicts after validation.\n const {\n permissions,\n identity,\n } = await checkValidator.run(\n structuredClone(input) as Record<string, any>,\n ) as {\n permissions: AuthorizationCheckPermissions,\n identity?: AuthorizationCheckEvaluatorInput['identity'],\n };\n\n const seen = new Set<string>();\n for (const [i, permission] of permissions.entries()) {\n if (seen.has(permission.name)) {\n throw new ValidupError([defineIssueItem({\n message: `The permission ${permission.name} is answered more than once.`,\n path: ['permissions', i, 'name'],\n })]);\n }\n\n seen.add(permission.name);\n }\n\n return { permissions, identity };\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * The node a policy tree travels as when the server withholds it, because the\n * caller's realm reach does not cover the row it was read from.\n *\n * It is deliberately a type no consumer can project: `projectAuthorizationPolicy`\n * refuses it, which is already the state a definition referencing it denies\n * through and a grant naming it is dropped through, so withholding a body needs\n * no rule of its own on the consumer side. That is a contract between the two\n * halves rather than a server detail, which is why it is declared HERE, next to\n * the projection that has to keep refusing it, and pinned by this package's own\n * test.\n */\nexport const AUTHORIZATION_POLICY_WITHHELD_TYPE = 'withheld';\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { defineIssueItem, prefixIssuePath } from '@ebec/core';\nimport { createValidator } from '@validup/zod';\nimport { Container, ValidupError, isValidupError } from 'validup';\nimport { z } from 'zod';\nimport type { PolicyValidators } from '../../policy';\nimport { BuiltInPolicyType, PolicyDefaultValidators } from '../../policy';\nimport { AUTHORIZATION_POLICY_WITHHELD_TYPE } from './constants';\nimport type { AuthorizationPolicy } from './types';\n\ntype AuthorizationPolicyHead = {\n type: string,\n children?: unknown[],\n};\n\n/**\n * The two keys a node carries whatever its type is. Deliberately NOT the whole\n * node: every other key is that type's own configuration, which the type's own\n * validator reads, and a container strips every key it does not mount.\n */\nclass AuthorizationPolicyHeadValidator extends Container<AuthorizationPolicyHead> {\n override initialize() {\n super.initialize();\n\n this.mount('type', createValidator(z.string().min(1)));\n this.mount('children', createValidator(z.array(z.unknown()).optional()));\n }\n}\n\n/**\n * The one definition of what a policy looks like on the wire, used by the server\n * to build a document and by the consumer to validate one. A node is the OUTPUT\n * of its type's validator (validup strips every unmounted key, so entity columns\n * such as `id`, `name`, `builtIn` or `createdAt` never travel), plus its type\n * and, for a composite, its projected children.\n *\n * The type set is the `validators` registry, `PolicyDefaultValidators` unless\n * the caller hands another (#3635): a type the registry lacks is refused, so\n * the server and a consumer that register the same custom type let it travel,\n * and one that does not denies it. The withheld node is refused whatever the\n * registry says, since projecting it would evaluate a tree the caller was not\n * allowed to see.\n *\n * Every refusal is a `ValidupError`, the node's head and the type's own\n * validator alike, and a child's issues are rebased onto the position it sits\n * at, so one message names the node in the tree that is wrong.\n */\nexport async function projectAuthorizationPolicy(\n input: unknown,\n validators: PolicyValidators = PolicyDefaultValidators,\n) : Promise<AuthorizationPolicy> {\n const headValidator = new AuthorizationPolicyHeadValidator();\n\n const project = async (value: unknown) : Promise<AuthorizationPolicy> => {\n const head = await headValidator.run(value as Record<string, any>);\n const validator = head.type !== AUTHORIZATION_POLICY_WITHHELD_TYPE && Object.hasOwn(validators, head.type) ?\n validators[head.type] :\n undefined;\n if (!validator) {\n throw new ValidupError([defineIssueItem({\n message: `The policy type ${head.type} is not supported.`,\n path: ['type'],\n })]);\n }\n const validated = await validator.run(value as Record<string, any>) as Record<string, unknown>;\n\n const output : AuthorizationPolicy = { ...validated, type: head.type };\n for (const key of Object.keys(output)) {\n if (typeof output[key] === 'undefined') {\n delete output[key];\n }\n }\n\n if (head.type === BuiltInPolicyType.COMPOSITE) {\n output.children = await Promise.all(\n (head.children ?? []).map((child, index) => projectChild(child, index)),\n );\n } else {\n delete output.children;\n }\n\n return output;\n };\n\n const projectChild = async (child: unknown, index: number) : Promise<AuthorizationPolicy> => {\n try {\n return await project(child);\n } catch (e) {\n if (isValidupError(e)) {\n throw new ValidupError(e.issues.map((issue) => prefixIssuePath(issue, ['children', index])));\n }\n\n throw e;\n }\n };\n\n return project(input);\n}\n\n/**\n * Whether a projected tree evaluates the permission binding at any depth. A\n * grant policy carrying one would re-enter its own permission's grants, so\n * `createAuthorizationEvaluator` drops the grant that names it and evaluates\n * the permission from the rest. Its one caller is that consumer: the tree is\n * legal in a definition, where the binding check is what reach is enforced\n * by, so the producer carries it and only the grant side is refused.\n */\nexport function containsBindingCheck(policy: AuthorizationPolicy) : boolean {\n if (policy.type === BuiltInPolicyType.PERMISSION_BINDING) {\n return true;\n }\n\n return (policy.children ?? []).some((child) => containsBindingCheck(child));\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { type Issue, defineIssueItem, prefixIssuePath } from '@ebec/core';\nimport { InternalError } from '@authup/errors';\nimport { buildIssuesForZodError } from '@validup/zod';\nimport { ValidupError } from 'validup';\nimport { z } from 'zod';\nimport type { BasePolicy } from '../../policy';\nimport {\n BuiltInPolicyType,\n IdentityPermissionBindingPolicyEvaluator,\n PolicyData,\n PolicyDefaultEvaluators,\n PolicyEngine,\n} from '../../policy';\nimport type {\n IPermissionEvaluator,\n PermissionCompileContext,\n PermissionCompileResult,\n PermissionEvaluationContext,\n} from '../evaluator';\nimport { PermissionEvaluator } from '../evaluator';\nimport { PermissionError } from '../error';\nimport { buildPermissionKey } from '../helpers';\nimport { PermissionMemoryProvider } from '../provider';\nimport { normalizeRealmScope } from '../realm-scope';\nimport type { BasePermission, PermissionPolicyBinding } from '../types';\nimport { AuthorizationCatalogStaleError } from './error';\nimport { containsBindingCheck, projectAuthorizationPolicy } from './policy';\nimport { parseAuthorizationCheckEvaluatorInput } from './check-schema';\nimport { parseAuthorizationEvaluatorInput } from './schema';\nimport type {\n AuthorizationCheckEvaluatorInput,\n AuthorizationEvaluatorInput,\n AuthorizationEvaluatorOptions,\n AuthorizationPolicy,\n} from './types';\n\n/**\n * Every value `realmScopeMatches` decides, and nothing it would have to guess\n * at (#3636): a realm key, `null` for a global row, or a list of either for a\n * row spanning several realms. An empty key and an empty list are legal and\n * DENY there (no identity's realm is the empty string, and the empty set is\n * fail-closed), so refusing them here would make the consumer the one side\n * that errors where the server answers. `undefined` stays refused: the server\n * coerces it to `null`, which reads as a global row, and a caller passing an\n * absent column should hear about it rather than reach the global rows.\n */\nconst realmMatchSchema = z.union([z.string(), z.array(z.string().nullable()), z.null()]);\n\n/**\n * Every refusal of the DOCUMENT is a `ValidupError` carrying the path of the\n * member at fault, the shape `parseAuthorizationEvaluatorInput` raises and the\n * one a consumer can render. A bare `Error` carries neither a code nor a path,\n * so nothing downstream can normalize it.\n */\nfunction refuseDocument(message: string, path: PropertyKey[]) : never {\n throw new ValidupError([defineIssueItem({ message, path })]);\n}\n\nfunction refuseDocumentWithIssues(issues: Issue[]) : never {\n throw new ValidupError(issues);\n}\n\nfunction toPolicy(tree: AuthorizationPolicy) : BasePolicy {\n const {\n invert,\n children,\n ...policy\n } = tree;\n\n return {\n ...policy,\n ...(typeof invert === 'boolean' ? { invert } : {}),\n ...(children ? { children: children.map((child) => toPolicy(child)) } : {}),\n };\n}\n\n/**\n * Build a resource-server (or console) evaluator from the catalog\n * `GET /authorization` serves, the identity's grants as the introspection\n * endpoints report them, and the identity itself. Rejects legacy, incomplete\n * and unsupported input. A grant referencing a definition or a policy the\n * catalog lacks throws `AuthorizationCatalogStaleError`, the signal to\n * refetch the catalog: the grants come from a fresh introspection while the\n * catalog may predate the definition or the junction row. A definition the\n * server could not project travels with `policies: null` instead of being\n * left out, so a grant of it is dropped rather than reported stale: the\n * definition layer cannot be evaluated here, a refetch changes nothing, and\n * the permission denies until the policy is fixed.\n *\n * A tree THIS copy cannot project is the same condition read from the other\n * side, and it is per tree: a policy type the validator registry lacks (a\n * type newer than this package, or a custom one the caller did not register)\n * or a configuration its validator refuses denies the definitions that reference\n * it, exactly as `policies: null` does, and drops a grant that names it,\n * exactly as a binding check does. One such tree never takes the evaluator\n * down for the permissions that do not use it. A malformed catalog still\n * throws: a duplicate permission namespace is not a data condition.\n *\n * Both the identity and the grants are optional. Without an identity no grant\n * is bound and any IDENTITY key the caller supplied is REMOVED, so the\n * binding evaluator answers with missing data exactly as the server does for\n * an anonymous request, only a definition whose policies need no identity can\n * pass, and a caller can never inject an identity the document did not prove.\n * Grants without the identity they belong to are refused.\n *\n * The REALM_MATCH data key follows the server's own three-way rule: a\n * resource that carries a realm passes it (null for a global row, which\n * `own` denies), a resource with no realm dimension passes nothing and reach\n * neutral-passes. `preEvaluate` / `preEvaluateOneOf` are the pre-gate and\n * enforce reach only when that key is present. `compile` returns the\n * allow/deny/conditional/post contract; a `post` collection query must be\n * rejected or evaluated over every candidate before paging. The supplied\n * identity is authoritative; `options.decisionStrategy` is forwarded and the\n * policy include, exclude and pending options are refused.\n *\n * The policy type set is open (#3635): `options.validators` decides which\n * trees project and `options.evaluators` how they evaluate, the built-in\n * registries by default. A custom type needs both, the validator the server\n * projected it with and the evaluator the server decides it with; given only\n * the first it projects and then denies. The binding evaluator is always this\n * function's own, since it is what binds the introspected grants.\n */\nexport async function createAuthorizationEvaluator(\n input: AuthorizationEvaluatorInput,\n options: AuthorizationEvaluatorOptions = {},\n) : Promise<IPermissionEvaluator> {\n const {\n catalog, \n grants, \n identity, \n } = await parseAuthorizationEvaluatorInput(input);\n\n const trees = new Map<string, AuthorizationPolicy>();\n const unevaluable = new Set<string>();\n for (const [id, raw] of Object.entries(catalog.policies)) {\n try {\n trees.set(id, await projectAuthorizationPolicy(raw, options.validators));\n } catch {\n unevaluable.add(id);\n }\n }\n\n const definitions : PermissionPolicyBinding[] = [];\n const permissions = new Map<string, BasePermission | null>();\n for (const [index, entry] of catalog.permissions.entries()) {\n const permission : BasePermission = {\n name: entry.name,\n realmId: entry.realm_id,\n clientId: entry.client_id,\n decisionStrategy: entry.decision_strategy ?? undefined,\n };\n const key = buildPermissionKey(permission);\n if (permissions.has(key)) {\n refuseDocument(\n `The catalog defines the permission ${key} more than once.`,\n ['catalog', 'permissions', index],\n );\n }\n if (entry.policies === null || entry.policies.some((id) => unevaluable.has(id))) {\n permissions.set(key, null);\n continue;\n }\n permissions.set(key, permission);\n\n const policies : BasePolicy[] = [];\n for (const [i, id] of entry.policies.entries()) {\n const tree = trees.get(id);\n if (!tree) {\n refuseDocument(\n `The catalog does not declare the policy ${id}.`,\n ['catalog', 'permissions', index, 'policies', i],\n );\n }\n policies.push(toPolicy(tree));\n }\n\n definitions.push({ permission, policies: policies.length > 0 ? policies : undefined });\n }\n\n const bindings : PermissionPolicyBinding[] = [];\n for (const grant of grants) {\n const key = buildPermissionKey({\n name: grant.name,\n realmId: grant.realm_id ?? null,\n clientId: grant.client_id ?? null,\n });\n const permission = permissions.get(key);\n if (typeof permission === 'undefined') {\n throw new AuthorizationCatalogStaleError(`The catalog does not define the permission ${key}.`);\n }\n if (permission === null) {\n continue;\n }\n\n const policies : BasePolicy[] = [];\n let evaluable = true;\n for (const id of grant.policies ?? []) {\n if (unevaluable.has(id)) {\n evaluable = false;\n break;\n }\n const tree = trees.get(id);\n if (!tree) {\n throw new AuthorizationCatalogStaleError(`The catalog does not declare the policy ${id}.`);\n }\n if (containsBindingCheck(tree)) {\n evaluable = false;\n break;\n }\n policies.push(toPolicy(tree));\n }\n if (!evaluable) {\n continue;\n }\n\n bindings.push({\n permission,\n realmScope: normalizeRealmScope(grant.realm_scope),\n policies: policies.length > 0 ? policies : undefined,\n });\n }\n\n const engine = new PolicyEngine(options.evaluators ?? PolicyDefaultEvaluators);\n engine.registerEvaluator(\n BuiltInPolicyType.PERMISSION_BINDING,\n new IdentityPermissionBindingPolicyEvaluator({ getFor: async () => bindings }),\n );\n const evaluator = new PermissionEvaluator({\n provider: new PermissionMemoryProvider(definitions),\n policyEngine: engine,\n });\n\n const withIdentity = (input?: PolicyData) : PolicyData => {\n const data = input?.clone() ?? new PolicyData();\n if (!identity) {\n // symmetrical with the branch below, which overwrites the key:\n // the document proved no identity, so the caller may not supply\n // one either\n data.delete(BuiltInPolicyType.IDENTITY);\n\n return data;\n }\n\n data.set(BuiltInPolicyType.IDENTITY, {\n id: identity.id,\n type: identity.type,\n realmId: identity.realmId ?? undefined,\n realmName: identity.realmName ?? undefined,\n clientId: identity.clientId ?? null,\n });\n\n return data;\n };\n\n const forGate = (ctx: PermissionEvaluationContext) : PermissionEvaluationContext => {\n if (\n ctx.options?.policiesIncluded ||\n ctx.options?.policiesExcluded ||\n ctx.options?.pendingPolicies\n ) {\n throw new InternalError('The authorization evaluator does not accept policy bypass options.');\n }\n\n return {\n name: ctx.name,\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n data: withIdentity(ctx.data),\n ...(ctx.options?.decisionStrategy ?\n { options: { decisionStrategy: ctx.options.decisionStrategy } } :\n {}),\n };\n };\n\n const forResource = (ctx: PermissionEvaluationContext) : PermissionEvaluationContext => {\n const next = forGate(ctx);\n if (next.data!.has(BuiltInPolicyType.REALM_MATCH)) {\n const value = next.data!.get(BuiltInPolicyType.REALM_MATCH);\n const outcome = realmMatchSchema.safeParse(value);\n if (!outcome.success) {\n refuseDocumentWithIssues(\n buildIssuesForZodError(outcome.error, value)\n .map((issue) => prefixIssuePath(issue, ['data', BuiltInPolicyType.REALM_MATCH])),\n );\n }\n }\n\n return next;\n };\n\n return {\n async evaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.evaluate(forResource(ctx));\n },\n async evaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.evaluateOneOf(forResource(ctx));\n },\n async preEvaluate(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.preEvaluate(forGate(ctx));\n },\n async preEvaluateOneOf(ctx: PermissionEvaluationContext) : Promise<void> {\n return evaluator.preEvaluateOneOf(forGate(ctx));\n },\n async compile(ctx: PermissionCompileContext) : Promise<PermissionCompileResult> {\n if (ctx.data?.has(BuiltInPolicyType.REALM_MATCH) || ctx.data?.has(BuiltInPolicyType.ATTRIBUTES)) {\n throw new InternalError('Compile authorization without resource realm or row attributes.');\n }\n\n return evaluator.compile({\n name: ctx.name,\n realmId: ctx.realmId,\n clientId: ctx.clientId,\n data: withIdentity(ctx.data),\n realmAttributeName: ctx.realmAttributeName,\n });\n },\n };\n}\n\n/**\n * An `IPermissionEvaluator` over the answer `POST /authorization/check`\n * served: the caller's own verdicts, paired with the realms they hold in.\n *\n * It is what a PUBLIC client gets where the catalog is out of reach. A public\n * client holds no secret, so it can obtain no `client_credentials` token and\n * has no credential of its own for the catalog's gate to be satisfied by;\n * publishing every policy predicate to it instead would be the wrong trade.\n * The verdicts are computed by the server from the same grants and the same\n * evaluators a request runs, so this is authoritative where the name-only\n * fallback it replaces is merely coarse.\n *\n * Two properties follow from the answer being a pre-gate:\n *\n * It is an UPPER BOUND, so `evaluate` and `evaluateOneOf` answer exactly what\n * the pre-gate pair answers. A check that depends on a resource row belongs to\n * whoever holds the row, and the server decides it there; answering such a\n * check here would mean inventing a verdict. That is the same bound the\n * name-only fallback already had, so nothing that gates on it loosens.\n *\n * And a resource realm is matched against what the REQUEST asked about: a\n * `realmMatch` naming a realm the request never carried is in no entry's list\n * and therefore denies. That is fail-closed by construction rather than by a\n * rule, and it is why a caller must ask about the realms its UI will ask\n * about.\n */\nexport async function createAuthorizationCheckEvaluator(\n input: AuthorizationCheckEvaluatorInput,\n) : Promise<IPermissionEvaluator> {\n const { permissions, identity } = await parseAuthorizationCheckEvaluatorInput(input);\n\n const verdicts = new Map<string, Set<string | null>>();\n for (const permission of permissions) {\n verdicts.set(permission.name, new Set<string | null>(permission.realms));\n }\n\n // The server resolves `own` / `ownOrNull` to the identity's realm ID, while\n // a caller may name its own realm either way: the reach comparison the\n // server makes accepts the id or the name, so the consumer has to as well,\n // or a check carrying the realm NAME would deny against an answer keyed by\n // the id.\n const ownKeys = new Set<string>();\n if (identity?.realmId) {\n ownKeys.add(identity.realmId);\n }\n if (identity?.realmName) {\n ownKeys.add(identity.realmName);\n }\n\n const matchesRealm = (realms: Set<string | null>, value: string | null) : boolean => {\n if (realms.has(value)) {\n return true;\n }\n\n if (value === null || !ownKeys.has(value)) {\n return false;\n }\n\n for (const key of ownKeys) {\n if (realms.has(key)) {\n return true;\n }\n }\n\n return false;\n };\n\n const holds = (name: string, data?: PolicyData) : boolean => {\n const realms = verdicts.get(name);\n if (!realms) {\n return false;\n }\n\n if (!data || !data.has(BuiltInPolicyType.REALM_MATCH)) {\n // No resource realm named, so the question is whether the\n // permission is held at all, which it is: an entry only exists\n // when at least one requested realm passed.\n return true;\n }\n\n const value = data.get<string | string[] | null>(BuiltInPolicyType.REALM_MATCH);\n if (Array.isArray(value)) {\n // A resource spanning several realms needs every one of them,\n // fail-closed on the empty set, the rule `realmScopeMatches` applies.\n if (value.length === 0) {\n return false;\n }\n\n return value.every((entry) => matchesRealm(realms, entry ?? null));\n }\n\n return matchesRealm(realms, value ?? null);\n };\n\n const names = (ctx: PermissionEvaluationContext) : string[] => (Array.isArray(ctx.name) ?\n ctx.name :\n [ctx.name]);\n\n const assertEvery = async (ctx: PermissionEvaluationContext) : Promise<void> => {\n for (const name of names(ctx)) {\n if (!holds(name, ctx.data)) {\n throw PermissionError.evaluationFailed(ctx.name);\n }\n }\n };\n\n const assertSome = async (ctx: PermissionEvaluationContext) : Promise<void> => {\n const list = names(ctx);\n for (const name of list) {\n if (holds(name, ctx.data)) {\n return;\n }\n }\n\n throw PermissionError.evaluationFailed(ctx.name);\n };\n\n return {\n evaluate: assertEvery,\n evaluateOneOf: assertSome,\n preEvaluate: assertEvery,\n preEvaluateOneOf: assertSome,\n async compile(ctx: PermissionCompileContext) : Promise<PermissionCompileResult> {\n // A verdict set carries no row predicate, so nothing here can be\n // lowered into a query. `deny` is still sound and worth answering:\n // a name held in no requested realm cannot match a row either.\n const list = Array.isArray(ctx.name) ? ctx.name : [ctx.name];\n if (list.some((name) => holds(name, ctx.data))) {\n return { verdict: 'post' };\n }\n\n return { verdict: 'deny' };\n },\n };\n}\n"],"mappings":"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"}