@venizia/ignis 0.4.6 → 0.4.7-0

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 (57) hide show
  1. package/dist/esm/base/applications/base.d.ts.map +1 -1
  2. package/dist/esm/base/applications/base.js +4 -2
  3. package/dist/esm/base/applications/base.js.map +1 -1
  4. package/dist/esm/base/controllers/grpc/adapter.d.ts.map +1 -1
  5. package/dist/esm/base/controllers/grpc/adapter.js +5 -1
  6. package/dist/esm/base/controllers/grpc/adapter.js.map +1 -1
  7. package/dist/esm/base/middlewares/request-spy/request-spy.middleware.d.ts.map +1 -1
  8. package/dist/esm/base/middlewares/request-spy/request-spy.middleware.js +9 -3
  9. package/dist/esm/base/middlewares/request-spy/request-spy.middleware.js.map +1 -1
  10. package/dist/esm/components/api-reference/ui/scalar.d.ts.map +1 -1
  11. package/dist/esm/components/api-reference/ui/scalar.js +2 -1
  12. package/dist/esm/components/api-reference/ui/scalar.js.map +1 -1
  13. package/dist/esm/components/api-reference/ui/swagger.d.ts.map +1 -1
  14. package/dist/esm/components/api-reference/ui/swagger.js +2 -1
  15. package/dist/esm/components/api-reference/ui/swagger.js.map +1 -1
  16. package/dist/esm/components/auth/authenticate/services/bearer/abstract.service.d.ts.map +1 -1
  17. package/dist/esm/components/auth/authenticate/services/bearer/abstract.service.js +4 -2
  18. package/dist/esm/components/auth/authenticate/services/bearer/abstract.service.js.map +1 -1
  19. package/dist/esm/components/auth/authenticate/services/service/signer.service.d.ts.map +1 -1
  20. package/dist/esm/components/auth/authenticate/services/service/signer.service.js +6 -4
  21. package/dist/esm/components/auth/authenticate/services/service/signer.service.js.map +1 -1
  22. package/dist/esm/components/auth/authorize/adapters/scoped-casbin/adapter.d.ts.map +1 -1
  23. package/dist/esm/components/auth/authorize/adapters/scoped-casbin/adapter.js +6 -3
  24. package/dist/esm/components/auth/authorize/adapters/scoped-casbin/adapter.js.map +1 -1
  25. package/dist/esm/components/auth/authorize/enforcers/casbin-module.d.ts.map +1 -1
  26. package/dist/esm/components/auth/authorize/enforcers/casbin-module.js +2 -1
  27. package/dist/esm/components/auth/authorize/enforcers/casbin-module.js.map +1 -1
  28. package/dist/esm/components/auth/authorize/enforcers/casbin.enforcer.d.ts.map +1 -1
  29. package/dist/esm/components/auth/authorize/enforcers/casbin.enforcer.js +9 -3
  30. package/dist/esm/components/auth/authorize/enforcers/casbin.enforcer.js.map +1 -1
  31. package/dist/esm/components/health-check/component.d.ts.map +1 -1
  32. package/dist/esm/components/health-check/component.js +5 -3
  33. package/dist/esm/components/health-check/component.js.map +1 -1
  34. package/dist/esm/components/mail/helpers/executors/bull-mq-executor.helper.d.ts.map +1 -1
  35. package/dist/esm/components/mail/helpers/executors/bull-mq-executor.helper.js +2 -1
  36. package/dist/esm/components/mail/helpers/executors/bull-mq-executor.helper.js.map +1 -1
  37. package/dist/esm/components/mail/helpers/transporters/nodemail-transporter.helper.d.ts.map +1 -1
  38. package/dist/esm/components/mail/helpers/transporters/nodemail-transporter.helper.js +5 -3
  39. package/dist/esm/components/mail/helpers/transporters/nodemail-transporter.helper.js.map +1 -1
  40. package/dist/esm/components/mail/services/mail.service.d.ts.map +1 -1
  41. package/dist/esm/components/mail/services/mail.service.js +6 -3
  42. package/dist/esm/components/mail/services/mail.service.js.map +1 -1
  43. package/dist/esm/components/mail/utilities/attachment.utility.d.ts.map +1 -1
  44. package/dist/esm/components/mail/utilities/attachment.utility.js +4 -2
  45. package/dist/esm/components/mail/utilities/attachment.utility.js.map +1 -1
  46. package/dist/esm/components/mail/utilities/mime.utility.d.ts.map +1 -1
  47. package/dist/esm/components/mail/utilities/mime.utility.js +8 -4
  48. package/dist/esm/components/mail/utilities/mime.utility.js.map +1 -1
  49. package/dist/esm/components/static-asset/controller/factory.d.ts.map +1 -1
  50. package/dist/esm/components/static-asset/controller/factory.js +4 -2
  51. package/dist/esm/components/static-asset/controller/factory.js.map +1 -1
  52. package/dist/esm/testing/assert-application-boots.d.ts.map +1 -1
  53. package/dist/esm/testing/assert-application-boots.js +8 -1
  54. package/dist/esm/testing/assert-application-boots.js.map +1 -1
  55. package/dist/presets/app/preset.json +4 -4
  56. package/dist/presets/lib/preset.json +3 -3
  57. package/package.json +8 -8
@@ -1 +1 @@
1
- {"version":3,"file":"signer.service.js","sourceRoot":"","sources":["../../../../../../../src/components/auth/authenticate/services/service/signer.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { inject } from '@/base/metadata';\nimport { AuthenticateBindingKeys, BaseService, ServiceAssertion } from '@venizia/ignis-kernel';\nimport type { IServiceAuthOptions } from '@venizia/ignis-kernel';\nimport { getError, RequestIdGenerator } from '@venizia/ignis-helpers/core';\nimport { HTTP } from '@venizia/ignis-helpers/common';\nimport type { CryptoKey, JWK } from 'jose';\nimport { readFile } from 'node:fs/promises';\nimport { JWKSKeyDrivers, JWKSKeyFormats } from '@venizia/ignis-kernel';\nimport { JoseLoader } from '../jose-loader';\n\n/**\n * Mints the outgoing assertion, and publishes the public half for callees to verify against.\n *\n * Only a service that CALLS OUT needs this. `isEnabled()` is false when the application configured\n * no keys, and the component then mounts no certs route.\n */\nexport class ServiceAssertionSignerService extends BaseService {\n private readonly requestIdGenerator = new RequestIdGenerator({\n scope: ServiceAssertionSignerService.name,\n });\n\n private privateKey?: CryptoKey;\n private jwks?: { keys: JWK[] };\n\n constructor(\n @inject({ key: AuthenticateBindingKeys.SERVICE_OPTIONS })\n private readonly options: IServiceAuthOptions,\n ) {\n super({ scope: ServiceAssertionSignerService.name });\n }\n\n isEnabled(): boolean {\n return Boolean(this.options.keys);\n }\n\n /** `<name>_<rest path without its slash>`, so a rotated mount changes the kid rather than colliding. */\n getKeyId(): string {\n const restPath = this.options.rest?.path ?? ServiceAssertion.DEFAULT_REST_PATH;\n return this.options.keys?.kid ?? `${this.options.name}_${restPath.replace(/^\\//, '')}`;\n }\n\n /**\n * One assertion, bound to this exact call.\n *\n * `path` must be the percent-ENCODED pathname - `new URL(target).pathname`. The verifier compares\n * against the same shape, and a decoded path here would fail every route carrying a space or a\n * non-ASCII slug.\n */\n async sign(opts: { method: string; path: string; audience: string }): Promise<string> {\n const { method, path, audience } = opts;\n\n this.assertEnabled();\n\n const { SignJWT } = await JoseLoader.load();\n const now = Math.floor(Date.now() / 1000);\n const lifetime =\n this.options.signLifetimeSeconds ?? ServiceAssertion.DEFAULT_SIGN_LIFETIME_SECONDS;\n\n return new SignJWT({ htm: method.toUpperCase(), htu: path })\n .setProtectedHeader({\n alg: ServiceAssertion.ALGORITHM,\n kid: this.getKeyId(),\n typ: ServiceAssertion.TYP,\n })\n .setIssuer(this.options.name)\n .setSubject(this.options.name)\n .setAudience(audience)\n .setJti(this.requestIdGenerator.nextId())\n .setIssuedAt(now)\n .setExpirationTime(now + lifetime)\n .sign(await this.resolvePrivateKey());\n }\n\n /**\n * The document `/svc-certs` serves, built from the PUBLIC key only.\n *\n * `importSPKI` refuses a private PEM outright, which is what makes the private half unreachable\n * from here by construction rather than by care. The JWK format is deliberately NOT accepted for\n * this path: `importJWK` imports whatever it is handed, and a private JWK marked `\"ext\": true`\n * round-trips its `d` straight into this document. See `JWKSIssuerTokenService.assertPublicJWK`.\n */\n async getPublicJWKS(): Promise<{ keys: JWK[] }> {\n if (this.jwks) {\n return this.jwks;\n }\n\n this.assertEnabled();\n\n const { exportJWK, importSPKI } = await JoseLoader.load();\n const raw = await this.readKey({ source: this.options.keys!.public });\n const publicKey = await importSPKI(raw, ServiceAssertion.ALGORITHM);\n const jwk = await exportJWK(publicKey);\n\n if (jwk.d !== undefined) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[${ServiceAssertionSignerService.name}] The public key material carries a private exponent | this key would be published at the certs endpoint`,\n });\n }\n\n this.jwks = {\n keys: [{ ...jwk, kid: this.getKeyId(), alg: ServiceAssertion.ALGORITHM, use: 'sig' }],\n };\n\n return this.jwks;\n }\n\n private async resolvePrivateKey(): Promise<CryptoKey> {\n if (this.privateKey) {\n return this.privateKey;\n }\n\n const { importPKCS8 } = await JoseLoader.load();\n const raw = await this.readKey({ source: this.options.keys!.private });\n this.privateKey = await importPKCS8(raw, ServiceAssertion.ALGORITHM);\n return this.privateKey;\n }\n\n private async readKey(opts: { source: string }): Promise<string> {\n const { format, driver } = this.options.keys!;\n\n if (format !== JWKSKeyFormats.PEM) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[${ServiceAssertionSignerService.name}] Only the '${JWKSKeyFormats.PEM}' key format is supported | got: ${format}`,\n });\n }\n\n if (driver === JWKSKeyDrivers.FILE) {\n return readFile(opts.source, 'utf-8');\n }\n\n return opts.source;\n }\n\n private assertEnabled(): void {\n if (this.options.keys) {\n return;\n }\n\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[${ServiceAssertionSignerService.name}] This service has no signing keys | it can verify assertions but not mint them`,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"signer.service.js","sourceRoot":"","sources":["../../../../../../../src/components/auth/authenticate/services/service/signer.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { inject } from '@/base/metadata';\nimport { AuthenticateBindingKeys, BaseService, ServiceAssertion } from '@venizia/ignis-kernel';\nimport type { IServiceAuthOptions } from '@venizia/ignis-kernel';\nimport { getError, RequestIdGenerator } from '@venizia/ignis-helpers/core';\nimport { HTTP } from '@venizia/ignis-helpers/common';\nimport type { CryptoKey, JWK } from 'jose';\nimport { readFile } from 'node:fs/promises';\nimport { JWKSKeyDrivers, JWKSKeyFormats } from '@venizia/ignis-kernel';\nimport { JoseLoader } from '../jose-loader';\n\n/**\n * Mints the outgoing assertion, and publishes the public half for callees to verify against.\n *\n * Only a service that CALLS OUT needs this. `isEnabled()` is false when the application configured\n * no keys, and the component then mounts no certs route.\n */\nexport class ServiceAssertionSignerService extends BaseService {\n private readonly requestIdGenerator = new RequestIdGenerator({\n scope: ServiceAssertionSignerService.name,\n });\n\n private privateKey?: CryptoKey;\n private jwks?: { keys: JWK[] };\n\n constructor(\n @inject({ key: AuthenticateBindingKeys.SERVICE_OPTIONS })\n private readonly options: IServiceAuthOptions,\n ) {\n super({ scope: ServiceAssertionSignerService.name });\n }\n\n isEnabled(): boolean {\n return Boolean(this.options.keys);\n }\n\n /** `<name>_<rest path without its slash>`, so a rotated mount changes the kid rather than colliding. */\n getKeyId(): string {\n const restPath = this.options.rest?.path ?? ServiceAssertion.DEFAULT_REST_PATH;\n return this.options.keys?.kid ?? `${this.options.name}_${restPath.replace(/^\\//, '')}`;\n }\n\n /**\n * One assertion, bound to this exact call.\n *\n * `path` must be the percent-ENCODED pathname - `new URL(target).pathname`. The verifier compares\n * against the same shape, and a decoded path here would fail every route carrying a space or a\n * non-ASCII slug.\n */\n async sign(opts: { method: string; path: string; audience: string }): Promise<string> {\n const { method, path, audience } = opts;\n\n this.assertEnabled();\n\n const { SignJWT } = await JoseLoader.load();\n const now = Math.floor(Date.now() / 1000);\n const lifetime =\n this.options.signLifetimeSeconds ?? ServiceAssertion.DEFAULT_SIGN_LIFETIME_SECONDS;\n\n const assertion = new SignJWT({ htm: method.toUpperCase(), htu: path })\n .setProtectedHeader({\n alg: ServiceAssertion.ALGORITHM,\n kid: this.getKeyId(),\n typ: ServiceAssertion.TYP,\n })\n .setIssuer(this.options.name)\n .setSubject(this.options.name)\n .setAudience(audience)\n .setJti(this.requestIdGenerator.nextId())\n .setIssuedAt(now)\n .setExpirationTime(now + lifetime);\n\n const privateKey = await this.resolvePrivateKey();\n return assertion.sign(privateKey);\n }\n\n /**\n * The document `/svc-certs` serves, built from the PUBLIC key only.\n *\n * `importSPKI` refuses a private PEM outright, which is what makes the private half unreachable\n * from here by construction rather than by care. The JWK format is deliberately NOT accepted for\n * this path: `importJWK` imports whatever it is handed, and a private JWK marked `\"ext\": true`\n * round-trips its `d` straight into this document. See `JWKSIssuerTokenService.assertPublicJWK`.\n */\n async getPublicJWKS(): Promise<{ keys: JWK[] }> {\n if (this.jwks) {\n return this.jwks;\n }\n\n this.assertEnabled();\n\n const { exportJWK, importSPKI } = await JoseLoader.load();\n const raw = await this.readKey({ source: this.options.keys!.public });\n const publicKey = await importSPKI(raw, ServiceAssertion.ALGORITHM);\n const jwk = await exportJWK(publicKey);\n\n if (jwk.d !== undefined) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[${ServiceAssertionSignerService.name}] The public key material carries a private exponent | this key would be published at the certs endpoint`,\n });\n }\n\n this.jwks = {\n keys: [{ ...jwk, kid: this.getKeyId(), alg: ServiceAssertion.ALGORITHM, use: 'sig' }],\n };\n\n return this.jwks;\n }\n\n private async resolvePrivateKey(): Promise<CryptoKey> {\n if (this.privateKey) {\n return this.privateKey;\n }\n\n const { importPKCS8 } = await JoseLoader.load();\n const raw = await this.readKey({ source: this.options.keys!.private });\n const result = await importPKCS8(raw, ServiceAssertion.ALGORITHM);\n this.privateKey = result;\n return this.privateKey;\n }\n\n private async readKey(opts: { source: string }): Promise<string> {\n const { format, driver } = this.options.keys!;\n\n if (format !== JWKSKeyFormats.PEM) {\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[${ServiceAssertionSignerService.name}] Only the '${JWKSKeyFormats.PEM}' key format is supported | got: ${format}`,\n });\n }\n\n if (driver === JWKSKeyDrivers.FILE) {\n return readFile(opts.source, 'utf-8');\n }\n\n return opts.source;\n }\n\n private assertEnabled(): void {\n if (this.options.keys) {\n return;\n }\n\n throw getError({\n statusCode: HTTP.ResultCodes.RS_5.InternalServerError,\n message: `[${ServiceAssertionSignerService.name}] This service has no signing keys | it can verify assertions but not mint them`,\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/auth/authorize/adapters/scoped-casbin/adapter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../../../../src/components/auth/authorize/adapters/scoped-casbin/adapter.ts"],"names":[],"mappings":"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"}
@@ -71,8 +71,10 @@ export class ScopedCasbinAdapter extends BaseFilteredAdapter {
71
71
  principal,
72
72
  domains: [...domainClosure],
73
73
  });
74
- lines.push(...(await this.buildGrantLines({ subjectType: principal.type, rows: directGrants })));
75
- lines.push(...(await this.buildGrantLines({ subjectType: principals.role, rows: roleGrants })));
74
+ const result = await this.buildGrantLines({ subjectType: principal.type, rows: directGrants });
75
+ lines.push(...result);
76
+ const result2 = await this.buildGrantLines({ subjectType: principals.role, rows: roleGrants });
77
+ lines.push(...result2);
76
78
  const [structuralEdges, hookLines] = await Promise.all([
77
79
  structuralEdgesPromise,
78
80
  hookLinesPromise,
@@ -119,7 +121,8 @@ export class ScopedCasbinAdapter extends BaseFilteredAdapter {
119
121
  }
120
122
  let edges;
121
123
  try {
122
- edges = await this.resolveDomainEdges(opts);
124
+ const result = await this.resolveDomainEdges(opts);
125
+ edges = result;
123
126
  }
124
127
  catch (error) {
125
128
  this.logger
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../../../../../src/components/auth/authorize/adapters/scoped-casbin/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IdType } from '@/base';\nimport { type Model } from 'casbin';\nimport { sql, type SQL } from 'drizzle-orm';\nimport { GrantBuilder } from '@venizia/ignis-kernel';\nimport {\n AuthorizationActions,\n AuthorizationDecisions,\n AuthorizationDomainScopes,\n AuthorizationPolicyVariants,\n} from '@venizia/ignis-kernel';\nimport { BaseFilteredAdapter } from '../base-filtered';\nimport { CustomGrantExpander, type TCustomGrantRow } from '../custom-grant-expander';\nimport type { ICasbinPolicySource, IScopedCasbinEntities } from '../common';\nimport { PrincipalPolicyEdges, type TPrincipalPolicyRow } from './policy-edges';\nimport {\n DEFAULT_SCHEMA,\n type IScopedCasbinPolicyFilter,\n type TDomainHierarchyEdge,\n type TGrantRow,\n type TResolveDomainEdgesFn,\n} from './common';\n\n/**\n * Filtered casbin adapter for the scoped RBAC model: loads ONE principal's edges (role assignments,\n * memberships, grants) plus the shared structural hierarchy trees as casbin lines. Read-only.\n *\n * EVERY branch below must select by `variant = <known value>` or `variant IN (<known values>)`.\n * Never `variant NOT IN (...)`, and never a bare select that classifies afterwards. Applications\n * store their own edge kinds in this same table (declared via `extraVariants`), and an exclusion\n * filter would sweep those unknown rows into a branch that has no idea what they mean. The current\n * shape makes an undeclared variant inert, which is what makes sharing the table safe.\n */\nexport class ScopedCasbinAdapter extends BaseFilteredAdapter<IScopedCasbinPolicyFilter> {\n protected readonly entities: IScopedCasbinEntities;\n protected readonly customGrantExpander: CustomGrantExpander;\n protected readonly resolveDomainEdges?: TResolveDomainEdgesFn;\n\n constructor(opts: {\n dataSource: ICasbinPolicySource;\n entities: IScopedCasbinEntities;\n resolveDomainEdges?: TResolveDomainEdgesFn;\n }) {\n super({ scope: ScopedCasbinAdapter.name, dataSource: opts.dataSource });\n this.entities = opts.entities;\n this.resolveDomainEdges = opts.resolveDomainEdges;\n this.customGrantExpander = new CustomGrantExpander({\n dataSource: opts.dataSource,\n entities: { permission: opts.entities.permission, softDelete: opts.entities.softDelete },\n });\n }\n\n /**\n * One wave: the principal-scoped CTE and the merged structural-edges query are issued together -\n * the role closure resolves in SQL, so neither waits on the other. `resolveDomainEdges` cannot\n * join that wave - it needs the domain closure the principal-scoped CTE produces - but it does\n * not wait for the structural-edges query either: both run concurrently once the closure is known.\n */\n async loadFilteredPolicy(model: Model, filter: IScopedCasbinPolicyFilter): Promise<void> {\n const { principal } = filter;\n const { principals } = this.entities;\n\n const principalPoliciesPromise = this.queryPrincipalPolicies({ principal });\n const structuralEdgesPromise = this.queryEdgePolicies();\n const principalRows = await principalPoliciesPromise;\n\n const lines: string[] = [];\n const directGrants: TGrantRow[] = [];\n const roleGrants: TGrantRow[] = [];\n const domainClosure = new Set<string>();\n\n for (const row of principalRows) {\n switch (row.kind) {\n case PrincipalPolicyEdges.ROLE_EDGE: {\n lines.push(\n `${AuthorizationPolicyVariants.ROLE_INHERITS.rule}, ${principals.role}_${row.subjectId}, ${principals.role}_${row.targetId}, *`,\n );\n break;\n }\n\n case PrincipalPolicyEdges.ROLE_GRANT: {\n roleGrants.push(row);\n break;\n }\n\n case PrincipalPolicyEdges.DOMAIN_EDGE: {\n lines.push(\n `${AuthorizationPolicyVariants.DOMAIN_INHERITS.rule}, ${row.subjectId}, ${row.targetId}`,\n );\n // Both ends are, by construction, members of the principal's domain_closure CTE.\n domainClosure.add(String(row.subjectId));\n domainClosure.add(String(row.targetId));\n break;\n }\n\n default: {\n if (row.variant === AuthorizationPolicyVariants.JOIN_DOMAIN.action) {\n domainClosure.add(`${row.targetType}_${row.targetId}`);\n }\n this.collectDirectRow({ row, principal, lines, directGrants });\n break;\n }\n }\n }\n\n const hookLinesPromise = this.resolveDomainEdgeLines({\n principal,\n domains: [...domainClosure],\n });\n\n lines.push(\n ...(await this.buildGrantLines({ subjectType: principal.type, rows: directGrants })),\n );\n lines.push(...(await this.buildGrantLines({ subjectType: principals.role, rows: roleGrants })));\n\n const [structuralEdges, hookLines] = await Promise.all([\n structuralEdgesPromise,\n hookLinesPromise,\n ]);\n lines.push(...structuralEdges);\n lines.push(...hookLines);\n\n await this.loadLines({ model, lines });\n }\n\n /** Route one `direct` row to its casbin line, or to the grant batch. */\n protected collectDirectRow(opts: {\n row: TPrincipalPolicyRow;\n principal: { type: string; id: IdType };\n lines: string[];\n directGrants: TGrantRow[];\n }): void {\n const { row, principal, lines, directGrants } = opts;\n const { principals } = this.entities;\n\n switch (row.variant) {\n case AuthorizationPolicyVariants.ASSIGN_ROLE.action: {\n lines.push(\n `${AuthorizationPolicyVariants.ASSIGN_ROLE.rule}, ${principal.type}_${principal.id}, ${principals.role}_${row.targetId}, ${row.domain ?? '*'}`,\n );\n break;\n }\n\n case AuthorizationPolicyVariants.JOIN_DOMAIN.action: {\n lines.push(\n `${AuthorizationPolicyVariants.JOIN_DOMAIN.rule}, ${principal.type}_${principal.id}, ${row.targetType}_${row.targetId}`,\n );\n break;\n }\n\n case AuthorizationPolicyVariants.GRANT.action: {\n directGrants.push(row);\n break;\n }\n\n default: {\n this.logger\n .for(this.collectDirectRow.name)\n .error('Unexpected variant in the direct branch | variant: %s', row.variant);\n break;\n }\n }\n }\n\n /**\n * Calls the `resolveDomainEdges` hook, if supplied, and turns its edges into `g3` lines using\n * the same shape the DOMAIN_EDGE branch emits. A throwing hook is logged and treated as no\n * edges - the rows already gathered for this principal still load. This is the safe direction:\n * a missing hierarchy edge can only narrow what `g`/`g2`/`g3` reach, never widen it, so the\n * failure degrades to less access rather than either an outage or excess access.\n */\n protected async resolveDomainEdgeLines(opts: {\n principal: { type: string; id: IdType };\n domains: string[];\n }): Promise<string[]> {\n if (!this.resolveDomainEdges) {\n return [];\n }\n\n let edges: TDomainHierarchyEdge[];\n try {\n edges = await this.resolveDomainEdges(opts);\n } catch (error) {\n this.logger\n .for(this.resolveDomainEdgeLines.name)\n .error(\n 'resolveDomainEdges hook threw - continuing without its edges for this load | principal: %s_%s | error: %s',\n opts.principal.type,\n opts.principal.id,\n error,\n );\n return [];\n }\n\n return edges.map(\n (edge) =>\n `${AuthorizationPolicyVariants.DOMAIN_INHERITS.rule}, ${edge.child}, ${edge.parent}`,\n );\n }\n\n /** Schema for a table, defaulting to `public`. */\n protected schemaOf(table: { schemaName?: string }): string {\n return table.schemaName ?? DEFAULT_SCHEMA;\n }\n\n /** The casbin domain token, built from the stored pair - one expression for every SELECT so they cannot drift. NULL reaches `buildGrantLines` as `ANY_MEMBER`. The alias is emitted raw for the same reason as in `softDeleteClause`: quoting folds it to a different case than the unquoted FROM alias. */\n protected domainTokenSelection(opts: { alias: string }): SQL {\n const column = (name: string) => sql`${sql.raw(opts.alias)}.${sql.identifier(name)}`;\n const domainType = column('domain_type');\n const domainId = column('domain_id');\n\n return sql`CASE\n WHEN ${domainType} IS NULL THEN NULL\n WHEN ${domainId} IS NULL THEN ${domainType}\n ELSE ${domainType} || '_' || ${domainId}::text\n END AS \"domain\"`;\n }\n\n /** Schema-qualified table reference (`\"<schema>\".\"<table>\"`) for use after FROM/JOIN with an alias. */\n protected qualifiedTable(opts: { table: { schemaName?: string; tableName: string } }): SQL {\n const { table } = opts;\n return sql`${sql.identifier(this.schemaOf(table))}.${sql.identifier(table.tableName)}`;\n }\n\n /** `AND <alias>.<col> IS NULL` when soft-delete is on, else empty. The alias is emitted raw to match the unquoted FROM alias - quoting folds it to a different case and breaks the join. */\n protected softDeleteClause(opts: { alias: string }): SQL {\n const sd = this.entities.softDelete;\n if (!sd?.use) {\n return sql.empty();\n }\n\n return sql` AND ${sql.raw(opts.alias)}.${sql.identifier(sd.columnName)} IS NULL`;\n }\n\n /** One statement for everything scoped to a principal: its own edges, the role_inherits edges reachable from its roles, and the grants of that closure. `UNION` in the recursive term is what terminates a cyclic role graph. */\n protected async queryPrincipalPolicies(opts: {\n principal: { type: string; id: IdType };\n }): Promise<TPrincipalPolicyRow[]> {\n const { policyDefinition, permission, principals, domainTypes } = this.entities;\n const policyDefinitionTable = this.qualifiedTable({ table: policyDefinition });\n const permissionTable = this.qualifiedTable({ table: permission });\n const { principal } = opts;\n\n const metadataColumnName = policyDefinition.metadata?.columnName;\n const metadataSelection = metadataColumnName\n ? sql`, policyDefinition.${sql.identifier(metadataColumnName)} AS \"metadata\"`\n : sql.empty();\n const metadataNull = metadataColumnName ? sql`, NULL::jsonb AS \"metadata\"` : sql.empty();\n\n const domainTypeList = sql.join(\n domainTypes.map((domainType) => sql`${domainType}`),\n sql`, `,\n );\n\n const rows = await this.query<TPrincipalPolicyRow>({\n statement: sql`\n WITH RECURSIVE role_closure AS (\n SELECT policyDefinition.target_id AS role_id\n FROM ${policyDefinitionTable} policyDefinition\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ASSIGN_ROLE.action}\n AND policyDefinition.subject_type = ${principal.type}\n AND policyDefinition.subject_id = ${principal.id}\n AND policyDefinition.target_type = ${principals.role}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION\n\n SELECT policyDefinition.target_id\n FROM ${policyDefinitionTable} policyDefinition\n JOIN role_closure ON policyDefinition.subject_id = role_closure.role_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ROLE_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n ),\n\n domain_closure AS (\n SELECT policyDefinition.target_type AS dom_type, policyDefinition.target_id AS dom_id\n FROM ${policyDefinitionTable} policyDefinition\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.JOIN_DOMAIN.action}\n AND policyDefinition.subject_type = ${principal.type}\n AND policyDefinition.subject_id = ${principal.id}\n AND policyDefinition.target_type IN (${domainTypeList})${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION\n\n SELECT policyDefinition.target_type, policyDefinition.target_id\n FROM ${policyDefinitionTable} policyDefinition\n JOIN domain_closure ON policyDefinition.subject_type = domain_closure.dom_type\n AND policyDefinition.subject_id = domain_closure.dom_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.DOMAIN_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n )\n\n SELECT\n ${PrincipalPolicyEdges.DIRECT}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_id::text AS \"subjectId\",\n policyDefinition.target_type AS \"targetType\",\n policyDefinition.target_id::text AS \"targetId\",\n policyDefinition.action,\n policyDefinition.effect,\n ${this.domainTokenSelection({ alias: 'policyDefinition' })},\n permission.code AS \"objectCode\",\n permission.subject AS \"objectSubject\",\n permission.method AS \"objectMethod\"${metadataSelection}\n FROM ${policyDefinitionTable} policyDefinition\n LEFT JOIN ${permissionTable} permission\n ON policyDefinition.target_id = permission.id${this.softDeleteClause({ alias: 'permission' })}\n WHERE policyDefinition.subject_type = ${principal.type}\n AND policyDefinition.subject_id = ${principal.id}\n AND policyDefinition.variant IN (\n ${AuthorizationPolicyVariants.ASSIGN_ROLE.action},\n ${AuthorizationPolicyVariants.JOIN_DOMAIN.action},\n ${AuthorizationPolicyVariants.GRANT.action}\n )\n AND (\n policyDefinition.variant <> ${AuthorizationPolicyVariants.JOIN_DOMAIN.action}\n OR policyDefinition.target_type IN (${domainTypeList})\n )${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${PrincipalPolicyEdges.ROLE_EDGE}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_id::text AS \"subjectId\",\n policyDefinition.target_type AS \"targetType\",\n policyDefinition.target_id::text AS \"targetId\",\n NULL AS \"action\",\n NULL AS \"effect\",\n NULL AS \"domain\",\n NULL AS \"objectCode\",\n NULL AS \"objectSubject\",\n NULL AS \"objectMethod\"${metadataNull}\n FROM ${policyDefinitionTable} policyDefinition\n JOIN role_closure ON policyDefinition.subject_id = role_closure.role_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ROLE_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${PrincipalPolicyEdges.ROLE_GRANT}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_id::text AS \"subjectId\",\n policyDefinition.target_type AS \"targetType\",\n policyDefinition.target_id::text AS \"targetId\",\n policyDefinition.action,\n policyDefinition.effect,\n ${this.domainTokenSelection({ alias: 'policyDefinition' })},\n permission.code AS \"objectCode\",\n permission.subject AS \"objectSubject\",\n permission.method AS \"objectMethod\"${metadataSelection}\n FROM ${policyDefinitionTable} policyDefinition\n JOIN role_closure ON policyDefinition.subject_id = role_closure.role_id\n LEFT JOIN ${permissionTable} permission\n ON policyDefinition.target_id = permission.id${this.softDeleteClause({ alias: 'permission' })}\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.GRANT.action}\n AND policyDefinition.subject_type = ${principals.role}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${PrincipalPolicyEdges.DOMAIN_EDGE}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_type || '_' || policyDefinition.subject_id::text AS \"subjectId\",\n NULL AS \"targetType\",\n policyDefinition.target_type || '_' || policyDefinition.target_id::text AS \"targetId\",\n NULL AS \"action\",\n NULL AS \"effect\",\n NULL AS \"domain\",\n NULL AS \"objectCode\",\n NULL AS \"objectSubject\",\n NULL AS \"objectMethod\"${metadataNull}\n FROM ${policyDefinitionTable} policyDefinition\n JOIN domain_closure ON policyDefinition.subject_type = domain_closure.dom_type\n AND policyDefinition.subject_id = domain_closure.dom_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.DOMAIN_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n `,\n });\n\n return rows;\n }\n\n /** Turn fetched grant rows into casbin lines. Shared by the direct and role-closure branches. */\n protected async buildGrantLines(opts: {\n subjectType: string;\n rows: TGrantRow[];\n }): Promise<string[]> {\n const { subjectType, rows } = opts;\n const metadataColumnName = this.entities.policyDefinition.metadata?.columnName;\n\n const lines: string[] = [];\n const customRows: TCustomGrantRow[] = [];\n\n for (const row of rows) {\n if (!row.objectCode) {\n this.logger\n .for(this.buildGrantLines.name)\n .error(\n 'Skipping grant row whose permission did not resolve - the target is missing or soft-deleted | subject: %s_%s',\n subjectType,\n row.subjectId,\n );\n continue;\n }\n\n const domain = row.domain ?? AuthorizationDomainScopes.ANY_MEMBER;\n const effect = row.effect ?? AuthorizationDecisions.ALLOW;\n const parsed = metadataColumnName\n ? GrantBuilder.getInstance().parseCustomGrantMetadata({ metadata: row.metadata })\n : null;\n const isCustomAction = row.action === AuthorizationActions.CUSTOM;\n const isCustomRow = isCustomAction || Boolean(parsed);\n\n if (!isCustomRow && !row.action) {\n this.logger\n .for(this.buildGrantLines.name)\n .error(\n 'Skipping grant row with no action - the permission it should confer is silently missing | subject: %s_%s | object: %s',\n subjectType,\n row.subjectId,\n row.objectCode,\n );\n continue;\n }\n\n if (!isCustomRow) {\n lines.push(\n `${AuthorizationPolicyVariants.GRANT.rule}, ${subjectType}_${row.subjectId}, ${domain}, ${row.objectCode}, ${row.action}, ${effect}`,\n );\n continue;\n }\n\n if (!row.objectSubject || !row.objectMethod) {\n this.logger\n .for(this.buildGrantLines.name)\n .error(\n 'Skipping custom grant row whose subject or method did not resolve - the target is missing or soft-deleted | subject: %s_%s | object: %s',\n subjectType,\n row.subjectId,\n row.objectCode,\n );\n continue;\n }\n\n const rejection = this.customGrantExpander.rejectCustomRow({\n row: {\n subjectId: row.subjectId,\n objectCode: row.objectCode,\n objectMethod: row.objectMethod,\n },\n parsed,\n isCustomAction,\n metadataColumnName,\n });\n\n if (rejection) {\n this.logger.for(this.buildGrantLines.name).error(rejection);\n continue;\n }\n\n customRows.push({\n subjectId: row.subjectId,\n objectSubject: row.objectSubject,\n ops: parsed!.ops,\n domain,\n effect,\n });\n }\n\n const expanded = await this.customGrantExpander.expandCustomGrants({ subjectType, customRows });\n for (const rejection of expanded.rejections) {\n this.logger.for(this.buildGrantLines.name).error(rejection);\n }\n lines.push(...expanded.lines);\n\n return lines;\n }\n\n /** The two code-fixed structural trees only (`g4` resource, `g5` action) - constant regardless of tenant count. Domain edges (`g3`) grow with the domain count, so they are principal-scoped in {@link queryPrincipalPolicies} instead. */\n protected async queryEdgePolicies(): Promise<string[]> {\n const { policyDefinition, permission } = this.entities;\n const policyDefinitionTable = this.qualifiedTable({ table: policyDefinition });\n const permissionTable = this.qualifiedTable({ table: permission });\n\n const rows = await this.query<{ rel: string; child: string; parent: string }>({\n statement: sql`\n SELECT\n ${AuthorizationPolicyVariants.RESOURCE_INHERITS.rule} AS \"rel\",\n child_permission.code AS \"child\",\n parent_permission.code AS \"parent\"\n FROM ${policyDefinitionTable} policyDefinition\n INNER JOIN ${permissionTable} child_permission ON policyDefinition.subject_id = child_permission.id\n INNER JOIN ${permissionTable} parent_permission ON policyDefinition.target_id = parent_permission.id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.RESOURCE_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${AuthorizationPolicyVariants.ACTION_INHERITS.rule} AS \"rel\",\n policyDefinition.subject_id::text AS \"child\",\n policyDefinition.target_id::text AS \"parent\"\n FROM ${policyDefinitionTable} policyDefinition\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ACTION_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n `,\n });\n\n return rows.map((row) => `${row.rel}, ${row.child}, ${row.parent}`);\n }\n}\n"]}
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../../../../../src/components/auth/authorize/adapters/scoped-casbin/adapter.ts"],"names":[],"mappings":"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","sourcesContent":["import type { IdType } from '@/base';\nimport { type Model } from 'casbin';\nimport { sql, type SQL } from 'drizzle-orm';\nimport { GrantBuilder } from '@venizia/ignis-kernel';\nimport {\n AuthorizationActions,\n AuthorizationDecisions,\n AuthorizationDomainScopes,\n AuthorizationPolicyVariants,\n} from '@venizia/ignis-kernel';\nimport { BaseFilteredAdapter } from '../base-filtered';\nimport { CustomGrantExpander, type TCustomGrantRow } from '../custom-grant-expander';\nimport type { ICasbinPolicySource, IScopedCasbinEntities } from '../common';\nimport { PrincipalPolicyEdges, type TPrincipalPolicyRow } from './policy-edges';\nimport {\n DEFAULT_SCHEMA,\n type IScopedCasbinPolicyFilter,\n type TDomainHierarchyEdge,\n type TGrantRow,\n type TResolveDomainEdgesFn,\n} from './common';\n\n/**\n * Filtered casbin adapter for the scoped RBAC model: loads ONE principal's edges (role assignments,\n * memberships, grants) plus the shared structural hierarchy trees as casbin lines. Read-only.\n *\n * EVERY branch below must select by `variant = <known value>` or `variant IN (<known values>)`.\n * Never `variant NOT IN (...)`, and never a bare select that classifies afterwards. Applications\n * store their own edge kinds in this same table (declared via `extraVariants`), and an exclusion\n * filter would sweep those unknown rows into a branch that has no idea what they mean. The current\n * shape makes an undeclared variant inert, which is what makes sharing the table safe.\n */\nexport class ScopedCasbinAdapter extends BaseFilteredAdapter<IScopedCasbinPolicyFilter> {\n protected readonly entities: IScopedCasbinEntities;\n protected readonly customGrantExpander: CustomGrantExpander;\n protected readonly resolveDomainEdges?: TResolveDomainEdgesFn;\n\n constructor(opts: {\n dataSource: ICasbinPolicySource;\n entities: IScopedCasbinEntities;\n resolveDomainEdges?: TResolveDomainEdgesFn;\n }) {\n super({ scope: ScopedCasbinAdapter.name, dataSource: opts.dataSource });\n this.entities = opts.entities;\n this.resolveDomainEdges = opts.resolveDomainEdges;\n this.customGrantExpander = new CustomGrantExpander({\n dataSource: opts.dataSource,\n entities: { permission: opts.entities.permission, softDelete: opts.entities.softDelete },\n });\n }\n\n /**\n * One wave: the principal-scoped CTE and the merged structural-edges query are issued together -\n * the role closure resolves in SQL, so neither waits on the other. `resolveDomainEdges` cannot\n * join that wave - it needs the domain closure the principal-scoped CTE produces - but it does\n * not wait for the structural-edges query either: both run concurrently once the closure is known.\n */\n async loadFilteredPolicy(model: Model, filter: IScopedCasbinPolicyFilter): Promise<void> {\n const { principal } = filter;\n const { principals } = this.entities;\n\n const principalPoliciesPromise = this.queryPrincipalPolicies({ principal });\n const structuralEdgesPromise = this.queryEdgePolicies();\n const principalRows = await principalPoliciesPromise;\n\n const lines: string[] = [];\n const directGrants: TGrantRow[] = [];\n const roleGrants: TGrantRow[] = [];\n const domainClosure = new Set<string>();\n\n for (const row of principalRows) {\n switch (row.kind) {\n case PrincipalPolicyEdges.ROLE_EDGE: {\n lines.push(\n `${AuthorizationPolicyVariants.ROLE_INHERITS.rule}, ${principals.role}_${row.subjectId}, ${principals.role}_${row.targetId}, *`,\n );\n break;\n }\n\n case PrincipalPolicyEdges.ROLE_GRANT: {\n roleGrants.push(row);\n break;\n }\n\n case PrincipalPolicyEdges.DOMAIN_EDGE: {\n lines.push(\n `${AuthorizationPolicyVariants.DOMAIN_INHERITS.rule}, ${row.subjectId}, ${row.targetId}`,\n );\n // Both ends are, by construction, members of the principal's domain_closure CTE.\n domainClosure.add(String(row.subjectId));\n domainClosure.add(String(row.targetId));\n break;\n }\n\n default: {\n if (row.variant === AuthorizationPolicyVariants.JOIN_DOMAIN.action) {\n domainClosure.add(`${row.targetType}_${row.targetId}`);\n }\n this.collectDirectRow({ row, principal, lines, directGrants });\n break;\n }\n }\n }\n\n const hookLinesPromise = this.resolveDomainEdgeLines({\n principal,\n domains: [...domainClosure],\n });\n\n const result = await this.buildGrantLines({ subjectType: principal.type, rows: directGrants });\n lines.push(...result);\n const result2 = await this.buildGrantLines({ subjectType: principals.role, rows: roleGrants });\n lines.push(...result2);\n\n const [structuralEdges, hookLines] = await Promise.all([\n structuralEdgesPromise,\n hookLinesPromise,\n ]);\n lines.push(...structuralEdges);\n lines.push(...hookLines);\n\n await this.loadLines({ model, lines });\n }\n\n /** Route one `direct` row to its casbin line, or to the grant batch. */\n protected collectDirectRow(opts: {\n row: TPrincipalPolicyRow;\n principal: { type: string; id: IdType };\n lines: string[];\n directGrants: TGrantRow[];\n }): void {\n const { row, principal, lines, directGrants } = opts;\n const { principals } = this.entities;\n\n switch (row.variant) {\n case AuthorizationPolicyVariants.ASSIGN_ROLE.action: {\n lines.push(\n `${AuthorizationPolicyVariants.ASSIGN_ROLE.rule}, ${principal.type}_${principal.id}, ${principals.role}_${row.targetId}, ${row.domain ?? '*'}`,\n );\n break;\n }\n\n case AuthorizationPolicyVariants.JOIN_DOMAIN.action: {\n lines.push(\n `${AuthorizationPolicyVariants.JOIN_DOMAIN.rule}, ${principal.type}_${principal.id}, ${row.targetType}_${row.targetId}`,\n );\n break;\n }\n\n case AuthorizationPolicyVariants.GRANT.action: {\n directGrants.push(row);\n break;\n }\n\n default: {\n this.logger\n .for(this.collectDirectRow.name)\n .error('Unexpected variant in the direct branch | variant: %s', row.variant);\n break;\n }\n }\n }\n\n /**\n * Calls the `resolveDomainEdges` hook, if supplied, and turns its edges into `g3` lines using\n * the same shape the DOMAIN_EDGE branch emits. A throwing hook is logged and treated as no\n * edges - the rows already gathered for this principal still load. This is the safe direction:\n * a missing hierarchy edge can only narrow what `g`/`g2`/`g3` reach, never widen it, so the\n * failure degrades to less access rather than either an outage or excess access.\n */\n protected async resolveDomainEdgeLines(opts: {\n principal: { type: string; id: IdType };\n domains: string[];\n }): Promise<string[]> {\n if (!this.resolveDomainEdges) {\n return [];\n }\n\n let edges: TDomainHierarchyEdge[];\n try {\n const result = await this.resolveDomainEdges(opts);\n edges = result;\n } catch (error) {\n this.logger\n .for(this.resolveDomainEdgeLines.name)\n .error(\n 'resolveDomainEdges hook threw - continuing without its edges for this load | principal: %s_%s | error: %s',\n opts.principal.type,\n opts.principal.id,\n error,\n );\n return [];\n }\n\n return edges.map(\n (edge) =>\n `${AuthorizationPolicyVariants.DOMAIN_INHERITS.rule}, ${edge.child}, ${edge.parent}`,\n );\n }\n\n /** Schema for a table, defaulting to `public`. */\n protected schemaOf(table: { schemaName?: string }): string {\n return table.schemaName ?? DEFAULT_SCHEMA;\n }\n\n /** The casbin domain token, built from the stored pair - one expression for every SELECT so they cannot drift. NULL reaches `buildGrantLines` as `ANY_MEMBER`. The alias is emitted raw for the same reason as in `softDeleteClause`: quoting folds it to a different case than the unquoted FROM alias. */\n protected domainTokenSelection(opts: { alias: string }): SQL {\n const column = (name: string) => sql`${sql.raw(opts.alias)}.${sql.identifier(name)}`;\n const domainType = column('domain_type');\n const domainId = column('domain_id');\n\n return sql`CASE\n WHEN ${domainType} IS NULL THEN NULL\n WHEN ${domainId} IS NULL THEN ${domainType}\n ELSE ${domainType} || '_' || ${domainId}::text\n END AS \"domain\"`;\n }\n\n /** Schema-qualified table reference (`\"<schema>\".\"<table>\"`) for use after FROM/JOIN with an alias. */\n protected qualifiedTable(opts: { table: { schemaName?: string; tableName: string } }): SQL {\n const { table } = opts;\n return sql`${sql.identifier(this.schemaOf(table))}.${sql.identifier(table.tableName)}`;\n }\n\n /** `AND <alias>.<col> IS NULL` when soft-delete is on, else empty. The alias is emitted raw to match the unquoted FROM alias - quoting folds it to a different case and breaks the join. */\n protected softDeleteClause(opts: { alias: string }): SQL {\n const sd = this.entities.softDelete;\n if (!sd?.use) {\n return sql.empty();\n }\n\n return sql` AND ${sql.raw(opts.alias)}.${sql.identifier(sd.columnName)} IS NULL`;\n }\n\n /** One statement for everything scoped to a principal: its own edges, the role_inherits edges reachable from its roles, and the grants of that closure. `UNION` in the recursive term is what terminates a cyclic role graph. */\n protected async queryPrincipalPolicies(opts: {\n principal: { type: string; id: IdType };\n }): Promise<TPrincipalPolicyRow[]> {\n const { policyDefinition, permission, principals, domainTypes } = this.entities;\n const policyDefinitionTable = this.qualifiedTable({ table: policyDefinition });\n const permissionTable = this.qualifiedTable({ table: permission });\n const { principal } = opts;\n\n const metadataColumnName = policyDefinition.metadata?.columnName;\n const metadataSelection = metadataColumnName\n ? sql`, policyDefinition.${sql.identifier(metadataColumnName)} AS \"metadata\"`\n : sql.empty();\n const metadataNull = metadataColumnName ? sql`, NULL::jsonb AS \"metadata\"` : sql.empty();\n\n const domainTypeList = sql.join(\n domainTypes.map((domainType) => sql`${domainType}`),\n sql`, `,\n );\n\n const rows = await this.query<TPrincipalPolicyRow>({\n statement: sql`\n WITH RECURSIVE role_closure AS (\n SELECT policyDefinition.target_id AS role_id\n FROM ${policyDefinitionTable} policyDefinition\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ASSIGN_ROLE.action}\n AND policyDefinition.subject_type = ${principal.type}\n AND policyDefinition.subject_id = ${principal.id}\n AND policyDefinition.target_type = ${principals.role}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION\n\n SELECT policyDefinition.target_id\n FROM ${policyDefinitionTable} policyDefinition\n JOIN role_closure ON policyDefinition.subject_id = role_closure.role_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ROLE_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n ),\n\n domain_closure AS (\n SELECT policyDefinition.target_type AS dom_type, policyDefinition.target_id AS dom_id\n FROM ${policyDefinitionTable} policyDefinition\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.JOIN_DOMAIN.action}\n AND policyDefinition.subject_type = ${principal.type}\n AND policyDefinition.subject_id = ${principal.id}\n AND policyDefinition.target_type IN (${domainTypeList})${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION\n\n SELECT policyDefinition.target_type, policyDefinition.target_id\n FROM ${policyDefinitionTable} policyDefinition\n JOIN domain_closure ON policyDefinition.subject_type = domain_closure.dom_type\n AND policyDefinition.subject_id = domain_closure.dom_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.DOMAIN_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n )\n\n SELECT\n ${PrincipalPolicyEdges.DIRECT}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_id::text AS \"subjectId\",\n policyDefinition.target_type AS \"targetType\",\n policyDefinition.target_id::text AS \"targetId\",\n policyDefinition.action,\n policyDefinition.effect,\n ${this.domainTokenSelection({ alias: 'policyDefinition' })},\n permission.code AS \"objectCode\",\n permission.subject AS \"objectSubject\",\n permission.method AS \"objectMethod\"${metadataSelection}\n FROM ${policyDefinitionTable} policyDefinition\n LEFT JOIN ${permissionTable} permission\n ON policyDefinition.target_id = permission.id${this.softDeleteClause({ alias: 'permission' })}\n WHERE policyDefinition.subject_type = ${principal.type}\n AND policyDefinition.subject_id = ${principal.id}\n AND policyDefinition.variant IN (\n ${AuthorizationPolicyVariants.ASSIGN_ROLE.action},\n ${AuthorizationPolicyVariants.JOIN_DOMAIN.action},\n ${AuthorizationPolicyVariants.GRANT.action}\n )\n AND (\n policyDefinition.variant <> ${AuthorizationPolicyVariants.JOIN_DOMAIN.action}\n OR policyDefinition.target_type IN (${domainTypeList})\n )${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${PrincipalPolicyEdges.ROLE_EDGE}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_id::text AS \"subjectId\",\n policyDefinition.target_type AS \"targetType\",\n policyDefinition.target_id::text AS \"targetId\",\n NULL AS \"action\",\n NULL AS \"effect\",\n NULL AS \"domain\",\n NULL AS \"objectCode\",\n NULL AS \"objectSubject\",\n NULL AS \"objectMethod\"${metadataNull}\n FROM ${policyDefinitionTable} policyDefinition\n JOIN role_closure ON policyDefinition.subject_id = role_closure.role_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ROLE_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${PrincipalPolicyEdges.ROLE_GRANT}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_id::text AS \"subjectId\",\n policyDefinition.target_type AS \"targetType\",\n policyDefinition.target_id::text AS \"targetId\",\n policyDefinition.action,\n policyDefinition.effect,\n ${this.domainTokenSelection({ alias: 'policyDefinition' })},\n permission.code AS \"objectCode\",\n permission.subject AS \"objectSubject\",\n permission.method AS \"objectMethod\"${metadataSelection}\n FROM ${policyDefinitionTable} policyDefinition\n JOIN role_closure ON policyDefinition.subject_id = role_closure.role_id\n LEFT JOIN ${permissionTable} permission\n ON policyDefinition.target_id = permission.id${this.softDeleteClause({ alias: 'permission' })}\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.GRANT.action}\n AND policyDefinition.subject_type = ${principals.role}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${PrincipalPolicyEdges.DOMAIN_EDGE}::text AS \"kind\",\n policyDefinition.variant,\n policyDefinition.subject_type || '_' || policyDefinition.subject_id::text AS \"subjectId\",\n NULL AS \"targetType\",\n policyDefinition.target_type || '_' || policyDefinition.target_id::text AS \"targetId\",\n NULL AS \"action\",\n NULL AS \"effect\",\n NULL AS \"domain\",\n NULL AS \"objectCode\",\n NULL AS \"objectSubject\",\n NULL AS \"objectMethod\"${metadataNull}\n FROM ${policyDefinitionTable} policyDefinition\n JOIN domain_closure ON policyDefinition.subject_type = domain_closure.dom_type\n AND policyDefinition.subject_id = domain_closure.dom_id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.DOMAIN_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n `,\n });\n\n return rows;\n }\n\n /** Turn fetched grant rows into casbin lines. Shared by the direct and role-closure branches. */\n protected async buildGrantLines(opts: {\n subjectType: string;\n rows: TGrantRow[];\n }): Promise<string[]> {\n const { subjectType, rows } = opts;\n const metadataColumnName = this.entities.policyDefinition.metadata?.columnName;\n\n const lines: string[] = [];\n const customRows: TCustomGrantRow[] = [];\n\n for (const row of rows) {\n if (!row.objectCode) {\n this.logger\n .for(this.buildGrantLines.name)\n .error(\n 'Skipping grant row whose permission did not resolve - the target is missing or soft-deleted | subject: %s_%s',\n subjectType,\n row.subjectId,\n );\n continue;\n }\n\n const domain = row.domain ?? AuthorizationDomainScopes.ANY_MEMBER;\n const effect = row.effect ?? AuthorizationDecisions.ALLOW;\n const parsed = metadataColumnName\n ? GrantBuilder.getInstance().parseCustomGrantMetadata({ metadata: row.metadata })\n : null;\n const isCustomAction = row.action === AuthorizationActions.CUSTOM;\n const isCustomRow = isCustomAction || Boolean(parsed);\n\n if (!isCustomRow && !row.action) {\n this.logger\n .for(this.buildGrantLines.name)\n .error(\n 'Skipping grant row with no action - the permission it should confer is silently missing | subject: %s_%s | object: %s',\n subjectType,\n row.subjectId,\n row.objectCode,\n );\n continue;\n }\n\n if (!isCustomRow) {\n lines.push(\n `${AuthorizationPolicyVariants.GRANT.rule}, ${subjectType}_${row.subjectId}, ${domain}, ${row.objectCode}, ${row.action}, ${effect}`,\n );\n continue;\n }\n\n if (!row.objectSubject || !row.objectMethod) {\n this.logger\n .for(this.buildGrantLines.name)\n .error(\n 'Skipping custom grant row whose subject or method did not resolve - the target is missing or soft-deleted | subject: %s_%s | object: %s',\n subjectType,\n row.subjectId,\n row.objectCode,\n );\n continue;\n }\n\n const rejection = this.customGrantExpander.rejectCustomRow({\n row: {\n subjectId: row.subjectId,\n objectCode: row.objectCode,\n objectMethod: row.objectMethod,\n },\n parsed,\n isCustomAction,\n metadataColumnName,\n });\n\n if (rejection) {\n this.logger.for(this.buildGrantLines.name).error(rejection);\n continue;\n }\n\n customRows.push({\n subjectId: row.subjectId,\n objectSubject: row.objectSubject,\n ops: parsed!.ops,\n domain,\n effect,\n });\n }\n\n const expanded = await this.customGrantExpander.expandCustomGrants({ subjectType, customRows });\n for (const rejection of expanded.rejections) {\n this.logger.for(this.buildGrantLines.name).error(rejection);\n }\n lines.push(...expanded.lines);\n\n return lines;\n }\n\n /** The two code-fixed structural trees only (`g4` resource, `g5` action) - constant regardless of tenant count. Domain edges (`g3`) grow with the domain count, so they are principal-scoped in {@link queryPrincipalPolicies} instead. */\n protected async queryEdgePolicies(): Promise<string[]> {\n const { policyDefinition, permission } = this.entities;\n const policyDefinitionTable = this.qualifiedTable({ table: policyDefinition });\n const permissionTable = this.qualifiedTable({ table: permission });\n\n const rows = await this.query<{ rel: string; child: string; parent: string }>({\n statement: sql`\n SELECT\n ${AuthorizationPolicyVariants.RESOURCE_INHERITS.rule} AS \"rel\",\n child_permission.code AS \"child\",\n parent_permission.code AS \"parent\"\n FROM ${policyDefinitionTable} policyDefinition\n INNER JOIN ${permissionTable} child_permission ON policyDefinition.subject_id = child_permission.id\n INNER JOIN ${permissionTable} parent_permission ON policyDefinition.target_id = parent_permission.id\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.RESOURCE_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n\n UNION ALL\n\n SELECT\n ${AuthorizationPolicyVariants.ACTION_INHERITS.rule} AS \"rel\",\n policyDefinition.subject_id::text AS \"child\",\n policyDefinition.target_id::text AS \"parent\"\n FROM ${policyDefinitionTable} policyDefinition\n WHERE policyDefinition.variant = ${AuthorizationPolicyVariants.ACTION_INHERITS.action}${this.softDeleteClause({ alias: 'policyDefinition' })}\n `,\n });\n\n return rows.map((row) => `${row.rel}, ${row.child}, ${row.parent}`);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"casbin-module.d.ts","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin-module.ts"],"names":[],"mappings":"AAEA,iOAAiO;AACjO,qBAAa,YAAY;WACV,IAAI,IAAI,OAAO,CAAC,cAAc,QAAQ,CAAC,CAAC;CAUtD"}
1
+ {"version":3,"file":"casbin-module.d.ts","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin-module.ts"],"names":[],"mappings":"AAEA,iOAAiO;AACjO,qBAAa,YAAY;WACV,IAAI,IAAI,OAAO,CAAC,cAAc,QAAQ,CAAC,CAAC;CAWtD"}
@@ -3,7 +3,8 @@ import { getError } from '@venizia/ignis-helpers/core';
3
3
  export class CasbinModule {
4
4
  static async load() {
5
5
  try {
6
- return await import('casbin');
6
+ const result = await import('casbin');
7
+ return result;
7
8
  }
8
9
  catch {
9
10
  throw getError({
@@ -1 +1 @@
1
- {"version":3,"file":"casbin-module.js","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,iOAAiO;AACjO,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,KAAK,CAAC,IAAI;QACf,IAAI,CAAC;YACH,OAAO,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,QAAQ,CAAC;gBACb,OAAO,EACL,wGAAwG;aAC3G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF","sourcesContent":["import { getError } from '@venizia/ignis-helpers/core';\n\n/** Loads the optional peer `casbin`. The specifier stays a literal so a build embeds casbin when it is installed, and the import sits in a `try` so a build without it still succeeds - only using the casbin enforcer fails. */\nexport class CasbinModule {\n static async load(): Promise<typeof import('casbin')> {\n try {\n return await import('casbin');\n } catch {\n throw getError({\n message:\n '[CasbinModule] \"casbin\" is not installed | Install the optional peer casbin to use the casbin enforcer',\n });\n }\n }\n}\n"]}
1
+ {"version":3,"file":"casbin-module.js","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin-module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAEvD,iOAAiO;AACjO,MAAM,OAAO,YAAY;IACvB,MAAM,CAAC,KAAK,CAAC,IAAI;QACf,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YACtC,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,QAAQ,CAAC;gBACb,OAAO,EACL,wGAAwG;aAC3G,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF","sourcesContent":["import { getError } from '@venizia/ignis-helpers/core';\n\n/** Loads the optional peer `casbin`. The specifier stays a literal so a build embeds casbin when it is installed, and the import sits in a `try` so a build without it still succeeds - only using the casbin enforcer fails. */\nexport class CasbinModule {\n static async load(): Promise<typeof import('casbin')> {\n try {\n const result = await import('casbin');\n return result;\n } catch {\n throw getError({\n message:\n '[CasbinModule] \"casbin\" is not installed | Install the optional peer casbin to use the casbin enforcer',\n });\n }\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"casbin.enforcer.d.ts","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin.enforcer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"casbin.enforcer.d.ts","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin.enforcer.ts"],"names":[],"mappings":"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"}
@@ -90,9 +90,15 @@ let CasbinAuthorizationEnforcer = CasbinAuthorizationEnforcer_1 = class CasbinAu
90
90
  async buildRules(opts) {
91
91
  const { user } = opts;
92
92
  const cached = this.options.cached;
93
- const lines = cached.use
94
- ? await this.requireRedisCache().fetch({ user })
95
- : await this.extractUserLines({ user });
93
+ let lines;
94
+ if (cached.use) {
95
+ const fetched = await this.requireRedisCache().fetch({ user });
96
+ lines = fetched;
97
+ }
98
+ else {
99
+ const extracted = await this.extractUserLines({ user });
100
+ lines = extracted;
101
+ }
96
102
  return { user, lines };
97
103
  }
98
104
  async evaluate(opts) {
@@ -1 +1 @@
1
- {"version":3,"file":"casbin.enforcer.js","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin.enforcer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type TContext } from '@venizia/ignis-kernel';\nimport { inject } from '@venizia/ignis-kernel';\nimport { BaseHelper, BasePoolHelper, getError } from '@venizia/ignis-helpers/core';\nimport { type TNullable } from '@venizia/ignis-helpers/common';\nimport type {\n Enforcer as CasbinEnforcerType,\n Helper as CasbinHelperType,\n RoleManager as CasbinRoleManagerType,\n} from 'casbin';\nimport { type Env } from 'hono';\nimport { AuthorizationPermissionBuilder } from '@venizia/ignis-kernel';\nimport {\n AuthorizationDecisions,\n AuthorizationDomainScopes,\n AuthorizationEnforcerTypes,\n AuthorizationPolicyVariants,\n AuthorizeBindingKeys,\n CasbinDomainMatchingFunctions,\n CasbinEnforcerModelDrivers,\n CasbinRuleVariants,\n type IAuthorizationEnforcer,\n type IAuthorizationUser,\n type ICasbinEnforcerOptions,\n type ICasbinRules,\n type IAuthorizationRequest,\n type TAuthorizationDecision,\n type TCasbinDomainMatchingFunction,\n} from '@venizia/ignis-kernel';\nimport { DomainHierarchyRoleManager } from '../role-managers/domain-hierarchy';\nimport { CasbinModule } from './casbin-module';\nimport { MembershipRoleManager } from '../role-managers/membership';\nimport { ResourceRoleManager } from '../role-managers/resource';\nimport { PolicyLineCodec } from './policy-line-codec';\nimport { UserPolicyLineCache } from './user-policy-line-cache';\n\n/** Payload shape for the scoped/custom path, matching defaultScopedPayloadFn(). */\ntype TNormalizePayloadFn<E extends Env, TAction, TResource> = (opts: {\n user: IAuthorizationUser;\n action: TAction;\n resource: TResource;\n context: TContext<E, string>;\n}) => { subject: string; resource: string; action: string; domain?: string };\n\n/** `addDomainHierarchy` lives on casbin's `DefaultRoleManager`, not on the `RoleManager` interface or the `Enforcer` facade - feature-detect it on whatever `getNamedRoleManager` returns. */\ninterface ICasbinRoleManagerWithDomainHierarchy {\n addDomainHierarchy?(rm: CasbinRoleManagerType): Promise<void>;\n}\n\n// Wraps casbin (optional peer dep). Each request borrows its own pooled enforcer; any error during use destroys it (fail-closed). Pooled enforcers carry no adapter - only extractUserLines uses one.\n\nexport class CasbinAuthorizationEnforcer<\n E extends Env = Env,\n TAction extends string = string,\n TResource extends string = string,\n>\n extends BaseHelper\n implements IAuthorizationEnforcer<E, TAction, TResource, ICasbinRules>\n{\n name = CasbinAuthorizationEnforcer.name;\n private readonly MIN_EXPIRES_IN = 10_000;\n\n private pool: TNullable<BasePoolHelper<CasbinEnforcerType>> = null;\n private helper: TNullable<typeof CasbinHelperType> = null;\n // Lazily created on first cache use (see requireRedisCache) - one instance for the enforcer's lifetime so its single-flight de-dup map actually dedupes.\n private userPolicyLineCache: TNullable<UserPolicyLineCache> = null;\n\n // Memoized in configure() (options are fixed after) to avoid rebuilding this closure on every evaluate() (hot path).\n private resolvedPayloadFn: TNullable<TNormalizePayloadFn<E, TAction, TResource>> = null;\n\n constructor(\n @inject({ key: AuthorizeBindingKeys.enforcerOptions(AuthorizationEnforcerTypes.CASBIN) })\n private options: ICasbinEnforcerOptions<E, TAction, TResource>,\n ) {\n super({ scope: CasbinAuthorizationEnforcer.name });\n }\n\n // Lifecycle\n\n async configure(): Promise<void> {\n const casbin = await CasbinModule.load();\n\n if (!this.options.model) {\n throw getError({\n message: '[CasbinAuthorizationEnforcer] options.model is required.',\n });\n }\n\n this.helper = casbin.Helper;\n\n this.resolvedPayloadFn = this.options.normalizePayloadFn ?? this.defaultScopedPayloadFn();\n\n const { cached } = this.options;\n if (cached.use) {\n this.validateExpiresIn({ expiresIn: cached.options.expiresIn });\n }\n\n this.pool = new BasePoolHelper<CasbinEnforcerType>({\n scope: `${CasbinAuthorizationEnforcer.name}.Pool`,\n size: this.options.poolSize ?? 16,\n acquireTimeoutMs: this.options.poolAcquireTimeoutMs ?? 5000,\n create: async () => {\n const model = this.resolveModel({ casbin, model: this.options.model });\n\n const enforcer = await casbin.newEnforcer(model);\n await this.registerMatchers({ enforcer, casbin });\n this.assertMatcherCompilesSync({ enforcer });\n\n return enforcer;\n },\n });\n await this.pool.warmup();\n\n this.logger\n .for(this.configure.name)\n .info(\n 'Casbin enforcer pool ready (size: %s, cached: %s)',\n this.options.poolSize ?? 16,\n cached.use ? cached.driver : 'none',\n );\n }\n\n destroy(): void {\n this.pool?.destroy().catch((error) => {\n this.logger.for(this.destroy.name).warn('Pool destroy failed: %s', error);\n });\n }\n\n /** casbin compiles the matcher lazily (first enforce, not newEnforcer/buildRoleLinks); this dummy enforceSync forces the compile at warmup so syntax / unregistered-function / arity errors fail boot. */\n protected assertMatcherCompilesSync(opts: { enforcer: CasbinEnforcerType }) {\n try {\n if (this.options.isScoped || this.options.normalizePayloadFn) {\n opts.enforcer.enforceSync('::warmup', '::warmup', '::warmup', '::warmup');\n return;\n }\n\n opts.enforcer.enforceSync('::warmup', '::warmup', '::warmup');\n } catch (error) {\n throw getError({\n message: `[CasbinAuthorizationEnforcer] Matcher smoke test failed at warmup - the model matcher did not compile (check matcher syntax, that every referenced function is registered, and the request arity). ${String(error)}`,\n });\n }\n }\n\n // IAuthorizationEnforcer - public API\n\n async buildRules(opts: {\n user: IAuthorizationUser;\n context: TContext<E, string>;\n }): Promise<ICasbinRules> {\n const { user } = opts;\n const cached = this.options.cached;\n\n const lines = cached.use\n ? await this.requireRedisCache().fetch({ user })\n : await this.extractUserLines({ user });\n\n return { user, lines };\n }\n\n async evaluate(opts: {\n rules: ICasbinRules;\n request: IAuthorizationRequest<TAction, TResource>;\n context: TContext<E, string>;\n }): Promise<TAuthorizationDecision> {\n if (!this.pool) {\n throw getError({\n message: '[CasbinAuthorizationEnforcer] Not configured. Call configure() first.',\n });\n }\n\n if (!opts.request?.action || !opts.request?.resource) {\n throw getError({\n message: '[CasbinAuthorizationEnforcer] request.action and request.resource are required.',\n });\n }\n\n const { rules, request, context } = opts;\n const { user, lines } = rules;\n\n return this.pool.use({\n execution: async (enforcer) => {\n await this.loadPolicyLinesIntoModel({ enforcer, lines });\n\n const normalizePayloadFn = this.resolvedPayloadFn;\n\n if (!normalizePayloadFn) {\n const subject = `${user.principalType}_${user.userId}`;\n const isAllowed = this.enforceWithExplain({\n enforcer,\n vals: [subject, String(request.resource), String(request.action)],\n });\n return isAllowed ? AuthorizationDecisions.ALLOW : AuthorizationDecisions.DENY;\n }\n\n const normalized = normalizePayloadFn({\n user,\n action: request.action,\n resource: request.resource,\n context,\n });\n\n // Scoped model is 4-token (sub, dom, obj, act): a request with no resolvable domain still needs one - default SYSTEM_WIDE, never the 3-arg path, which misaligns args and silently misjudges.\n const domain =\n normalized.domain ??\n request.domain ??\n (this.options.isScoped ? AuthorizationDomainScopes.SYSTEM_WIDE : undefined);\n\n const vals = domain\n ? [normalized.subject, domain, normalized.resource, normalized.action]\n : [normalized.subject, normalized.resource, normalized.action];\n const isAllowed = this.enforceWithExplain({ enforcer, vals });\n\n return isAllowed ? AuthorizationDecisions.ALLOW : AuthorizationDecisions.DENY;\n },\n });\n }\n\n /** On DENY, logs the deciding policy rule; matchedPolicy is `[]` when nothing matched (default-deny). */\n protected enforceWithExplain(opts: { enforcer: CasbinEnforcerType; vals: string[] }): boolean {\n const [isAllowed, matchedPolicy] = opts.enforcer.enforceExSync(...opts.vals);\n\n if (!isAllowed) {\n this.logger\n .for(this.evaluate.name)\n .info(\n 'DENY | request: [%s] | matchedPolicy: %s',\n opts.vals.join(', '),\n matchedPolicy.length ? matchedPolicy.join(', ') : '<none - default-deny>',\n );\n }\n\n return isAllowed;\n }\n\n // Cache management - optional IAuthorizationEnforcer members (on-demand)\n async invalidateUserCache(opts: {\n user: IAuthorizationUser;\n }): Promise<{ invalidatedKeys: number }> {\n const { cacheKey, invalidatedKeys } = await this.requireRedisCache().invalidate({\n user: opts.user,\n });\n\n this.logger\n .for(this.invalidateUserCache.name)\n .info(\n 'Invalidated authz cache | user: %s | key: %s | deleted: %s',\n opts.user.userId,\n cacheKey,\n invalidatedKeys,\n );\n\n return { invalidatedKeys };\n }\n\n async rebuildUserCache(opts: {\n user: IAuthorizationUser;\n }): Promise<{ cacheKey: string; lineCount: number }> {\n // Extraction runs on an isolated throwaway enforcer (not a serving model), so a concurrent request cannot make us cache another user's policies under this key.\n const { cacheKey, lines } = await this.requireRedisCache().rebuild({ user: opts.user });\n\n this.logger\n .for(this.rebuildUserCache.name)\n .info(\n 'Rebuilt authz cache | user: %s | key: %s | lines: %s',\n opts.user.userId,\n cacheKey,\n lines.length,\n );\n\n return { cacheKey, lineCount: lines.length };\n }\n\n /** Narrow `options.cached` to the redis variant and lazily create the per-user line cache - memoized so its single-flight de-dup map is shared across calls rather than reset on every access. */\n protected requireRedisCache(): UserPolicyLineCache {\n const { cached } = this.options;\n\n if (!cached.use) {\n throw getError({\n message:\n '[CasbinAuthorizationEnforcer] Cache management requires the redis cache driver, but caching is disabled.',\n });\n }\n\n return (this.userPolicyLineCache ??= new UserPolicyLineCache({\n cached,\n loadLines: (opts) => this.extractUserLines(opts),\n }));\n }\n\n // Matchers & model resolvers\n\n protected async registerMatchers(opts: {\n enforcer: CasbinEnforcerType;\n casbin: typeof import('casbin');\n }): Promise<void> {\n const { enforcer, casbin } = opts;\n const { domainMatching, isScoped } = this.options;\n\n if (domainMatching) {\n if (!enforcer.getNamedRoleManager(domainMatching.roleDefinition)) {\n throw getError({\n message: `[registerMatchers] Role definition \"${domainMatching.roleDefinition}\" is not declared in the Casbin model. Declare it under [role_definition] (e.g. \\`g = _, _, _\\`) before enabling domainMatching.`,\n });\n }\n\n const matchFn = this.resolveDomainMatchingFn({ casbin, name: domainMatching.fn });\n await enforcer.addNamedDomainMatchingFunc(domainMatching.roleDefinition, matchFn);\n }\n\n if (isScoped) {\n await enforcer.addNamedDomainMatchingFunc(CasbinRuleVariants.G, casbin.Util.keyMatchFunc);\n await enforcer.addFunction('objectMatch', AuthorizationPermissionBuilder.objectMatch);\n\n // A dedicated role manager for the resource axis, NOT addNamedMatchingFunc: a matching func sets casbin's `hasPattern`, which makes every hasLink rebuild the whole g4 graph.\n enforcer.setNamedRoleManager(\n AuthorizationPolicyVariants.RESOURCE_INHERITS.rule,\n new ResourceRoleManager(),\n );\n\n // Shared across g2, g3, and the reversed `g` instance below: casbin never puts the\n // `g`-axis hierarchy manager in rmMap, so it never receives addLink and would miss\n // per-request g3 edges - g2 needs the same freshness for a just-created child domain.\n // This is a per-REQUEST overlay: `clear()` empties it every buildRoleLinks cycle, and it is\n // repopulated from whatever `g3` lines this principal's own policy line set carries.\n const domainHierarchyOverlay = new Map<string, Set<string>>();\n\n // g2 (membership) and g3 (domain nesting, request-domain-first) sit on their own axes.\n enforcer.setNamedRoleManager(\n CasbinRuleVariants.G2,\n new MembershipRoleManager({ overlay: domainHierarchyOverlay }),\n );\n\n enforcer.setNamedRoleManager(\n CasbinRuleVariants.G3,\n new DomainHierarchyRoleManager({ overlay: domainHierarchyOverlay }),\n );\n\n // addNamedDomainMatchingFunc(G, keyMatchFunc) above must stay: generateTempRoles ORs\n // hasDomainPattern with hasDomainHierarchy, and role_inherits `*` rides the keyMatch path.\n const gRoleManager = enforcer.getNamedRoleManager(CasbinRuleVariants.G) as\n | (CasbinRoleManagerType & ICasbinRoleManagerWithDomainHierarchy)\n | undefined;\n\n if (!gRoleManager?.addDomainHierarchy) {\n throw getError({\n message:\n '[registerMatchers] The \"g\" role manager does not expose addDomainHierarchy() - the scoped model requires casbin\\'s DefaultRoleManager on the g axis (present in casbin ^5.51.1, this package\\'s pinned range). Upgrade casbin, or check that a custom role manager was not substituted for \"g\".',\n });\n }\n\n await gRoleManager.addDomainHierarchy(\n new DomainHierarchyRoleManager({ reversed: true, overlay: domainHierarchyOverlay }),\n );\n }\n\n await enforcer.buildRoleLinks();\n }\n\n /** Map a CasbinDomainMatchingFunctions value to casbin's Util.*Func matcher. */\n protected resolveDomainMatchingFn(opts: {\n casbin: typeof import('casbin');\n name: TCasbinDomainMatchingFunction;\n }): (arg1: string, arg2: string) => boolean {\n // casbin Util built-ins: (requestValue, policyValue) => match. keyMatchFunc only special-cases `*` (never splits on `/` or `:`), so it cannot pattern-match a `Merchant_<uuid>`; see CasbinDomainMatchingFunctions for per-function semantics.\n const { Util } = opts.casbin;\n switch (opts.name) {\n case CasbinDomainMatchingFunctions.KEY_MATCH: {\n return Util.keyMatchFunc;\n }\n case CasbinDomainMatchingFunctions.KEY_MATCH_2: {\n return Util.keyMatch2Func;\n }\n case CasbinDomainMatchingFunctions.KEY_MATCH_3: {\n return Util.keyMatch3Func;\n }\n case CasbinDomainMatchingFunctions.KEY_MATCH_4: {\n return Util.keyMatch4Func;\n }\n case CasbinDomainMatchingFunctions.REGEX_MATCH: {\n return Util.regexMatchFunc;\n }\n default: {\n throw getError({\n message: `[resolveDomainMatchingFn] Unsupported func: ${opts.name} | Valids: [${[...CasbinDomainMatchingFunctions.SCHEME_SET].join(', ')}]`,\n });\n }\n }\n }\n\n /** Default (sub,dom,obj,act) payload for the scoped model; domain comes from request.domain. */\n protected defaultScopedPayloadFn(): TNormalizePayloadFn<E, TAction, TResource> | undefined {\n if (!this.options.isScoped) {\n return undefined;\n }\n\n return (opts: {\n user: IAuthorizationUser;\n action: TAction;\n resource: TResource;\n }): { subject: string; resource: string; action: string; domain?: string } => {\n // No domain here - evaluate() fills it from request.domain (set by the provider).\n return {\n subject: `${opts.user.principalType}_${opts.user.userId}`,\n resource: String(opts.resource),\n action: String(opts.action),\n };\n };\n }\n\n protected resolveModel(opts: {\n casbin: typeof import('casbin');\n model: ICasbinEnforcerOptions['model'];\n }) {\n const { casbin, model } = opts;\n\n switch (model.driver) {\n case CasbinEnforcerModelDrivers.FILE: {\n return casbin.newModelFromFile(model.definition);\n }\n case CasbinEnforcerModelDrivers.TEXT: {\n return casbin.newModelFromString(model.definition);\n }\n default: {\n throw getError({\n message: `[resolveModel] Invalid model.driver | Valids: [${CasbinEnforcerModelDrivers.FILE}, ${CasbinEnforcerModelDrivers.TEXT}]`,\n });\n }\n }\n }\n\n protected validateExpiresIn(opts: { expiresIn: number }): void {\n if (opts.expiresIn >= this.MIN_EXPIRES_IN) {\n return;\n }\n\n throw getError({\n message: `[CasbinAuthorizationEnforcer] cached.options.expiresIn must be >= ${this.MIN_EXPIRES_IN} (ms) | Received: ${opts.expiresIn}`,\n });\n }\n\n // Policy loading internals\n\n /** Resolves this enforcer's model, then delegates the isolated-enforcer extraction (own model + adapter, never a pooled serving one, so concurrent requests cannot change what we cache) to PolicyLineCodec. */\n protected async extractUserLines(opts: { user: IAuthorizationUser }): Promise<string[]> {\n const casbin = await CasbinModule.load();\n const model = this.resolveModel({ casbin, model: this.options.model });\n\n return PolicyLineCodec.extractUserLines({\n casbin,\n model,\n adapter: this.options.adapter,\n user: opts.user,\n });\n }\n\n /** Requires configure() to have resolved the casbin Helper; the clearPolicy + loadPolicyLine + buildRoleLinks ordering lives in PolicyLineCodec. */\n protected async loadPolicyLinesIntoModel(opts: {\n enforcer: CasbinEnforcerType;\n lines: string[];\n }): Promise<void> {\n if (!this.helper) {\n throw getError({\n message: '[loadPolicyLinesIntoModel] Not configured. Call configure() first.',\n });\n }\n\n await PolicyLineCodec.loadLinesIntoModel({\n enforcer: opts.enforcer,\n lines: opts.lines,\n helper: this.helper,\n });\n }\n}\n"]}
1
+ {"version":3,"file":"casbin.enforcer.js","sourceRoot":"","sources":["../../../../../../src/components/auth/authorize/enforcers/casbin.enforcer.ts"],"names":[],"mappings":"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","sourcesContent":["import { type TContext } from '@venizia/ignis-kernel';\nimport { inject } from '@venizia/ignis-kernel';\nimport { BaseHelper, BasePoolHelper, getError } from '@venizia/ignis-helpers/core';\nimport { type TNullable } from '@venizia/ignis-helpers/common';\nimport type {\n Enforcer as CasbinEnforcerType,\n Helper as CasbinHelperType,\n RoleManager as CasbinRoleManagerType,\n} from 'casbin';\nimport { type Env } from 'hono';\nimport { AuthorizationPermissionBuilder } from '@venizia/ignis-kernel';\nimport {\n AuthorizationDecisions,\n AuthorizationDomainScopes,\n AuthorizationEnforcerTypes,\n AuthorizationPolicyVariants,\n AuthorizeBindingKeys,\n CasbinDomainMatchingFunctions,\n CasbinEnforcerModelDrivers,\n CasbinRuleVariants,\n type IAuthorizationEnforcer,\n type IAuthorizationUser,\n type ICasbinEnforcerOptions,\n type ICasbinRules,\n type IAuthorizationRequest,\n type TAuthorizationDecision,\n type TCasbinDomainMatchingFunction,\n} from '@venizia/ignis-kernel';\nimport { DomainHierarchyRoleManager } from '../role-managers/domain-hierarchy';\nimport { CasbinModule } from './casbin-module';\nimport { MembershipRoleManager } from '../role-managers/membership';\nimport { ResourceRoleManager } from '../role-managers/resource';\nimport { PolicyLineCodec } from './policy-line-codec';\nimport { UserPolicyLineCache } from './user-policy-line-cache';\n\n/** Payload shape for the scoped/custom path, matching defaultScopedPayloadFn(). */\ntype TNormalizePayloadFn<E extends Env, TAction, TResource> = (opts: {\n user: IAuthorizationUser;\n action: TAction;\n resource: TResource;\n context: TContext<E, string>;\n}) => { subject: string; resource: string; action: string; domain?: string };\n\n/** `addDomainHierarchy` lives on casbin's `DefaultRoleManager`, not on the `RoleManager` interface or the `Enforcer` facade - feature-detect it on whatever `getNamedRoleManager` returns. */\ninterface ICasbinRoleManagerWithDomainHierarchy {\n addDomainHierarchy?(rm: CasbinRoleManagerType): Promise<void>;\n}\n\n// Wraps casbin (optional peer dep). Each request borrows its own pooled enforcer; any error during use destroys it (fail-closed). Pooled enforcers carry no adapter - only extractUserLines uses one.\n\nexport class CasbinAuthorizationEnforcer<\n E extends Env = Env,\n TAction extends string = string,\n TResource extends string = string,\n>\n extends BaseHelper\n implements IAuthorizationEnforcer<E, TAction, TResource, ICasbinRules>\n{\n name = CasbinAuthorizationEnforcer.name;\n private readonly MIN_EXPIRES_IN = 10_000;\n\n private pool: TNullable<BasePoolHelper<CasbinEnforcerType>> = null;\n private helper: TNullable<typeof CasbinHelperType> = null;\n // Lazily created on first cache use (see requireRedisCache) - one instance for the enforcer's lifetime so its single-flight de-dup map actually dedupes.\n private userPolicyLineCache: TNullable<UserPolicyLineCache> = null;\n\n // Memoized in configure() (options are fixed after) to avoid rebuilding this closure on every evaluate() (hot path).\n private resolvedPayloadFn: TNullable<TNormalizePayloadFn<E, TAction, TResource>> = null;\n\n constructor(\n @inject({ key: AuthorizeBindingKeys.enforcerOptions(AuthorizationEnforcerTypes.CASBIN) })\n private options: ICasbinEnforcerOptions<E, TAction, TResource>,\n ) {\n super({ scope: CasbinAuthorizationEnforcer.name });\n }\n\n // Lifecycle\n\n async configure(): Promise<void> {\n const casbin = await CasbinModule.load();\n\n if (!this.options.model) {\n throw getError({\n message: '[CasbinAuthorizationEnforcer] options.model is required.',\n });\n }\n\n this.helper = casbin.Helper;\n\n this.resolvedPayloadFn = this.options.normalizePayloadFn ?? this.defaultScopedPayloadFn();\n\n const { cached } = this.options;\n if (cached.use) {\n this.validateExpiresIn({ expiresIn: cached.options.expiresIn });\n }\n\n this.pool = new BasePoolHelper<CasbinEnforcerType>({\n scope: `${CasbinAuthorizationEnforcer.name}.Pool`,\n size: this.options.poolSize ?? 16,\n acquireTimeoutMs: this.options.poolAcquireTimeoutMs ?? 5000,\n create: async () => {\n const model = this.resolveModel({ casbin, model: this.options.model });\n\n const enforcer = await casbin.newEnforcer(model);\n await this.registerMatchers({ enforcer, casbin });\n this.assertMatcherCompilesSync({ enforcer });\n\n return enforcer;\n },\n });\n await this.pool.warmup();\n\n this.logger\n .for(this.configure.name)\n .info(\n 'Casbin enforcer pool ready (size: %s, cached: %s)',\n this.options.poolSize ?? 16,\n cached.use ? cached.driver : 'none',\n );\n }\n\n destroy(): void {\n this.pool?.destroy().catch((error) => {\n this.logger.for(this.destroy.name).warn('Pool destroy failed: %s', error);\n });\n }\n\n /** casbin compiles the matcher lazily (first enforce, not newEnforcer/buildRoleLinks); this dummy enforceSync forces the compile at warmup so syntax / unregistered-function / arity errors fail boot. */\n protected assertMatcherCompilesSync(opts: { enforcer: CasbinEnforcerType }) {\n try {\n if (this.options.isScoped || this.options.normalizePayloadFn) {\n opts.enforcer.enforceSync('::warmup', '::warmup', '::warmup', '::warmup');\n return;\n }\n\n opts.enforcer.enforceSync('::warmup', '::warmup', '::warmup');\n } catch (error) {\n throw getError({\n message: `[CasbinAuthorizationEnforcer] Matcher smoke test failed at warmup - the model matcher did not compile (check matcher syntax, that every referenced function is registered, and the request arity). ${String(error)}`,\n });\n }\n }\n\n // IAuthorizationEnforcer - public API\n\n async buildRules(opts: {\n user: IAuthorizationUser;\n context: TContext<E, string>;\n }): Promise<ICasbinRules> {\n const { user } = opts;\n const cached = this.options.cached;\n\n let lines: string[];\n if (cached.use) {\n const fetched = await this.requireRedisCache().fetch({ user });\n lines = fetched;\n } else {\n const extracted = await this.extractUserLines({ user });\n lines = extracted;\n }\n\n return { user, lines };\n }\n\n async evaluate(opts: {\n rules: ICasbinRules;\n request: IAuthorizationRequest<TAction, TResource>;\n context: TContext<E, string>;\n }): Promise<TAuthorizationDecision> {\n if (!this.pool) {\n throw getError({\n message: '[CasbinAuthorizationEnforcer] Not configured. Call configure() first.',\n });\n }\n\n if (!opts.request?.action || !opts.request?.resource) {\n throw getError({\n message: '[CasbinAuthorizationEnforcer] request.action and request.resource are required.',\n });\n }\n\n const { rules, request, context } = opts;\n const { user, lines } = rules;\n\n return this.pool.use({\n execution: async (enforcer) => {\n await this.loadPolicyLinesIntoModel({ enforcer, lines });\n\n const normalizePayloadFn = this.resolvedPayloadFn;\n\n if (!normalizePayloadFn) {\n const subject = `${user.principalType}_${user.userId}`;\n const isAllowed = this.enforceWithExplain({\n enforcer,\n vals: [subject, String(request.resource), String(request.action)],\n });\n return isAllowed ? AuthorizationDecisions.ALLOW : AuthorizationDecisions.DENY;\n }\n\n const normalized = normalizePayloadFn({\n user,\n action: request.action,\n resource: request.resource,\n context,\n });\n\n // Scoped model is 4-token (sub, dom, obj, act): a request with no resolvable domain still needs one - default SYSTEM_WIDE, never the 3-arg path, which misaligns args and silently misjudges.\n const domain =\n normalized.domain ??\n request.domain ??\n (this.options.isScoped ? AuthorizationDomainScopes.SYSTEM_WIDE : undefined);\n\n const vals = domain\n ? [normalized.subject, domain, normalized.resource, normalized.action]\n : [normalized.subject, normalized.resource, normalized.action];\n const isAllowed = this.enforceWithExplain({ enforcer, vals });\n\n return isAllowed ? AuthorizationDecisions.ALLOW : AuthorizationDecisions.DENY;\n },\n });\n }\n\n /** On DENY, logs the deciding policy rule; matchedPolicy is `[]` when nothing matched (default-deny). */\n protected enforceWithExplain(opts: { enforcer: CasbinEnforcerType; vals: string[] }): boolean {\n const [isAllowed, matchedPolicy] = opts.enforcer.enforceExSync(...opts.vals);\n\n if (!isAllowed) {\n this.logger\n .for(this.evaluate.name)\n .info(\n 'DENY | request: [%s] | matchedPolicy: %s',\n opts.vals.join(', '),\n matchedPolicy.length ? matchedPolicy.join(', ') : '<none - default-deny>',\n );\n }\n\n return isAllowed;\n }\n\n // Cache management - optional IAuthorizationEnforcer members (on-demand)\n async invalidateUserCache(opts: {\n user: IAuthorizationUser;\n }): Promise<{ invalidatedKeys: number }> {\n const { cacheKey, invalidatedKeys } = await this.requireRedisCache().invalidate({\n user: opts.user,\n });\n\n this.logger\n .for(this.invalidateUserCache.name)\n .info(\n 'Invalidated authz cache | user: %s | key: %s | deleted: %s',\n opts.user.userId,\n cacheKey,\n invalidatedKeys,\n );\n\n return { invalidatedKeys };\n }\n\n async rebuildUserCache(opts: {\n user: IAuthorizationUser;\n }): Promise<{ cacheKey: string; lineCount: number }> {\n // Extraction runs on an isolated throwaway enforcer (not a serving model), so a concurrent request cannot make us cache another user's policies under this key.\n const { cacheKey, lines } = await this.requireRedisCache().rebuild({ user: opts.user });\n\n this.logger\n .for(this.rebuildUserCache.name)\n .info(\n 'Rebuilt authz cache | user: %s | key: %s | lines: %s',\n opts.user.userId,\n cacheKey,\n lines.length,\n );\n\n return { cacheKey, lineCount: lines.length };\n }\n\n /** Narrow `options.cached` to the redis variant and lazily create the per-user line cache - memoized so its single-flight de-dup map is shared across calls rather than reset on every access. */\n protected requireRedisCache(): UserPolicyLineCache {\n const { cached } = this.options;\n\n if (!cached.use) {\n throw getError({\n message:\n '[CasbinAuthorizationEnforcer] Cache management requires the redis cache driver, but caching is disabled.',\n });\n }\n\n return (this.userPolicyLineCache ??= new UserPolicyLineCache({\n cached,\n loadLines: (opts) => this.extractUserLines(opts),\n }));\n }\n\n // Matchers & model resolvers\n\n protected async registerMatchers(opts: {\n enforcer: CasbinEnforcerType;\n casbin: typeof import('casbin');\n }): Promise<void> {\n const { enforcer, casbin } = opts;\n const { domainMatching, isScoped } = this.options;\n\n if (domainMatching) {\n if (!enforcer.getNamedRoleManager(domainMatching.roleDefinition)) {\n throw getError({\n message: `[registerMatchers] Role definition \"${domainMatching.roleDefinition}\" is not declared in the Casbin model. Declare it under [role_definition] (e.g. \\`g = _, _, _\\`) before enabling domainMatching.`,\n });\n }\n\n const matchFn = this.resolveDomainMatchingFn({ casbin, name: domainMatching.fn });\n await enforcer.addNamedDomainMatchingFunc(domainMatching.roleDefinition, matchFn);\n }\n\n if (isScoped) {\n await enforcer.addNamedDomainMatchingFunc(CasbinRuleVariants.G, casbin.Util.keyMatchFunc);\n await enforcer.addFunction('objectMatch', AuthorizationPermissionBuilder.objectMatch);\n\n // A dedicated role manager for the resource axis, NOT addNamedMatchingFunc: a matching func sets casbin's `hasPattern`, which makes every hasLink rebuild the whole g4 graph.\n enforcer.setNamedRoleManager(\n AuthorizationPolicyVariants.RESOURCE_INHERITS.rule,\n new ResourceRoleManager(),\n );\n\n // Shared across g2, g3, and the reversed `g` instance below: casbin never puts the\n // `g`-axis hierarchy manager in rmMap, so it never receives addLink and would miss\n // per-request g3 edges - g2 needs the same freshness for a just-created child domain.\n // This is a per-REQUEST overlay: `clear()` empties it every buildRoleLinks cycle, and it is\n // repopulated from whatever `g3` lines this principal's own policy line set carries.\n const domainHierarchyOverlay = new Map<string, Set<string>>();\n\n // g2 (membership) and g3 (domain nesting, request-domain-first) sit on their own axes.\n enforcer.setNamedRoleManager(\n CasbinRuleVariants.G2,\n new MembershipRoleManager({ overlay: domainHierarchyOverlay }),\n );\n\n enforcer.setNamedRoleManager(\n CasbinRuleVariants.G3,\n new DomainHierarchyRoleManager({ overlay: domainHierarchyOverlay }),\n );\n\n // addNamedDomainMatchingFunc(G, keyMatchFunc) above must stay: generateTempRoles ORs\n // hasDomainPattern with hasDomainHierarchy, and role_inherits `*` rides the keyMatch path.\n const gRoleManager = enforcer.getNamedRoleManager(CasbinRuleVariants.G) as\n | (CasbinRoleManagerType & ICasbinRoleManagerWithDomainHierarchy)\n | undefined;\n\n if (!gRoleManager?.addDomainHierarchy) {\n throw getError({\n message:\n '[registerMatchers] The \"g\" role manager does not expose addDomainHierarchy() - the scoped model requires casbin\\'s DefaultRoleManager on the g axis (present in casbin ^5.51.1, this package\\'s pinned range). Upgrade casbin, or check that a custom role manager was not substituted for \"g\".',\n });\n }\n\n await gRoleManager.addDomainHierarchy(\n new DomainHierarchyRoleManager({ reversed: true, overlay: domainHierarchyOverlay }),\n );\n }\n\n await enforcer.buildRoleLinks();\n }\n\n /** Map a CasbinDomainMatchingFunctions value to casbin's Util.*Func matcher. */\n protected resolveDomainMatchingFn(opts: {\n casbin: typeof import('casbin');\n name: TCasbinDomainMatchingFunction;\n }): (arg1: string, arg2: string) => boolean {\n // casbin Util built-ins: (requestValue, policyValue) => match. keyMatchFunc only special-cases `*` (never splits on `/` or `:`), so it cannot pattern-match a `Merchant_<uuid>`; see CasbinDomainMatchingFunctions for per-function semantics.\n const { Util } = opts.casbin;\n switch (opts.name) {\n case CasbinDomainMatchingFunctions.KEY_MATCH: {\n return Util.keyMatchFunc;\n }\n case CasbinDomainMatchingFunctions.KEY_MATCH_2: {\n return Util.keyMatch2Func;\n }\n case CasbinDomainMatchingFunctions.KEY_MATCH_3: {\n return Util.keyMatch3Func;\n }\n case CasbinDomainMatchingFunctions.KEY_MATCH_4: {\n return Util.keyMatch4Func;\n }\n case CasbinDomainMatchingFunctions.REGEX_MATCH: {\n return Util.regexMatchFunc;\n }\n default: {\n throw getError({\n message: `[resolveDomainMatchingFn] Unsupported func: ${opts.name} | Valids: [${[...CasbinDomainMatchingFunctions.SCHEME_SET].join(', ')}]`,\n });\n }\n }\n }\n\n /** Default (sub,dom,obj,act) payload for the scoped model; domain comes from request.domain. */\n protected defaultScopedPayloadFn(): TNormalizePayloadFn<E, TAction, TResource> | undefined {\n if (!this.options.isScoped) {\n return undefined;\n }\n\n return (opts: {\n user: IAuthorizationUser;\n action: TAction;\n resource: TResource;\n }): { subject: string; resource: string; action: string; domain?: string } => {\n // No domain here - evaluate() fills it from request.domain (set by the provider).\n return {\n subject: `${opts.user.principalType}_${opts.user.userId}`,\n resource: String(opts.resource),\n action: String(opts.action),\n };\n };\n }\n\n protected resolveModel(opts: {\n casbin: typeof import('casbin');\n model: ICasbinEnforcerOptions['model'];\n }) {\n const { casbin, model } = opts;\n\n switch (model.driver) {\n case CasbinEnforcerModelDrivers.FILE: {\n return casbin.newModelFromFile(model.definition);\n }\n case CasbinEnforcerModelDrivers.TEXT: {\n return casbin.newModelFromString(model.definition);\n }\n default: {\n throw getError({\n message: `[resolveModel] Invalid model.driver | Valids: [${CasbinEnforcerModelDrivers.FILE}, ${CasbinEnforcerModelDrivers.TEXT}]`,\n });\n }\n }\n }\n\n protected validateExpiresIn(opts: { expiresIn: number }): void {\n if (opts.expiresIn >= this.MIN_EXPIRES_IN) {\n return;\n }\n\n throw getError({\n message: `[CasbinAuthorizationEnforcer] cached.options.expiresIn must be >= ${this.MIN_EXPIRES_IN} (ms) | Received: ${opts.expiresIn}`,\n });\n }\n\n // Policy loading internals\n\n /** Resolves this enforcer's model, then delegates the isolated-enforcer extraction (own model + adapter, never a pooled serving one, so concurrent requests cannot change what we cache) to PolicyLineCodec. */\n protected async extractUserLines(opts: { user: IAuthorizationUser }): Promise<string[]> {\n const casbin = await CasbinModule.load();\n const model = this.resolveModel({ casbin, model: this.options.model });\n\n return PolicyLineCodec.extractUserLines({\n casbin,\n model,\n adapter: this.options.adapter,\n user: opts.user,\n });\n }\n\n /** Requires configure() to have resolved the casbin Helper; the clearPolicy + loadPolicyLine + buildRoleLinks ordering lives in PolicyLineCodec. */\n protected async loadPolicyLinesIntoModel(opts: {\n enforcer: CasbinEnforcerType;\n lines: string[];\n }): Promise<void> {\n if (!this.helper) {\n throw getError({\n message: '[loadPolicyLinesIntoModel] Not configured. Call configure() first.',\n });\n }\n\n await PolicyLineCodec.loadLinesIntoModel({\n enforcer: opts.enforcer,\n lines: opts.lines,\n helper: this.helper,\n });\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/components/health-check/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAY5E,qBAAa,oBAAqB,SAAQ,aAAa,CAAC,mBAAmB,CAAC;IAEpB,OAAO,CAAC,WAAW;gBAAX,WAAW,EAAE,eAAe;IAa1F;;;;OAIG;IACY,SAAS,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAmCxC"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../../../src/components/health-check/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGtD,OAAO,EAA0B,KAAK,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAY5E,qBAAa,oBAAqB,SAAQ,aAAa,CAAC,mBAAmB,CAAC;IAEpB,OAAO,CAAC,WAAW;gBAAX,WAAW,EAAE,eAAe;IAa1F;;;;OAIG;IACY,SAAS,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBpD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAqCxC"}
@@ -71,9 +71,11 @@ let HealthCheckComponent = HealthCheckComponent_1 = class HealthCheckComponent e
71
71
  }
72
72
  // `getAppInfo()` is async while the container builds the controller synchronously, so the
73
73
  // resolved value is bound here rather than resolved inside the controller.
74
- this.application
75
- .bind({ key: HealthCheckBindingKeys.APPLICATION_INFO })
76
- .toValue(await this.application.getAppInfo());
74
+ const binding = this.application.bind({
75
+ key: HealthCheckBindingKeys.APPLICATION_INFO,
76
+ });
77
+ const appInfo = await this.application.getAppInfo();
78
+ binding.toValue(appInfo);
77
79
  // The gate and the app identity are per container, but `@controller` writes the PATH onto this
78
80
  // one shared class in the process-wide MetadataRegistry, and `RestComponent` reads it back at
79
81
  // step 8. Two applications booted one after another are safe; two booted CONCURRENTLY with
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sourceRoot":"","sources":["../../../../src/components/health-check/component.ts"],"names":[],"mappings":"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","sourcesContent":["import { type BaseApplication } from '@/base/applications';\nimport { BaseComponent } from '@venizia/ignis-kernel';\nimport { controller, inject } from '@/base/metadata';\nimport { CoreBindings } from '@venizia/ignis-kernel';\nimport { HealthCheckBindingKeys, type IHealthCheckOptions } from './common';\nimport { HealthCheckController } from './controller';\nimport { HealthCheckReporter } from './reporter';\nimport { Environment } from '@venizia/ignis-helpers';\nimport { Binding } from '@venizia/ignis-kernel';\nimport type { IApplicationInfo } from '@venizia/ignis-kernel';\n\nconst DEFAULT_REST_PATH = '/health';\nconst DEFAULT_OPTIONS: IHealthCheckOptions = {\n restOptions: { path: DEFAULT_REST_PATH },\n};\n\nexport class HealthCheckComponent extends BaseComponent<IHealthCheckOptions> {\n constructor(\n @inject({ key: CoreBindings.APPLICATION_INSTANCE }) private application: BaseApplication,\n ) {\n super({\n scope: HealthCheckComponent.name,\n initDefault: { enable: true, container: application },\n bindings: {\n [HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS]: Binding.bind<IHealthCheckOptions>({\n key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,\n }).toValue(DEFAULT_OPTIONS),\n },\n });\n }\n\n /**\n * `application.component(HealthCheckComponent, { options })` lands here. Options given at the\n * call site are the most explicit statement of intent, so they take the binding over anything\n * bound earlier; `initDefaultBindings` then finds the key taken and leaves the default aside.\n */\n override async configure(opts?: IHealthCheckOptions): Promise<void> {\n // The base short-circuits a second call; binding before that check would swap the options\n // under routes that were already mounted from the first ones.\n if (this.isConfigured) {\n return;\n }\n\n if (opts !== undefined) {\n this.application\n .bind<IHealthCheckOptions>({ key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS })\n .toValue(opts);\n }\n\n await super.configure(opts);\n }\n\n override async binding(): Promise<void> {\n const healthOptions = this.application.get<IHealthCheckOptions>({\n key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,\n isOptional: true,\n });\n\n // A partially filled options binding (env/config driven) must not take the app down at boot.\n const path = healthOptions?.restOptions?.path ?? DEFAULT_REST_PATH;\n\n // Legal, occasionally correct, and silent until now: `stats.enable: true` bypasses the\n // environment gate, so the same code that opened the route for a local run opens it in\n // production. Warn rather than refuse - only the operator knows whether the port is reachable.\n if (healthOptions && HealthCheckReporter.isStatsUnguarded({ options: healthOptions })) {\n this.logger\n .for(this.binding.name)\n .warn(\n 'GET %s/stats is ENABLED with no secretKey on env \"%s\" - build stamp, runtime version and memory are readable by anything that reaches this port. Set stats.secretKey, or drop stats.enable and let the environment decide.',\n path,\n Environment.ambient ?? 'unset',\n );\n }\n\n // `getAppInfo()` is async while the container builds the controller synchronously, so the\n // resolved value is bound here rather than resolved inside the controller.\n this.application\n .bind<IApplicationInfo>({ key: HealthCheckBindingKeys.APPLICATION_INFO })\n .toValue(await this.application.getAppInfo());\n\n // The gate and the app identity are per container, but `@controller` writes the PATH onto this\n // one shared class in the process-wide MetadataRegistry, and `RestComponent` reads it back at\n // step 8. Two applications booted one after another are safe; two booted CONCURRENTLY with\n // different `restOptions.path` would race here, and nothing in this component prevents that.\n Reflect.decorate([controller({ path })], HealthCheckController);\n this.application.controller(HealthCheckController);\n }\n}\n"]}
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../../../../src/components/health-check/component.ts"],"names":[],"mappings":"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","sourcesContent":["import { type BaseApplication } from '@/base/applications';\nimport { BaseComponent } from '@venizia/ignis-kernel';\nimport { controller, inject } from '@/base/metadata';\nimport { CoreBindings } from '@venizia/ignis-kernel';\nimport { HealthCheckBindingKeys, type IHealthCheckOptions } from './common';\nimport { HealthCheckController } from './controller';\nimport { HealthCheckReporter } from './reporter';\nimport { Environment } from '@venizia/ignis-helpers';\nimport { Binding } from '@venizia/ignis-kernel';\nimport type { IApplicationInfo } from '@venizia/ignis-kernel';\n\nconst DEFAULT_REST_PATH = '/health';\nconst DEFAULT_OPTIONS: IHealthCheckOptions = {\n restOptions: { path: DEFAULT_REST_PATH },\n};\n\nexport class HealthCheckComponent extends BaseComponent<IHealthCheckOptions> {\n constructor(\n @inject({ key: CoreBindings.APPLICATION_INSTANCE }) private application: BaseApplication,\n ) {\n super({\n scope: HealthCheckComponent.name,\n initDefault: { enable: true, container: application },\n bindings: {\n [HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS]: Binding.bind<IHealthCheckOptions>({\n key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,\n }).toValue(DEFAULT_OPTIONS),\n },\n });\n }\n\n /**\n * `application.component(HealthCheckComponent, { options })` lands here. Options given at the\n * call site are the most explicit statement of intent, so they take the binding over anything\n * bound earlier; `initDefaultBindings` then finds the key taken and leaves the default aside.\n */\n override async configure(opts?: IHealthCheckOptions): Promise<void> {\n // The base short-circuits a second call; binding before that check would swap the options\n // under routes that were already mounted from the first ones.\n if (this.isConfigured) {\n return;\n }\n\n if (opts !== undefined) {\n this.application\n .bind<IHealthCheckOptions>({ key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS })\n .toValue(opts);\n }\n\n await super.configure(opts);\n }\n\n override async binding(): Promise<void> {\n const healthOptions = this.application.get<IHealthCheckOptions>({\n key: HealthCheckBindingKeys.HEALTH_CHECK_OPTIONS,\n isOptional: true,\n });\n\n // A partially filled options binding (env/config driven) must not take the app down at boot.\n const path = healthOptions?.restOptions?.path ?? DEFAULT_REST_PATH;\n\n // Legal, occasionally correct, and silent until now: `stats.enable: true` bypasses the\n // environment gate, so the same code that opened the route for a local run opens it in\n // production. Warn rather than refuse - only the operator knows whether the port is reachable.\n if (healthOptions && HealthCheckReporter.isStatsUnguarded({ options: healthOptions })) {\n this.logger\n .for(this.binding.name)\n .warn(\n 'GET %s/stats is ENABLED with no secretKey on env \"%s\" - build stamp, runtime version and memory are readable by anything that reaches this port. Set stats.secretKey, or drop stats.enable and let the environment decide.',\n path,\n Environment.ambient ?? 'unset',\n );\n }\n\n // `getAppInfo()` is async while the container builds the controller synchronously, so the\n // resolved value is bound here rather than resolved inside the controller.\n const binding = this.application.bind<IApplicationInfo>({\n key: HealthCheckBindingKeys.APPLICATION_INFO,\n });\n const appInfo = await this.application.getAppInfo();\n binding.toValue(appInfo);\n\n // The gate and the app identity are per container, but `@controller` writes the PATH onto this\n // one shared class in the process-wide MetadataRegistry, and `RestComponent` reads it back at\n // step 8. Two applications booted one after another are safe; two booted CONCURRENTLY with\n // different `restOptions.path` would race here, and nothing in this component prevents that.\n Reflect.decorate([controller({ path })], HealthCheckController);\n this.application.controller(HealthCheckController);\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"bull-mq-executor.helper.d.ts","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/executors/bull-mq-executor.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,EACV,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAEjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EAIpB,MAAM,cAAc,CAAC;AAGtB,qBAAa,wBAAyB,SAAQ,UAAW,YAAW,kBAAkB;IACpF,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAA0C;IAEtD,OAAO,CAAC,WAAW,CAAC,CAAmD;IACvE,OAAO,CAAC,aAAa,CAA8D;IACnF,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAA0B;IACxD,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,SAAS,CAAC,CAAmD;gBAEzD,IAAI,EAAE,uBAAuB;IAiBzC,SAAS,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAmC/C,YAAY,CAChB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,EAC3D,IAAI,CAAC,EAAE;QACL,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GACA,OAAO,CAAC,IAAI,CAAC;IAkChB,SAAS,CAAC,IAAI,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAsG1F,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBnD,6JAA6J;YAC/I,YAAY;IA2BpB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,sLAAsL;IAChL,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAkC5B,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,WAAW,CAAC,OAAO,mBAAmB,CAAC;IAI5C,wBAAwB,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC;CAqD7B"}
1
+ {"version":3,"file":"bull-mq-executor.helper.d.ts","sourceRoot":"","sources":["../../../../../../src/components/mail/helpers/executors/bull-mq-executor.helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAY,MAAM,6BAA6B,CAAC;AAEnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,KAAK,EACV,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAEjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,mBAAmB,EAIpB,MAAM,cAAc,CAAC;AAGtB,qBAAa,wBAAyB,SAAQ,UAAW,YAAW,kBAAkB;IACpF,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAA0C;IAEtD,OAAO,CAAC,WAAW,CAAC,CAAmD;IACvE,OAAO,CAAC,aAAa,CAA8D;IACnF,OAAO,CAAC,eAAe,CAAoB;IAC3C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,CAA0B;IACxD,OAAO,CAAC,YAAY,CAAK;IAEzB,OAAO,CAAC,SAAS,CAAC,CAAmD;gBAEzD,IAAI,EAAE,uBAAuB;IAiBzC,SAAS,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE;IAmC/C,YAAY,CAChB,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,oBAAoB,CAAC,EAC3D,IAAI,CAAC,EAAE;QACL,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GACA,OAAO,CAAC,IAAI,CAAC;IAkChB,SAAS,CAAC,IAAI,EAAE;QAAE,gBAAgB,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAsG1F,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBnD,6JAA6J;YAC/I,YAAY;IA2BpB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAOnC,sLAAsL;IAChL,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAmC5B,cAAc,IAAI,MAAM;IAIxB,OAAO,IAAI,WAAW,CAAC,OAAO,mBAAmB,CAAC;IAI5C,wBAAwB,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,gBAAgB,CAAC;CAqD7B"}
@@ -163,7 +163,8 @@ export class BullMQMailExecutorHelper extends BaseHelper {
163
163
  }
164
164
  /** Full teardown: workers -> queue -> Redis. Every step runs even if an earlier one failed (skipping leaks a queue client + Redis socket); failures are reported once, at the end. */
165
165
  async close() {
166
- const failures = [...(await this.closeWorkers())];
166
+ const result = await this.closeWorkers();
167
+ const failures = [...result];
167
168
  if (this.queueHelper) {
168
169
  try {
169
170
  await this.queueHelper.queue.close();