@endora-commerce/platform 0.100.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.
- package/LICENSE +21 -0
- package/README.md +58 -0
- package/dist/cli/dispatch.d.ts +146 -0
- package/dist/cli/dispatch.d.ts.map +1 -0
- package/dist/cli/dispatch.js +259 -0
- package/dist/cli/dispatch.js.map +1 -0
- package/dist/cli/index.d.ts +58 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +58 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/module-commands.d.ts +118 -0
- package/dist/cli/module-commands.d.ts.map +1 -0
- package/dist/cli/module-commands.js +120 -0
- package/dist/cli/module-commands.js.map +1 -0
- package/dist/commands/actor.d.ts +19 -0
- package/dist/commands/actor.d.ts.map +1 -0
- package/dist/commands/actor.js +45 -0
- package/dist/commands/actor.js.map +1 -0
- package/dist/commands/audit-from-context.d.ts +24 -0
- package/dist/commands/audit-from-context.d.ts.map +1 -0
- package/dist/commands/audit-from-context.js +28 -0
- package/dist/commands/audit-from-context.js.map +1 -0
- package/dist/commands/command-bus.d.ts +40 -0
- package/dist/commands/command-bus.d.ts.map +1 -0
- package/dist/commands/command-bus.js +46 -0
- package/dist/commands/command-bus.js.map +1 -0
- package/dist/commands/command.d.ts +76 -0
- package/dist/commands/command.d.ts.map +1 -0
- package/dist/commands/command.js +2 -0
- package/dist/commands/command.js.map +1 -0
- package/dist/commands/index.d.ts +65 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +57 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/reversible.d.ts +66 -0
- package/dist/commands/reversible.d.ts.map +1 -0
- package/dist/commands/reversible.js +41 -0
- package/dist/commands/reversible.js.map +1 -0
- package/dist/composition/compose-app.d.ts +305 -0
- package/dist/composition/compose-app.d.ts.map +1 -0
- package/dist/composition/compose-app.js +939 -0
- package/dist/composition/compose-app.js.map +1 -0
- package/dist/composition/index.d.ts +92 -0
- package/dist/composition/index.d.ts.map +1 -0
- package/dist/composition/index.js +175 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/composition/newsletter-token-secret.d.ts +19 -0
- package/dist/composition/newsletter-token-secret.d.ts.map +1 -0
- package/dist/composition/newsletter-token-secret.js +24 -0
- package/dist/composition/newsletter-token-secret.js.map +1 -0
- package/dist/composition/process-runs-workers.d.ts +17 -0
- package/dist/composition/process-runs-workers.d.ts.map +1 -0
- package/dist/composition/process-runs-workers.js +19 -0
- package/dist/composition/process-runs-workers.js.map +1 -0
- package/dist/db/baseline-migration-inventory.d.ts +15 -0
- package/dist/db/baseline-migration-inventory.d.ts.map +1 -0
- package/dist/db/baseline-migration-inventory.js +115 -0
- package/dist/db/baseline-migration-inventory.js.map +1 -0
- package/dist/db/configured-entities.d.ts +74 -0
- package/dist/db/configured-entities.d.ts.map +1 -0
- package/dist/db/configured-entities.js +20 -0
- package/dist/db/configured-entities.js.map +1 -0
- package/dist/db/configured-migrations.d.ts +199 -0
- package/dist/db/configured-migrations.d.ts.map +1 -0
- package/dist/db/configured-migrations.js +181 -0
- package/dist/db/configured-migrations.js.map +1 -0
- package/dist/db/index.d.ts +54 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +54 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrate.d.ts +21 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/migrate.js +48 -0
- package/dist/db/migrate.js.map +1 -0
- package/dist/db/migration-order.d.ts +159 -0
- package/dist/db/migration-order.d.ts.map +1 -0
- package/dist/db/migration-order.js +273 -0
- package/dist/db/migration-order.js.map +1 -0
- package/dist/db/mikro-orm.config.d.ts +51 -0
- package/dist/db/mikro-orm.config.d.ts.map +1 -0
- package/dist/db/mikro-orm.config.js +64 -0
- package/dist/db/mikro-orm.config.js.map +1 -0
- package/dist/db/orm.d.ts +40 -0
- package/dist/db/orm.d.ts.map +1 -0
- package/dist/db/orm.js +25 -0
- package/dist/db/orm.js.map +1 -0
- package/dist/db/platform-schema.d.ts +102 -0
- package/dist/db/platform-schema.d.ts.map +1 -0
- package/dist/db/platform-schema.js +79 -0
- package/dist/db/platform-schema.js.map +1 -0
- package/dist/db/pluralizing-naming-strategy.d.ts +16 -0
- package/dist/db/pluralizing-naming-strategy.d.ts.map +1 -0
- package/dist/db/pluralizing-naming-strategy.js +66 -0
- package/dist/db/pluralizing-naming-strategy.js.map +1 -0
- package/dist/demo/guard.d.ts +101 -0
- package/dist/demo/guard.d.ts.map +1 -0
- package/dist/demo/guard.js +168 -0
- package/dist/demo/guard.js.map +1 -0
- package/dist/demo/host-command.d.ts +133 -0
- package/dist/demo/host-command.d.ts.map +1 -0
- package/dist/demo/host-command.js +113 -0
- package/dist/demo/host-command.js.map +1 -0
- package/dist/demo/index.d.ts +82 -0
- package/dist/demo/index.d.ts.map +1 -0
- package/dist/demo/index.js +82 -0
- package/dist/demo/index.js.map +1 -0
- package/dist/demo/packages.d.ts +67 -0
- package/dist/demo/packages.d.ts.map +1 -0
- package/dist/demo/packages.js +132 -0
- package/dist/demo/packages.js.map +1 -0
- package/dist/demo/plan.d.ts +111 -0
- package/dist/demo/plan.d.ts.map +1 -0
- package/dist/demo/plan.js +74 -0
- package/dist/demo/plan.js.map +1 -0
- package/dist/demo/report.d.ts +17 -0
- package/dist/demo/report.d.ts.map +1 -0
- package/dist/demo/report.js +85 -0
- package/dist/demo/report.js.map +1 -0
- package/dist/demo/runner.d.ts +207 -0
- package/dist/demo/runner.d.ts.map +1 -0
- package/dist/demo/runner.js +169 -0
- package/dist/demo/runner.js.map +1 -0
- package/dist/demo/scope.d.ts +44 -0
- package/dist/demo/scope.d.ts.map +1 -0
- package/dist/demo/scope.js +44 -0
- package/dist/demo/scope.js.map +1 -0
- package/dist/env/index.d.ts +68 -0
- package/dist/env/index.d.ts.map +1 -0
- package/dist/env/index.js +427 -0
- package/dist/env/index.js.map +1 -0
- package/dist/events/bus.d.ts +29 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +67 -0
- package/dist/events/bus.js.map +1 -0
- package/dist/events/index.d.ts +19 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +19 -0
- package/dist/events/index.js.map +1 -0
- package/dist/http/cursor.d.ts +10 -0
- package/dist/http/cursor.d.ts.map +1 -0
- package/dist/http/cursor.js +20 -0
- package/dist/http/cursor.js.map +1 -0
- package/dist/http/error-envelope.d.ts +127 -0
- package/dist/http/error-envelope.d.ts.map +1 -0
- package/dist/http/error-envelope.js +402 -0
- package/dist/http/error-envelope.js.map +1 -0
- package/dist/http/health.d.ts +88 -0
- package/dist/http/health.d.ts.map +1 -0
- package/dist/http/health.js +77 -0
- package/dist/http/health.js.map +1 -0
- package/dist/http/index.d.ts +50 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +50 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/interceptors/dispatch.d.ts +14 -0
- package/dist/http/interceptors/dispatch.d.ts.map +1 -0
- package/dist/http/interceptors/dispatch.js +113 -0
- package/dist/http/interceptors/dispatch.js.map +1 -0
- package/dist/http/interceptors/index.d.ts +6 -0
- package/dist/http/interceptors/index.d.ts.map +1 -0
- package/dist/http/interceptors/index.js +5 -0
- package/dist/http/interceptors/index.js.map +1 -0
- package/dist/http/interceptors/registry.d.ts +44 -0
- package/dist/http/interceptors/registry.d.ts.map +1 -0
- package/dist/http/interceptors/registry.js +123 -0
- package/dist/http/interceptors/registry.js.map +1 -0
- package/dist/http/interceptors/route-table.d.ts +33 -0
- package/dist/http/interceptors/route-table.d.ts.map +1 -0
- package/dist/http/interceptors/route-table.js +39 -0
- package/dist/http/interceptors/route-table.js.map +1 -0
- package/dist/http/interceptors/types.d.ts +101 -0
- package/dist/http/interceptors/types.d.ts.map +1 -0
- package/dist/http/interceptors/types.js +2 -0
- package/dist/http/interceptors/types.js.map +1 -0
- package/dist/http/interceptors/validation.d.ts +22 -0
- package/dist/http/interceptors/validation.d.ts.map +1 -0
- package/dist/http/interceptors/validation.js +39 -0
- package/dist/http/interceptors/validation.js.map +1 -0
- package/dist/http/logger.d.ts +9 -0
- package/dist/http/logger.d.ts.map +1 -0
- package/dist/http/logger.js +25 -0
- package/dist/http/logger.js.map +1 -0
- package/dist/http/openapi.d.ts +21 -0
- package/dist/http/openapi.d.ts.map +1 -0
- package/dist/http/openapi.js +114 -0
- package/dist/http/openapi.js.map +1 -0
- package/dist/http/product-audience.d.ts +78 -0
- package/dist/http/product-audience.d.ts.map +1 -0
- package/dist/http/product-audience.js +92 -0
- package/dist/http/product-audience.js.map +1 -0
- package/dist/http/request-actor.d.ts +82 -0
- package/dist/http/request-actor.d.ts.map +1 -0
- package/dist/http/request-actor.js +2 -0
- package/dist/http/request-actor.js.map +1 -0
- package/dist/http/server.d.ts +60 -0
- package/dist/http/server.d.ts.map +1 -0
- package/dist/http/server.js +117 -0
- package/dist/http/server.js.map +1 -0
- package/dist/http/storefront-revalidator.d.ts +29 -0
- package/dist/http/storefront-revalidator.d.ts.map +1 -0
- package/dist/http/storefront-revalidator.js +34 -0
- package/dist/http/storefront-revalidator.js.map +1 -0
- package/dist/http/test-actor-carrier.d.ts +28 -0
- package/dist/http/test-actor-carrier.d.ts.map +1 -0
- package/dist/http/test-actor-carrier.js +10 -0
- package/dist/http/test-actor-carrier.js.map +1 -0
- package/dist/http/trusted-proxy.d.ts +48 -0
- package/dist/http/trusted-proxy.d.ts.map +1 -0
- package/dist/http/trusted-proxy.js +136 -0
- package/dist/http/trusted-proxy.js.map +1 -0
- package/dist/kernel/audit/audit-log-entry.entity.d.ts +33 -0
- package/dist/kernel/audit/audit-log-entry.entity.d.ts.map +1 -0
- package/dist/kernel/audit/audit-log-entry.entity.js +102 -0
- package/dist/kernel/audit/audit-log-entry.entity.js.map +1 -0
- package/dist/kernel/audit/audit-log-service.d.ts +63 -0
- package/dist/kernel/audit/audit-log-service.d.ts.map +1 -0
- package/dist/kernel/audit/audit-log-service.js +107 -0
- package/dist/kernel/audit/audit-log-service.js.map +1 -0
- package/dist/kernel/cache/in-process-cache-registry.d.ts +93 -0
- package/dist/kernel/cache/in-process-cache-registry.d.ts.map +1 -0
- package/dist/kernel/cache/in-process-cache-registry.js +78 -0
- package/dist/kernel/cache/in-process-cache-registry.js.map +1 -0
- package/dist/kernel/cache/shared-drop-marks.d.ts +39 -0
- package/dist/kernel/cache/shared-drop-marks.d.ts.map +1 -0
- package/dist/kernel/cache/shared-drop-marks.js +68 -0
- package/dist/kernel/cache/shared-drop-marks.js.map +1 -0
- package/dist/kernel/compose.d.ts +234 -0
- package/dist/kernel/compose.d.ts.map +1 -0
- package/dist/kernel/compose.js +279 -0
- package/dist/kernel/compose.js.map +1 -0
- package/dist/kernel/container.d.ts +95 -0
- package/dist/kernel/container.d.ts.map +1 -0
- package/dist/kernel/container.js +90 -0
- package/dist/kernel/container.js.map +1 -0
- package/dist/kernel/contribution-sinks.d.ts +106 -0
- package/dist/kernel/contribution-sinks.d.ts.map +1 -0
- package/dist/kernel/contribution-sinks.js +153 -0
- package/dist/kernel/contribution-sinks.js.map +1 -0
- package/dist/kernel/crypto/password-hasher.d.ts +3 -0
- package/dist/kernel/crypto/password-hasher.d.ts.map +1 -0
- package/dist/kernel/crypto/password-hasher.js +44 -0
- package/dist/kernel/crypto/password-hasher.js.map +1 -0
- package/dist/kernel/i18n/error-envelope-options.d.ts +56 -0
- package/dist/kernel/i18n/error-envelope-options.d.ts.map +1 -0
- package/dist/kernel/i18n/error-envelope-options.js +46 -0
- package/dist/kernel/i18n/error-envelope-options.js.map +1 -0
- package/dist/kernel/i18n/error-translation.d.ts +144 -0
- package/dist/kernel/i18n/error-translation.d.ts.map +1 -0
- package/dist/kernel/i18n/error-translation.js +84 -0
- package/dist/kernel/i18n/error-translation.js.map +1 -0
- package/dist/kernel/i18n/request-language.d.ts +80 -0
- package/dist/kernel/i18n/request-language.d.ts.map +1 -0
- package/dist/kernel/i18n/request-language.js +168 -0
- package/dist/kernel/i18n/request-language.js.map +1 -0
- package/dist/kernel/index.d.ts +142 -0
- package/dist/kernel/index.d.ts.map +1 -0
- package/dist/kernel/index.js +160 -0
- package/dist/kernel/index.js.map +1 -0
- package/dist/kernel/lazy-port.d.ts +59 -0
- package/dist/kernel/lazy-port.d.ts.map +1 -0
- package/dist/kernel/lazy-port.js +78 -0
- package/dist/kernel/lazy-port.js.map +1 -0
- package/dist/kernel/lifecycle/activation-resolver.d.ts +63 -0
- package/dist/kernel/lifecycle/activation-resolver.d.ts.map +1 -0
- package/dist/kernel/lifecycle/activation-resolver.js +70 -0
- package/dist/kernel/lifecycle/activation-resolver.js.map +1 -0
- package/dist/kernel/lifecycle/capability-registry.d.ts +145 -0
- package/dist/kernel/lifecycle/capability-registry.d.ts.map +1 -0
- package/dist/kernel/lifecycle/capability-registry.js +170 -0
- package/dist/kernel/lifecycle/capability-registry.js.map +1 -0
- package/dist/kernel/lifecycle/effective-state.d.ts +126 -0
- package/dist/kernel/lifecycle/effective-state.d.ts.map +1 -0
- package/dist/kernel/lifecycle/effective-state.js +111 -0
- package/dist/kernel/lifecycle/effective-state.js.map +1 -0
- package/dist/kernel/lifecycle/module-registration.entity.d.ts +57 -0
- package/dist/kernel/lifecycle/module-registration.entity.d.ts.map +1 -0
- package/dist/kernel/lifecycle/module-registration.entity.js +111 -0
- package/dist/kernel/lifecycle/module-registration.entity.js.map +1 -0
- package/dist/kernel/lifecycle/plugin-helpers.d.ts +165 -0
- package/dist/kernel/lifecycle/plugin-helpers.d.ts.map +1 -0
- package/dist/kernel/lifecycle/plugin-helpers.js +395 -0
- package/dist/kernel/lifecycle/plugin-helpers.js.map +1 -0
- package/dist/kernel/lifecycle/registry-cache.d.ts +318 -0
- package/dist/kernel/lifecycle/registry-cache.d.ts.map +1 -0
- package/dist/kernel/lifecycle/registry-cache.js +509 -0
- package/dist/kernel/lifecycle/registry-cache.js.map +1 -0
- package/dist/kernel/lifecycle/required-modules.d.ts +137 -0
- package/dist/kernel/lifecycle/required-modules.d.ts.map +1 -0
- package/dist/kernel/lifecycle/required-modules.js +80 -0
- package/dist/kernel/lifecycle/required-modules.js.map +1 -0
- package/dist/kernel/lifecycle/unique-module-ids.d.ts +58 -0
- package/dist/kernel/lifecycle/unique-module-ids.d.ts.map +1 -0
- package/dist/kernel/lifecycle/unique-module-ids.js +82 -0
- package/dist/kernel/lifecycle/unique-module-ids.js.map +1 -0
- package/dist/kernel/logging.d.ts +116 -0
- package/dist/kernel/logging.d.ts.map +1 -0
- package/dist/kernel/logging.js +71 -0
- package/dist/kernel/logging.js.map +1 -0
- package/dist/kernel/module-context.d.ts +563 -0
- package/dist/kernel/module-context.d.ts.map +1 -0
- package/dist/kernel/module-context.js +670 -0
- package/dist/kernel/module-context.js.map +1 -0
- package/dist/kernel/ports/audit.d.ts +115 -0
- package/dist/kernel/ports/audit.d.ts.map +1 -0
- package/dist/kernel/ports/audit.js +2 -0
- package/dist/kernel/ports/audit.js.map +1 -0
- package/dist/kernel/ports/organizations.d.ts +56 -0
- package/dist/kernel/ports/organizations.d.ts.map +1 -0
- package/dist/kernel/ports/organizations.js +2 -0
- package/dist/kernel/ports/organizations.js.map +1 -0
- package/dist/kernel/ports/provide.d.ts +14 -0
- package/dist/kernel/ports/provide.d.ts.map +1 -0
- package/dist/kernel/ports/provide.js +50 -0
- package/dist/kernel/ports/provide.js.map +1 -0
- package/dist/kernel/ports/require-admin.d.ts +61 -0
- package/dist/kernel/ports/require-admin.d.ts.map +1 -0
- package/dist/kernel/ports/require-admin.js +2 -0
- package/dist/kernel/ports/require-admin.js.map +1 -0
- package/dist/kernel/ports/require-customer.d.ts +17 -0
- package/dist/kernel/ports/require-customer.d.ts.map +1 -0
- package/dist/kernel/ports/require-customer.js +2 -0
- package/dist/kernel/ports/require-customer.js.map +1 -0
- package/dist/kernel/ports/sales-channel.d.ts +84 -0
- package/dist/kernel/ports/sales-channel.d.ts.map +1 -0
- package/dist/kernel/ports/sales-channel.js +2 -0
- package/dist/kernel/ports/sales-channel.js.map +1 -0
- package/dist/kernel/ports/settings.d.ts +59 -0
- package/dist/kernel/ports/settings.d.ts.map +1 -0
- package/dist/kernel/ports/settings.js +2 -0
- package/dist/kernel/ports/settings.js.map +1 -0
- package/dist/kernel/public-api-base-url.d.ts +98 -0
- package/dist/kernel/public-api-base-url.d.ts.map +1 -0
- package/dist/kernel/public-api-base-url.js +144 -0
- package/dist/kernel/public-api-base-url.js.map +1 -0
- package/dist/kernel/request-scope-hook.d.ts +63 -0
- package/dist/kernel/request-scope-hook.d.ts.map +1 -0
- package/dist/kernel/request-scope-hook.js +67 -0
- package/dist/kernel/request-scope-hook.js.map +1 -0
- package/dist/kernel/sales-channels/channel-bridge-registry.d.ts +109 -0
- package/dist/kernel/sales-channels/channel-bridge-registry.d.ts.map +1 -0
- package/dist/kernel/sales-channels/channel-bridge-registry.js +75 -0
- package/dist/kernel/sales-channels/channel-bridge-registry.js.map +1 -0
- package/dist/kernel/sales-channels/compose.d.ts +69 -0
- package/dist/kernel/sales-channels/compose.d.ts.map +1 -0
- package/dist/kernel/sales-channels/compose.js +43 -0
- package/dist/kernel/sales-channels/compose.js.map +1 -0
- package/dist/kernel/sales-channels/default-channel-reconciler.d.ts +66 -0
- package/dist/kernel/sales-channels/default-channel-reconciler.d.ts.map +1 -0
- package/dist/kernel/sales-channels/default-channel-reconciler.js +91 -0
- package/dist/kernel/sales-channels/default-channel-reconciler.js.map +1 -0
- package/dist/kernel/sales-channels/no-system-default-channel.error.d.ts +28 -0
- package/dist/kernel/sales-channels/no-system-default-channel.error.d.ts.map +1 -0
- package/dist/kernel/sales-channels/no-system-default-channel.error.js +33 -0
- package/dist/kernel/sales-channels/no-system-default-channel.error.js.map +1 -0
- package/dist/kernel/sales-channels/request-channel-assortment.d.ts +72 -0
- package/dist/kernel/sales-channels/request-channel-assortment.d.ts.map +1 -0
- package/dist/kernel/sales-channels/request-channel-assortment.js +83 -0
- package/dist/kernel/sales-channels/request-channel-assortment.js.map +1 -0
- package/dist/kernel/sales-channels/sales-channel-membership.service.d.ts +157 -0
- package/dist/kernel/sales-channels/sales-channel-membership.service.d.ts.map +1 -0
- package/dist/kernel/sales-channels/sales-channel-membership.service.js +302 -0
- package/dist/kernel/sales-channels/sales-channel-membership.service.js.map +1 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.middleware.d.ts +76 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.middleware.d.ts.map +1 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.middleware.js +184 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.middleware.js.map +1 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.service.d.ts +82 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.service.d.ts.map +1 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.service.js +126 -0
- package/dist/kernel/sales-channels/sales-channel-resolver.service.js.map +1 -0
- package/dist/kernel/sales-channels/sales-channel.entity.d.ts +50 -0
- package/dist/kernel/sales-channels/sales-channel.entity.d.ts.map +1 -0
- package/dist/kernel/sales-channels/sales-channel.entity.js +132 -0
- package/dist/kernel/sales-channels/sales-channel.entity.js.map +1 -0
- package/dist/kernel/sales-channels/sales-channels-cache.d.ts +170 -0
- package/dist/kernel/sales-channels/sales-channels-cache.d.ts.map +1 -0
- package/dist/kernel/sales-channels/sales-channels-cache.js +243 -0
- package/dist/kernel/sales-channels/sales-channels-cache.js.map +1 -0
- package/dist/kernel/scope.d.ts +153 -0
- package/dist/kernel/scope.d.ts.map +1 -0
- package/dist/kernel/scope.js +172 -0
- package/dist/kernel/scope.js.map +1 -0
- package/dist/kernel/settings/compose.d.ts +49 -0
- package/dist/kernel/settings/compose.d.ts.map +1 -0
- package/dist/kernel/settings/compose.js +21 -0
- package/dist/kernel/settings/compose.js.map +1 -0
- package/dist/kernel/settings/manifest-reconciler.d.ts +78 -0
- package/dist/kernel/settings/manifest-reconciler.d.ts.map +1 -0
- package/dist/kernel/settings/manifest-reconciler.js +343 -0
- package/dist/kernel/settings/manifest-reconciler.js.map +1 -0
- package/dist/kernel/settings/secret-value-codec.d.ts +52 -0
- package/dist/kernel/settings/secret-value-codec.d.ts.map +1 -0
- package/dist/kernel/settings/secret-value-codec.js +102 -0
- package/dist/kernel/settings/secret-value-codec.js.map +1 -0
- package/dist/kernel/settings/setting-group.entity.d.ts +25 -0
- package/dist/kernel/settings/setting-group.entity.d.ts.map +1 -0
- package/dist/kernel/settings/setting-group.entity.js +79 -0
- package/dist/kernel/settings/setting-group.entity.js.map +1 -0
- package/dist/kernel/settings/setting-value.entity.d.ts +23 -0
- package/dist/kernel/settings/setting-value.entity.d.ts.map +1 -0
- package/dist/kernel/settings/setting-value.entity.js +66 -0
- package/dist/kernel/settings/setting-value.entity.js.map +1 -0
- package/dist/kernel/settings/setting.entity.d.ts +56 -0
- package/dist/kernel/settings/setting.entity.d.ts.map +1 -0
- package/dist/kernel/settings/setting.entity.js +147 -0
- package/dist/kernel/settings/setting.entity.js.map +1 -0
- package/dist/kernel/settings/settings-cache.d.ts +158 -0
- package/dist/kernel/settings/settings-cache.d.ts.map +1 -0
- package/dist/kernel/settings/settings-cache.js +253 -0
- package/dist/kernel/settings/settings-cache.js.map +1 -0
- package/dist/kernel/settings/settings.service.d.ts +142 -0
- package/dist/kernel/settings/settings.service.d.ts.map +1 -0
- package/dist/kernel/settings/settings.service.js +294 -0
- package/dist/kernel/settings/settings.service.js.map +1 -0
- package/dist/lifecycle/backend.d.ts +51 -0
- package/dist/lifecycle/backend.d.ts.map +1 -0
- package/dist/lifecycle/backend.js +40 -0
- package/dist/lifecycle/backend.js.map +1 -0
- package/dist/lifecycle/commands/activation.commands.d.ts +97 -0
- package/dist/lifecycle/commands/activation.commands.d.ts.map +1 -0
- package/dist/lifecycle/commands/activation.commands.js +142 -0
- package/dist/lifecycle/commands/activation.commands.js.map +1 -0
- package/dist/lifecycle/commands/disable.d.ts +3 -0
- package/dist/lifecycle/commands/disable.d.ts.map +1 -0
- package/dist/lifecycle/commands/disable.js +126 -0
- package/dist/lifecycle/commands/disable.js.map +1 -0
- package/dist/lifecycle/commands/enable.d.ts +3 -0
- package/dist/lifecycle/commands/enable.d.ts.map +1 -0
- package/dist/lifecycle/commands/enable.js +102 -0
- package/dist/lifecycle/commands/enable.js.map +1 -0
- package/dist/lifecycle/commands/install.d.ts +3 -0
- package/dist/lifecycle/commands/install.d.ts.map +1 -0
- package/dist/lifecycle/commands/install.js +263 -0
- package/dist/lifecycle/commands/install.js.map +1 -0
- package/dist/lifecycle/commands/operator-entry.d.ts +104 -0
- package/dist/lifecycle/commands/operator-entry.d.ts.map +1 -0
- package/dist/lifecycle/commands/operator-entry.js +127 -0
- package/dist/lifecycle/commands/operator-entry.js.map +1 -0
- package/dist/lifecycle/commands/operator-runtime.d.ts +147 -0
- package/dist/lifecycle/commands/operator-runtime.d.ts.map +1 -0
- package/dist/lifecycle/commands/operator-runtime.js +40 -0
- package/dist/lifecycle/commands/operator-runtime.js.map +1 -0
- package/dist/lifecycle/commands/status.d.ts +3 -0
- package/dist/lifecycle/commands/status.d.ts.map +1 -0
- package/dist/lifecycle/commands/status.js +108 -0
- package/dist/lifecycle/commands/status.js.map +1 -0
- package/dist/lifecycle/commands/uninstall.d.ts +3 -0
- package/dist/lifecycle/commands/uninstall.d.ts.map +1 -0
- package/dist/lifecycle/commands/uninstall.js +223 -0
- package/dist/lifecycle/commands/uninstall.js.map +1 -0
- package/dist/lifecycle/divergence-declaration.d.ts +74 -0
- package/dist/lifecycle/divergence-declaration.d.ts.map +1 -0
- package/dist/lifecycle/divergence-declaration.js +92 -0
- package/dist/lifecycle/divergence-declaration.js.map +1 -0
- package/dist/lifecycle/i18n/en.json +4 -0
- package/dist/lifecycle/i18n/pl.json +4 -0
- package/dist/lifecycle/index.d.ts +110 -0
- package/dist/lifecycle/index.d.ts.map +1 -0
- package/dist/lifecycle/index.js +189 -0
- package/dist/lifecycle/index.js.map +1 -0
- package/dist/lifecycle/manifest-registry.d.ts +244 -0
- package/dist/lifecycle/manifest-registry.d.ts.map +1 -0
- package/dist/lifecycle/manifest-registry.js +223 -0
- package/dist/lifecycle/manifest-registry.js.map +1 -0
- package/dist/lifecycle/manifest.d.ts +166 -0
- package/dist/lifecycle/manifest.d.ts.map +1 -0
- package/dist/lifecycle/manifest.js +121 -0
- package/dist/lifecycle/manifest.js.map +1 -0
- package/dist/lifecycle/plugin.d.ts +56 -0
- package/dist/lifecycle/plugin.d.ts.map +1 -0
- package/dist/lifecycle/plugin.js +59 -0
- package/dist/lifecycle/plugin.js.map +1 -0
- package/dist/lifecycle/resident.d.ts +16 -0
- package/dist/lifecycle/resident.d.ts.map +1 -0
- package/dist/lifecycle/resident.js +59 -0
- package/dist/lifecycle/resident.js.map +1 -0
- package/dist/lifecycle/routes.admin.d.ts +57 -0
- package/dist/lifecycle/routes.admin.d.ts.map +1 -0
- package/dist/lifecycle/routes.admin.js +162 -0
- package/dist/lifecycle/routes.admin.js.map +1 -0
- package/dist/lifecycle/routes.storefront.d.ts +26 -0
- package/dist/lifecycle/routes.storefront.d.ts.map +1 -0
- package/dist/lifecycle/routes.storefront.js +36 -0
- package/dist/lifecycle/routes.storefront.js.map +1 -0
- package/dist/lifecycle/services/deactivation-ledger.d.ts +216 -0
- package/dist/lifecycle/services/deactivation-ledger.d.ts.map +1 -0
- package/dist/lifecycle/services/deactivation-ledger.js +171 -0
- package/dist/lifecycle/services/deactivation-ledger.js.map +1 -0
- package/dist/lifecycle/services/dep-graph.d.ts +119 -0
- package/dist/lifecycle/services/dep-graph.d.ts.map +1 -0
- package/dist/lifecycle/services/dep-graph.js +334 -0
- package/dist/lifecycle/services/dep-graph.js.map +1 -0
- package/dist/lifecycle/services/gating-graph.d.ts +164 -0
- package/dist/lifecycle/services/gating-graph.d.ts.map +1 -0
- package/dist/lifecycle/services/gating-graph.js +203 -0
- package/dist/lifecycle/services/gating-graph.js.map +1 -0
- package/dist/lifecycle/services/lock.d.ts +27 -0
- package/dist/lifecycle/services/lock.d.ts.map +1 -0
- package/dist/lifecycle/services/lock.js +82 -0
- package/dist/lifecycle/services/lock.js.map +1 -0
- package/dist/lifecycle/services/manifest-loader.d.ts +125 -0
- package/dist/lifecycle/services/manifest-loader.d.ts.map +1 -0
- package/dist/lifecycle/services/manifest-loader.js +210 -0
- package/dist/lifecycle/services/manifest-loader.js.map +1 -0
- package/dist/lifecycle/services/migration-ownership.d.ts +36 -0
- package/dist/lifecycle/services/migration-ownership.d.ts.map +1 -0
- package/dist/lifecycle/services/migration-ownership.js +15 -0
- package/dist/lifecycle/services/migration-ownership.js.map +1 -0
- package/dist/lifecycle/services/module-id-claims.d.ts +38 -0
- package/dist/lifecycle/services/module-id-claims.d.ts.map +1 -0
- package/dist/lifecycle/services/module-id-claims.js +123 -0
- package/dist/lifecycle/services/module-id-claims.js.map +1 -0
- package/dist/lifecycle/services/module-origin.d.ts +55 -0
- package/dist/lifecycle/services/module-origin.d.ts.map +1 -0
- package/dist/lifecycle/services/module-origin.js +47 -0
- package/dist/lifecycle/services/module-origin.js.map +1 -0
- package/dist/lifecycle/services/orchestrator.d.ts +235 -0
- package/dist/lifecycle/services/orchestrator.d.ts.map +1 -0
- package/dist/lifecycle/services/orchestrator.js +954 -0
- package/dist/lifecycle/services/orchestrator.js.map +1 -0
- package/dist/lifecycle/services/presence-load.d.ts +281 -0
- package/dist/lifecycle/services/presence-load.d.ts.map +1 -0
- package/dist/lifecycle/services/presence-load.js +437 -0
- package/dist/lifecycle/services/presence-load.js.map +1 -0
- package/dist/lifecycle/services/static-registry.d.ts +47 -0
- package/dist/lifecycle/services/static-registry.d.ts.map +1 -0
- package/dist/lifecycle/services/static-registry.js +41 -0
- package/dist/lifecycle/services/static-registry.js.map +1 -0
- package/dist/migrations/20260424T165847_core_foundation_init.d.ts +25 -0
- package/dist/migrations/20260424T165847_core_foundation_init.d.ts.map +1 -0
- package/dist/migrations/20260424T165847_core_foundation_init.js +238 -0
- package/dist/migrations/20260424T165847_core_foundation_init.js.map +1 -0
- package/dist/migrations/20260425T050720_core_commerce_init.d.ts +19 -0
- package/dist/migrations/20260425T050720_core_commerce_init.d.ts.map +1 -0
- package/dist/migrations/20260425T050720_core_commerce_init.js +200 -0
- package/dist/migrations/20260425T050720_core_commerce_init.js.map +1 -0
- package/dist/migrations/20260430T101450_core_settings_init.d.ts +25 -0
- package/dist/migrations/20260430T101450_core_settings_init.d.ts.map +1 -0
- package/dist/migrations/20260430T101450_core_settings_init.js +113 -0
- package/dist/migrations/20260430T101450_core_settings_init.js.map +1 -0
- package/dist/migrations/20260430T170044_core_sales_channels_promote.d.ts +67 -0
- package/dist/migrations/20260430T170044_core_sales_channels_promote.d.ts.map +1 -0
- package/dist/migrations/20260430T170044_core_sales_channels_promote.js +101 -0
- package/dist/migrations/20260430T170044_core_sales_channels_promote.js.map +1 -0
- package/dist/migrations/20260506T200657_core_module_lifecycle_init.d.ts +21 -0
- package/dist/migrations/20260506T200657_core_module_lifecycle_init.d.ts.map +1 -0
- package/dist/migrations/20260506T200657_core_module_lifecycle_init.js +41 -0
- package/dist/migrations/20260506T200657_core_module_lifecycle_init.js.map +1 -0
- package/dist/migrations/20260514T111329_core_settings_global_value.d.ts +30 -0
- package/dist/migrations/20260514T111329_core_settings_global_value.d.ts.map +1 -0
- package/dist/migrations/20260514T111329_core_settings_global_value.js +34 -0
- package/dist/migrations/20260514T111329_core_settings_global_value.js.map +1 -0
- package/dist/migrations/20260611T140411_core_settings_secret_value_type.d.ts +26 -0
- package/dist/migrations/20260611T140411_core_settings_secret_value_type.d.ts.map +1 -0
- package/dist/migrations/20260611T140411_core_settings_secret_value_type.js +63 -0
- package/dist/migrations/20260611T140411_core_settings_secret_value_type.js.map +1 -0
- package/dist/migrations/20260611T140419_core_settings_enum_options.d.ts +19 -0
- package/dist/migrations/20260611T140419_core_settings_enum_options.d.ts.map +1 -0
- package/dist/migrations/20260611T140419_core_settings_enum_options.js +23 -0
- package/dist/migrations/20260611T140419_core_settings_enum_options.js.map +1 -0
- package/dist/migrations/20260629T090100_core_settings_hidden_flag.d.ts +20 -0
- package/dist/migrations/20260629T090100_core_settings_hidden_flag.d.ts.map +1 -0
- package/dist/migrations/20260629T090100_core_settings_hidden_flag.js +24 -0
- package/dist/migrations/20260629T090100_core_settings_hidden_flag.js.map +1 -0
- package/dist/migrations/20260717T134752_core_tenant_scope_indexes.d.ts +27 -0
- package/dist/migrations/20260717T134752_core_tenant_scope_indexes.d.ts.map +1 -0
- package/dist/migrations/20260717T134752_core_tenant_scope_indexes.js +32 -0
- package/dist/migrations/20260717T134752_core_tenant_scope_indexes.js.map +1 -0
- package/dist/migrations/20260721T011510_core_settings_credential_ref_value_type.d.ts +24 -0
- package/dist/migrations/20260721T011510_core_settings_credential_ref_value_type.d.ts.map +1 -0
- package/dist/migrations/20260721T011510_core_settings_credential_ref_value_type.js +57 -0
- package/dist/migrations/20260721T011510_core_settings_credential_ref_value_type.js.map +1 -0
- package/dist/migrations/20260816T203339_core_retire_core_activation_settings.d.ts +39 -0
- package/dist/migrations/20260816T203339_core_retire_core_activation_settings.d.ts.map +1 -0
- package/dist/migrations/20260816T203339_core_retire_core_activation_settings.js +59 -0
- package/dist/migrations/20260816T203339_core_retire_core_activation_settings.js.map +1 -0
- package/dist/migrations/20260919T101500_core_module_registrations_boot_converged.d.ts +34 -0
- package/dist/migrations/20260919T101500_core_module_registrations_boot_converged.d.ts.map +1 -0
- package/dist/migrations/20260919T101500_core_module_registrations_boot_converged.js +38 -0
- package/dist/migrations/20260919T101500_core_module_registrations_boot_converged.js.map +1 -0
- package/dist/migrations/baseline-migrations.generated.d.ts +2 -0
- package/dist/migrations/baseline-migrations.generated.d.ts.map +1 -0
- package/dist/migrations/baseline-migrations.generated.js +136 -0
- package/dist/migrations/baseline-migrations.generated.js.map +1 -0
- package/dist/migrations/index.d.ts +62 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +75 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/overlay/deployment-roots.d.ts +37 -0
- package/dist/overlay/deployment-roots.d.ts.map +1 -0
- package/dist/overlay/deployment-roots.js +90 -0
- package/dist/overlay/deployment-roots.js.map +1 -0
- package/dist/overlay/index.d.ts +62 -0
- package/dist/overlay/index.d.ts.map +1 -0
- package/dist/overlay/index.js +62 -0
- package/dist/overlay/index.js.map +1 -0
- package/dist/overlay/overlay-runtime.d.ts +173 -0
- package/dist/overlay/overlay-runtime.d.ts.map +1 -0
- package/dist/overlay/overlay-runtime.js +281 -0
- package/dist/overlay/overlay-runtime.js.map +1 -0
- package/dist/overlay/resolve-overlay.d.ts +41 -0
- package/dist/overlay/resolve-overlay.d.ts.map +1 -0
- package/dist/overlay/resolve-overlay.js +72 -0
- package/dist/overlay/resolve-overlay.js.map +1 -0
- package/dist/packages/index.d.ts +57 -0
- package/dist/packages/index.d.ts.map +1 -0
- package/dist/packages/index.js +57 -0
- package/dist/packages/index.js.map +1 -0
- package/dist/packages/installed-packages.d.ts +79 -0
- package/dist/packages/installed-packages.d.ts.map +1 -0
- package/dist/packages/installed-packages.js +312 -0
- package/dist/packages/installed-packages.js.map +1 -0
- package/dist/packages/package-entity-lookup.d.ts +120 -0
- package/dist/packages/package-entity-lookup.d.ts.map +1 -0
- package/dist/packages/package-entity-lookup.js +17 -0
- package/dist/packages/package-entity-lookup.js.map +1 -0
- package/dist/packages/package-runtime.d.ts +177 -0
- package/dist/packages/package-runtime.d.ts.map +1 -0
- package/dist/packages/package-runtime.js +386 -0
- package/dist/packages/package-runtime.js.map +1 -0
- package/dist/tenancy/derived-scope.d.ts +43 -0
- package/dist/tenancy/derived-scope.d.ts.map +1 -0
- package/dist/tenancy/derived-scope.js +76 -0
- package/dist/tenancy/derived-scope.js.map +1 -0
- package/dist/tenancy/escape-hatch.d.ts +30 -0
- package/dist/tenancy/escape-hatch.d.ts.map +1 -0
- package/dist/tenancy/escape-hatch.js +50 -0
- package/dist/tenancy/escape-hatch.js.map +1 -0
- package/dist/tenancy/filters.d.ts +87 -0
- package/dist/tenancy/filters.d.ts.map +1 -0
- package/dist/tenancy/filters.js +126 -0
- package/dist/tenancy/filters.js.map +1 -0
- package/dist/tenancy/index.d.ts +63 -0
- package/dist/tenancy/index.d.ts.map +1 -0
- package/dist/tenancy/index.js +61 -0
- package/dist/tenancy/index.js.map +1 -0
- package/dist/tenancy/org-scoped.decorator.d.ts +150 -0
- package/dist/tenancy/org-scoped.decorator.d.ts.map +1 -0
- package/dist/tenancy/org-scoped.decorator.js +339 -0
- package/dist/tenancy/org-scoped.decorator.js.map +1 -0
- package/dist/tenancy/org-write-guard.d.ts +106 -0
- package/dist/tenancy/org-write-guard.d.ts.map +1 -0
- package/dist/tenancy/org-write-guard.js +141 -0
- package/dist/tenancy/org-write-guard.js.map +1 -0
- package/dist/tenancy/resolve-tenant-context.d.ts +91 -0
- package/dist/tenancy/resolve-tenant-context.d.ts.map +1 -0
- package/dist/tenancy/resolve-tenant-context.js +85 -0
- package/dist/tenancy/resolve-tenant-context.js.map +1 -0
- package/dist/tenancy/scoped-em.d.ts +10 -0
- package/dist/tenancy/scoped-em.d.ts.map +1 -0
- package/dist/tenancy/scoped-em.js +11 -0
- package/dist/tenancy/scoped-em.js.map +1 -0
- package/dist/tenancy/tenant-context.d.ts +154 -0
- package/dist/tenancy/tenant-context.d.ts.map +1 -0
- package/dist/tenancy/tenant-context.js +109 -0
- package/dist/tenancy/tenant-context.js.map +1 -0
- package/package.json +123 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { Filter } from '@mikro-orm/core';
|
|
2
|
+
import { ORG_FILTER, CUSTOMER_FILTER, CUSTOMER_ORGANIZATION_KEY, orgFilterCond, customerFilterCond, } from './filters.js';
|
|
3
|
+
const registry = [];
|
|
4
|
+
/** All classified entities registered at import time. */
|
|
5
|
+
export function tenantClassifications() {
|
|
6
|
+
return registry;
|
|
7
|
+
}
|
|
8
|
+
function applyMikroFilter(target, name, cond) {
|
|
9
|
+
// MikroORM's `Filter` is a class decorator; apply it programmatically.
|
|
10
|
+
// `args: false` — the cond reads the ambient context from AsyncLocalStorage at
|
|
11
|
+
// query time, so no per-fork `setFilterParams` is needed (fork-independent).
|
|
12
|
+
Filter({ name, cond, default: true, args: false })(target);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Whether the entity being filtered carries {@link CUSTOMER_ORGANIZATION_KEY},
|
|
16
|
+
* read out of the ORM's **own discovered metadata** — the same source the query
|
|
17
|
+
* being filtered is built from.
|
|
18
|
+
*
|
|
19
|
+
* It is derived rather than declared for the reason a derived fact is never
|
|
20
|
+
* written down twice: a list of "the customer-scoped classes that have an
|
|
21
|
+
* organization column" would be right on the day it was written and wrong the
|
|
22
|
+
* next time one of feature 087's fifteen migrations lands, and being wrong in
|
|
23
|
+
* the *permissive* direction is a disclosure. Deriving it means the column and
|
|
24
|
+
* the predicate arrive together, in one merge request, with no third artefact
|
|
25
|
+
* to keep in step.
|
|
26
|
+
*
|
|
27
|
+
* **It answers `'absent'` for anything it cannot read**, which is the
|
|
28
|
+
* restrictive answer: an unreadable metadata store must not be the reason a
|
|
29
|
+
* scoped administrator sees every organization's rows.
|
|
30
|
+
*/
|
|
31
|
+
function customerOrganizationColumn(em, entityName) {
|
|
32
|
+
const metadataOf = em?.getMetadata;
|
|
33
|
+
if (typeof metadataOf !== 'function')
|
|
34
|
+
return 'absent';
|
|
35
|
+
const storage = metadataOf.call(em);
|
|
36
|
+
if (typeof storage?.find !== 'function')
|
|
37
|
+
return 'absent';
|
|
38
|
+
const meta = storage.find(entityName);
|
|
39
|
+
const properties = meta?.properties;
|
|
40
|
+
if (!properties)
|
|
41
|
+
return 'absent';
|
|
42
|
+
return Object.prototype.hasOwnProperty.call(properties, CUSTOMER_ORGANIZATION_KEY)
|
|
43
|
+
? 'present'
|
|
44
|
+
: 'absent';
|
|
45
|
+
}
|
|
46
|
+
/** Direct `organizationId` column. Filtered by the `org` global filter. */
|
|
47
|
+
export function OrgScoped() {
|
|
48
|
+
return (target) => {
|
|
49
|
+
registry.push({ target, className: target.name, scope: 'org', key: 'organizationId' });
|
|
50
|
+
applyMikroFilter(target, ORG_FILTER, () => orgFilterCond());
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Direct `customerAccountId` column. Filtered by the `customerAccount` filter.
|
|
55
|
+
*
|
|
56
|
+
* The filter's `allowed-set` arm also needs to know whether *this* entity
|
|
57
|
+
* carries an organization column of its own, so the `cond` forwards the ORM's
|
|
58
|
+
* `em` and `entityName` to {@link customerOrganizationColumn}. See
|
|
59
|
+
* `customerFilterCond` for what each answer means.
|
|
60
|
+
*/
|
|
61
|
+
export function CustomerScoped() {
|
|
62
|
+
return (target) => {
|
|
63
|
+
registry.push({ target, className: target.name, scope: 'customer', key: 'customerAccountId' });
|
|
64
|
+
applyMikroFilter(target, CUSTOMER_FILTER, (_args, _type, em, _options, entityName) => customerFilterCond(customerOrganizationColumn(em, entityName ?? target)));
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Platform-global, exempt from all tenant filters. */
|
|
68
|
+
export function GlobalEntity() {
|
|
69
|
+
return (target) => {
|
|
70
|
+
registry.push({ target, className: target.name, scope: 'global' });
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Scoped through a parent aggregate's org (e.g. Invoice → Order). No own column.
|
|
75
|
+
*
|
|
76
|
+
* **The parent is named by its class name, not by the class** (feature 080,
|
|
77
|
+
* T049; ruling D-169). Both of this platform's transitive chains cross a module
|
|
78
|
+
* boundary — `Invoice` → `Order` and `KsefSubmission` → `Invoice` — and D-168
|
|
79
|
+
* says a module that has become a package publishes an `entities` array and no
|
|
80
|
+
* named entity class, so the symbol the old `() => Order` thunk closed over is
|
|
81
|
+
* one the child cannot import. Those two lines were the whole reason `invoices`
|
|
82
|
+
* and `ksef` could not be packaged. Nothing else in the tree took the thunk
|
|
83
|
+
* form, so there is one form and not two (Constitution IV).
|
|
84
|
+
*
|
|
85
|
+
* **Why the class name and not the table name.** {@link ClassificationMeta}
|
|
86
|
+
* already keys every row by `className`, so the lookup needs no second index
|
|
87
|
+
* and no per-module token registry; MikroORM refuses two entities sharing a
|
|
88
|
+
* class name at discovery (`MetadataValidator`), so the name is a
|
|
89
|
+
* platform-wide unique key the ORM already enforces rather than an assumption
|
|
90
|
+
* written down here; and no reader of this registry — `filters.ts`,
|
|
91
|
+
* `derived-scope.ts`, `kernel/scope.ts`, `check-entity-tenant-classification`
|
|
92
|
+
* — asks for a table. Resolving a table name would mean re-deriving it through
|
|
93
|
+
* the naming strategy or reading `MetadataStorage`, which is only populated
|
|
94
|
+
* after ORM discovery, i.e. later than the moment this has to answer.
|
|
95
|
+
*
|
|
96
|
+
* The name is resolved lazily by {@link resolveTransitiveParent}: entity
|
|
97
|
+
* classes register in import order and a child is routinely imported before its
|
|
98
|
+
* parent, so resolving here would refuse a chain that is perfectly good.
|
|
99
|
+
*/
|
|
100
|
+
export function TransitivelyScoped(parentClassName, fk) {
|
|
101
|
+
return (target) => {
|
|
102
|
+
registry.push({ target, className: target.name, scope: 'transitive', parentClassName, fk });
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* A `@TransitivelyScoped` chain from which no tenant can be read.
|
|
107
|
+
*
|
|
108
|
+
* It is an error and never a fallback. A transitively scoped entity carries no
|
|
109
|
+
* tenant column of its own, so an unresolved parent leaves it reachable with no
|
|
110
|
+
* tenant predicate at all — Principle XI (non-negotiable) defeated by a silence,
|
|
111
|
+
* which is exactly the failure mode a name-addressed parent would otherwise
|
|
112
|
+
* introduce. Resolution therefore has two outcomes and no third: the one
|
|
113
|
+
* classified entity carrying that name, or this.
|
|
114
|
+
*
|
|
115
|
+
* **It is also the error for a chain that resolves at every step and grounds
|
|
116
|
+
* nowhere** (D-170): a `global` or `rule` terminus, a cycle, and a run of
|
|
117
|
+
* transitives reaching no keyed classification. **One error class, deliberately.**
|
|
118
|
+
* A caller can do nothing different about "your parent does not exist" and "your
|
|
119
|
+
* parent has no tenant to give you" — both are boot failures with the same
|
|
120
|
+
* remedy, a decorator to open — and a second class would invite a `catch` that
|
|
121
|
+
* distinguishes them, which is the beginning of a degraded mode. The degraded
|
|
122
|
+
* mode is an untenanted read.
|
|
123
|
+
*/
|
|
124
|
+
export class UnresolvableTenantParentError extends Error {
|
|
125
|
+
constructor(detail) {
|
|
126
|
+
super(`Unresolvable @TransitivelyScoped parent — ${detail}`);
|
|
127
|
+
this.name = 'UnresolvableTenantParentError';
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Why `child`'s parent does not resolve, or `null` when it does.
|
|
132
|
+
*
|
|
133
|
+
* Shared by the single resolution and the whole-registry reconciliation so the
|
|
134
|
+
* two cannot come to disagree about what "resolves" means — and so neither has
|
|
135
|
+
* to `catch` the other's throw.
|
|
136
|
+
*/
|
|
137
|
+
function describeChild(child) {
|
|
138
|
+
return `${child.className} (fk '${child.fk ?? '?'}')`;
|
|
139
|
+
}
|
|
140
|
+
function transitiveParentIssue(child) {
|
|
141
|
+
const where = describeChild(child);
|
|
142
|
+
if (child.scope !== 'transitive' || child.parentClassName === undefined) {
|
|
143
|
+
return `${where} is classified '${child.scope}' and names no transitive parent`;
|
|
144
|
+
}
|
|
145
|
+
const matches = registry.filter((meta) => meta.className === child.parentClassName);
|
|
146
|
+
if (matches.length === 1)
|
|
147
|
+
return null;
|
|
148
|
+
if (matches.length === 0) {
|
|
149
|
+
return (`${where} is scoped through '${child.parentClassName}', and no classified entity of ` +
|
|
150
|
+
'that name is registered in this platform. Either the parent entity is not part of ' +
|
|
151
|
+
'this composition — check the owning module is installed and that this module ' +
|
|
152
|
+
'declares it in its manifest `dependencies` — or the name in the decorator is wrong.');
|
|
153
|
+
}
|
|
154
|
+
return (`${where} is scoped through '${child.parentClassName}', and ${matches.length} classified ` +
|
|
155
|
+
'entities carry that class name. A class name is the platform-wide key here, so an ' +
|
|
156
|
+
'ambiguous one is refused rather than resolved to whichever registered first.');
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* The classification of `child`'s parent aggregate, resolved by class name.
|
|
160
|
+
*
|
|
161
|
+
* Lazy and order-independent by construction: it reads the registry when it is
|
|
162
|
+
* called, never when the decorator ran. Throws {@link UnresolvableTenantParentError}
|
|
163
|
+
* — see that class for why there is no other outcome.
|
|
164
|
+
*/
|
|
165
|
+
export function resolveTransitiveParent(child) {
|
|
166
|
+
const issue = transitiveParentIssue(child);
|
|
167
|
+
if (issue !== null)
|
|
168
|
+
throw new UnresolvableTenantParentError(issue);
|
|
169
|
+
return registry.find((meta) => meta.className === child.parentClassName);
|
|
170
|
+
}
|
|
171
|
+
/** `A -> B -> C`, the shape every message below spells a chain in. */
|
|
172
|
+
function pathText(path) {
|
|
173
|
+
return path.join(' -> ');
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Walk `child`'s chain of parents to a classification that carries a tenant key.
|
|
177
|
+
*
|
|
178
|
+
* **The rule is `parent.key !== undefined`** (D-170), true for exactly `org` and
|
|
179
|
+
* `customer` — {@link ClassificationMeta} already encodes it, so nothing new is
|
|
180
|
+
* stored and the two cannot come to disagree.
|
|
181
|
+
*
|
|
182
|
+
* Checking the *immediate* parent, which is what this used to do, leaves three
|
|
183
|
+
* silences that are all the same failure with a different number of steps: a
|
|
184
|
+
* `global` terminus, a cycle (`A -> B -> A` resolves at every step and grounds
|
|
185
|
+
* nowhere), and a run of transitives reaching no keyed classification. In each
|
|
186
|
+
* of them the entity is reachable with no tenant predicate anywhere on the path.
|
|
187
|
+
*
|
|
188
|
+
* **No depth limit.** The repeated-name guard is what terminates the walk — a
|
|
189
|
+
* chain with no cycle is finite because the registry is — and a legitimate deep
|
|
190
|
+
* chain is not wrong for being deep.
|
|
191
|
+
*/
|
|
192
|
+
function walkTenancyChain(child) {
|
|
193
|
+
const path = [child.className];
|
|
194
|
+
const seen = new Set([child.className]);
|
|
195
|
+
let current = child;
|
|
196
|
+
for (;;) {
|
|
197
|
+
const issue = transitiveParentIssue(current);
|
|
198
|
+
if (issue !== null) {
|
|
199
|
+
// Beyond the first hop the broken decorator is somebody else's — and that
|
|
200
|
+
// entity is transitive too, so it reports the same issue under its own
|
|
201
|
+
// name. This one has to say which chain of its own brought it there.
|
|
202
|
+
return {
|
|
203
|
+
path,
|
|
204
|
+
issue: current === child
|
|
205
|
+
? issue
|
|
206
|
+
: `${describeChild(child)} is scoped through ${pathText(path)}, and that chain breaks: ${issue}`,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
const parent = registry.find((meta) => meta.className === current.parentClassName);
|
|
210
|
+
path.push(parent.className);
|
|
211
|
+
if (seen.has(parent.className)) {
|
|
212
|
+
return {
|
|
213
|
+
path,
|
|
214
|
+
issue: `${describeChild(child)} is scoped through ${pathText(path)}, which is a cycle. ` +
|
|
215
|
+
'It resolves at every step and grounds nowhere, so no tenant predicate is ' +
|
|
216
|
+
'reachable from it. One of the entities in the cycle owns the tenant and should ' +
|
|
217
|
+
"carry a column for it — '@OrgScoped' or '@CustomerScoped' — rather than pointing " +
|
|
218
|
+
'at the next.',
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
seen.add(parent.className);
|
|
222
|
+
if (parent.scope === 'transitive') {
|
|
223
|
+
current = parent;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
if (parent.key !== undefined)
|
|
227
|
+
return { path, terminus: parent, issue: null };
|
|
228
|
+
if (parent.scope === 'rule') {
|
|
229
|
+
return {
|
|
230
|
+
path,
|
|
231
|
+
issue: `${describeChild(child)} is scoped through ${pathText(path)}, which terminates at ` +
|
|
232
|
+
`'${parent.className}' — classified 'rule', so it carries no tenant key. A transitive ` +
|
|
233
|
+
'chain gives the child a foreign key and a foreign key cannot evaluate a rule: a ' +
|
|
234
|
+
"rule-scoped entity's org targeting lives in a JSONB rule that 'derived-scope.ts' " +
|
|
235
|
+
'makes the *query* intersect. This refusal retires the day a rule-scoped entity ' +
|
|
236
|
+
"gains a resolved-org projection — that projection is '@OrgScoped', and a chain may " +
|
|
237
|
+
'terminate there.',
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
path,
|
|
242
|
+
issue: `${describeChild(child)} is scoped through ${pathText(path)}, which terminates at ` +
|
|
243
|
+
`'${parent.className}' — classified '${parent.scope}', so it carries no tenant key. A ` +
|
|
244
|
+
'transitively scoped entity has no tenant column and no filter of its own, and a ' +
|
|
245
|
+
'global parent has none either, so the chain delivers no tenant predicate anywhere ' +
|
|
246
|
+
'on the path and no reader can recover one (Principle XI). If this entity genuinely ' +
|
|
247
|
+
"has no tenant, classify it '@GlobalEntity' itself.",
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* The default destination, for a caller that passes none.
|
|
253
|
+
*
|
|
254
|
+
* A real write and never a no-op, for the reason `kernel/logging.ts` gives its
|
|
255
|
+
* own fallback: this runs before `buildServer`, so stdout is what a boot line
|
|
256
|
+
* has. It is duplicated rather than imported because `kernel/logging.ts` reaches
|
|
257
|
+
* `kernel/scope.ts`, which imports this directory — and this file is loaded by
|
|
258
|
+
* every persisted entity class at decoration time, which is no place to drag
|
|
259
|
+
* the container in behind an import cycle.
|
|
260
|
+
*
|
|
261
|
+
* (The ORM's entity decorator is deliberately not spelled out above: the
|
|
262
|
+
* composer generator collects entity classes by a text match over these
|
|
263
|
+
* sources, so writing it here would make this file one.)
|
|
264
|
+
*/
|
|
265
|
+
const consoleReporter = {
|
|
266
|
+
// eslint-disable-next-line no-console -- the pre-`buildServer` destination; see above.
|
|
267
|
+
info: (obj, msg) => console.info(obj, msg),
|
|
268
|
+
};
|
|
269
|
+
/**
|
|
270
|
+
* Reconcile every transitive chain in the registry, and refuse if any is broken.
|
|
271
|
+
*
|
|
272
|
+
* **This is where the refusal lives, and the placement is the decision.** The
|
|
273
|
+
* decorator cannot refuse — a child is routinely decorated before its parent is
|
|
274
|
+
* imported, so an eager check would reject working chains. The *first
|
|
275
|
+
* resolution* cannot be the only refusal either: nothing in this repository
|
|
276
|
+
* resolves a parent on a request path today, so a chain that stopped resolving
|
|
277
|
+
* would sit there unmeasured, which is the silence this exists to remove. So
|
|
278
|
+
* the host reconciles the whole registry once, at the moment it enumerates the
|
|
279
|
+
* entity classes it is about to configure the ORM with
|
|
280
|
+
* (`backend/src/db/configured-entities.ts`) — the first instant at which every
|
|
281
|
+
* classification decorator has run, core and installed package alike, and still
|
|
282
|
+
* before a single query can be issued.
|
|
283
|
+
*
|
|
284
|
+
* It reports **every** broken chain, not the first: an author who renamed an
|
|
285
|
+
* entity wants the whole list in one boot, not one per restart.
|
|
286
|
+
*
|
|
287
|
+
* ## Three outcomes (D-170)
|
|
288
|
+
*
|
|
289
|
+
* Silent for an `org` terminus. **Refused** for `global`, `rule`, a cycle or a
|
|
290
|
+
* run of transitives that grounds nowhere — see {@link walkTenancyChain}.
|
|
291
|
+
* **Accepted with one `info` line** for a `customer` terminus, which is legal
|
|
292
|
+
* because it grounds (a real column, a default-on filter, and `CustomerAccount`
|
|
293
|
+
* is itself `@OrgScoped`, so the customer axis narrows the org axis rather than
|
|
294
|
+
* competing with it) and reported because of a measured circularity:
|
|
295
|
+
* `customerFilterCond()` returns `{ customerAccountId: … }` in `single-org`
|
|
296
|
+
* mode and **`{}` — no predicate at all — in `allowed-set`**, where that file's
|
|
297
|
+
* own comment says an org-scoped admin "cannot be expressed as a
|
|
298
|
+
* customer-account predicate… such rows are reached **via transitive scoping**
|
|
299
|
+
* where needed". A chain terminating there is therefore unfiltered for an
|
|
300
|
+
* org-scoped admin, and the recorded remedy for that is the very mechanism doing
|
|
301
|
+
* the terminating. Worth a line; not worth a throw, since refusing would police
|
|
302
|
+
* a defect the terminus did not cause — the `{}` applies to all customer-scoped
|
|
303
|
+
* entities either way — and would forbid a shape with nowhere else to go, a
|
|
304
|
+
* customer-scoped parent having no `organizationId` column to continue through.
|
|
305
|
+
*
|
|
306
|
+
* The notices are emitted before the refusal rather than instead of it: each
|
|
307
|
+
* chain is judged on its own, and suppressing a true report about one because
|
|
308
|
+
* another is broken would make the line come and go for unrelated reasons.
|
|
309
|
+
*/
|
|
310
|
+
export function assertTransitiveParentsResolve(report = consoleReporter) {
|
|
311
|
+
const failures = [];
|
|
312
|
+
const notices = [];
|
|
313
|
+
for (const child of registry.filter((meta) => meta.scope === 'transitive')) {
|
|
314
|
+
const walk = walkTenancyChain(child);
|
|
315
|
+
if (walk.issue !== null)
|
|
316
|
+
failures.push(walk.issue);
|
|
317
|
+
else if (walk.terminus?.scope === 'customer')
|
|
318
|
+
notices.push(walk);
|
|
319
|
+
}
|
|
320
|
+
for (const walk of notices) {
|
|
321
|
+
report.info({
|
|
322
|
+
chain: pathText(walk.path),
|
|
323
|
+
terminus: walk.terminus?.className,
|
|
324
|
+
terminusScope: walk.terminus?.scope,
|
|
325
|
+
}, 'tenancy chain terminates at a customer-scoped entity: filtered in `single-org` mode, ' +
|
|
326
|
+
'unfiltered in `allowed-set`, where `customerFilterCond()` returns no predicate for an ' +
|
|
327
|
+
'org-scoped admin');
|
|
328
|
+
}
|
|
329
|
+
if (failures.length === 0)
|
|
330
|
+
return;
|
|
331
|
+
throw new UnresolvableTenantParentError(`${failures.length} tenancy chain(s) do not reach a tenant:\n - ${failures.join('\n - ')}`);
|
|
332
|
+
}
|
|
333
|
+
/** Org targeting lives in a rule (e.g. price_lists `applicationRule`), not a column. */
|
|
334
|
+
export function RuleScoped() {
|
|
335
|
+
return (target) => {
|
|
336
|
+
registry.push({ target, className: target.name, scope: 'rule' });
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
//# sourceMappingURL=org-scoped.decorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-scoped.decorator.js","sourceRoot":"","sources":["../../src/tenancy/org-scoped.decorator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import type { EntityName, EventArgs, EventSubscriber } from '@mikro-orm/core';
|
|
2
|
+
/**
|
|
3
|
+
* The tenant guard on the **write** side (D-260/A, feature 050 FR-003).
|
|
4
|
+
*
|
|
5
|
+
* `@OrgScoped()` attaches a MikroORM global filter and nothing else, and
|
|
6
|
+
* MikroORM applies a filter to `SELECT` / `UPDATE` / `DELETE` and **not to
|
|
7
|
+
* `INSERT`** (`specs/087-tenant-scope-enforcement/r1-spike.md` §4: *"A
|
|
8
|
+
* tenant-scoped INSERT with no ambient context succeeds… The fail-closed
|
|
9
|
+
* guarantee in `tenant-context.ts`'s header is a **read** guarantee."*). So a
|
|
10
|
+
* classification bought a narrowed read and bought nothing on the write side,
|
|
11
|
+
* and the two halves compose into an escalation wherever a handler diffs a
|
|
12
|
+
* narrowed read against a caller-supplied set: an id the actor cannot see reads
|
|
13
|
+
* as *absent* and is then inserted. Measured on
|
|
14
|
+
* `PUT /api/v1/admin/stripe/methods/:id`, where a `sales_representative`
|
|
15
|
+
* assigned to org A submitted `[orgA, orgB]`, was answered **200**, and created
|
|
16
|
+
* org B's deny row.
|
|
17
|
+
*
|
|
18
|
+
* This subscriber closes that at the flush boundary, for every `scope === 'org'`
|
|
19
|
+
* class at once, out of the registry the classification decorators already
|
|
20
|
+
* write. There is no new declaration for a module to make and no per-route
|
|
21
|
+
* discipline to remember — which is the whole reason it is here and not in five
|
|
22
|
+
* payment-gateway packages that leave this repository in feature 134 wave 2.
|
|
23
|
+
*
|
|
24
|
+
* ## Why the flush boundary and not the Command Bus
|
|
25
|
+
*
|
|
26
|
+
* The bus is not on the path (D-260/A, *Alternatives rejected*): `mfa`'s org
|
|
27
|
+
* policy, `webhooks`' create and `organizations`' sales-rep assignment all write
|
|
28
|
+
* without one, so a command-level assertion would cover exactly the writes that
|
|
29
|
+
* are already the most disciplined. And a refusal here is inside
|
|
30
|
+
* `em.transactional`, so the bus's single transaction rolls back **whole** — no
|
|
31
|
+
* orphan row, no audit row, no event. That is 087 §2.2's *"silent-and-complete
|
|
32
|
+
* became loud-and-partial"* answered the other way round: loud **and** complete.
|
|
33
|
+
*
|
|
34
|
+
* ## Three deliberate limits, each with its reason
|
|
35
|
+
*
|
|
36
|
+
* 1. **`scope === 'org'` only, for v1** (D-260/A, step A3).
|
|
37
|
+
* `@TransitivelyScoped` children carry no organization column at all, so
|
|
38
|
+
* asserting one would mean loading the parent aggregate at flush time — a
|
|
39
|
+
* query inside a unit-of-work event, which is a different decision with a
|
|
40
|
+
* different cost. `@CustomerScoped` classes that *do* carry
|
|
41
|
+
* `organizationId` (`Cart` is the only one — `filters.ts:84-87`) are the
|
|
42
|
+
* second decision, and they need their own evidence: the customer axis is
|
|
43
|
+
* the primary key there and the organization column arrived later.
|
|
44
|
+
* 2. **A null or absent `organizationId` is not refused.** D-260/A's subject is
|
|
45
|
+
* *"a write that **carries** a foreign organization"*; a row with no
|
|
46
|
+
* organization carries none, so there is nothing for this predicate to
|
|
47
|
+
* compare. Two classified classes are in that state — `ReturnCase` and
|
|
48
|
+
* `AnalyticsEvent`, both `organizationId?: string | null` — and what a null
|
|
49
|
+
* tenant key *means* is D-259's open question and the owner's, not this
|
|
50
|
+
* subscriber's to answer by refusing. It is worth being explicit that this
|
|
51
|
+
* is the permissive arm: a row written with a null organization is invisible
|
|
52
|
+
* to every scoped reader (`orgFilterCond`'s `$in` and `=` both exclude
|
|
53
|
+
* null), so the leak it would permit is a row nobody can read, not a row
|
|
54
|
+
* another tenant can.
|
|
55
|
+
* 3. **`beforeCreate` and `beforeUpdate` only.** `beforeDelete` is not needed —
|
|
56
|
+
* a `DELETE` *is* filtered, so `em.remove` reaches only rows the narrowed
|
|
57
|
+
* read loaded. `beforeUpsert` is unsubscribed because nothing in this
|
|
58
|
+
* repository calls `em.upsert`, and `em.nativeUpdate` fires no event at all;
|
|
59
|
+
* both are recorded gaps rather than oversights, and both are reachable only
|
|
60
|
+
* by code that would have to *set* an organization id by hand.
|
|
61
|
+
*
|
|
62
|
+
* ## What "no ambient context" does
|
|
63
|
+
*
|
|
64
|
+
* `isOrgInScope` delegates to `orgConstraintFor`, which raises
|
|
65
|
+
* `MissingTenantContextError` when no context is established — the same answer a
|
|
66
|
+
* *read* of the same class gets today (`filters.ts`). A write with no scope
|
|
67
|
+
* therefore fails closed for the same reason and with the same error, rather
|
|
68
|
+
* than through a second arm here that would have to decide how much of the
|
|
69
|
+
* fail-closed guarantee to keep.
|
|
70
|
+
*/
|
|
71
|
+
export declare class OrgWriteGuardSubscriber implements EventSubscriber<object> {
|
|
72
|
+
/**
|
|
73
|
+
* Which class names are `scope === 'org'`, recomputed when the registry grows.
|
|
74
|
+
*
|
|
75
|
+
* The registry is written by decorators at entity-import time, so its contents
|
|
76
|
+
* depend on which modules a composition loaded. Caching on its **length**
|
|
77
|
+
* keeps the lookup O(1) per write event without freezing an answer taken
|
|
78
|
+
* before the last module's entities were imported — a real risk here, because
|
|
79
|
+
* this subscriber is constructed while the ORM configuration is being built.
|
|
80
|
+
*/
|
|
81
|
+
private cache;
|
|
82
|
+
private orgScopedClassNames;
|
|
83
|
+
/**
|
|
84
|
+
* The subscribed set, as classes out of the classification registry.
|
|
85
|
+
*
|
|
86
|
+
* MikroORM reads this **once**, when the `EventManager` registers the
|
|
87
|
+
* subscriber (`EventManager.registerSubscriber`), which is after the host has
|
|
88
|
+
* handed `mikroOrmConfigFrom` its entity list and therefore after every
|
|
89
|
+
* classification decorator has run.
|
|
90
|
+
*
|
|
91
|
+
* It is a narrowing for cost only, and never the guard's boundary: an empty
|
|
92
|
+
* array is how MikroORM spells *"every entity"* (`entities.size === 0` in
|
|
93
|
+
* `dispatchEvent`), so a registry this read too early would silently widen the
|
|
94
|
+
* subscription to `@GlobalEntity` classes that happen to carry an
|
|
95
|
+
* `organization_id` column — `Webhook`, `Promotion`, `MfaOrganizationPolicy`,
|
|
96
|
+
* `OrganizationSalesRepAssignment`, every one of them D-260/**B**'s territory
|
|
97
|
+
* and correctly classified. `assertInScope` therefore re-checks the class
|
|
98
|
+
* against the registry on each event, so the wide subscription is at worst
|
|
99
|
+
* wasted work and never a behaviour change.
|
|
100
|
+
*/
|
|
101
|
+
getSubscribedEntities(): EntityName<object>[];
|
|
102
|
+
beforeCreate(args: EventArgs<object>): void;
|
|
103
|
+
beforeUpdate(args: EventArgs<object>): void;
|
|
104
|
+
private assertInScope;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=org-write-guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-write-guard.d.ts","sourceRoot":"","sources":["../../src/tenancy/org-write-guard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAK9E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,qBAAa,uBAAwB,YAAW,eAAe,CAAC,MAAM,CAAC;IACrE;;;;;;;;OAQG;IACH,OAAO,CAAC,KAAK,CAA6E;IAE1F,OAAO,CAAC,mBAAmB;IAW3B;;;;;;;;;;;;;;;;;OAiBG;IACH,qBAAqB,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE;IAO7C,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAI3C,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,IAAI;IAQ3C,OAAO,CAAC,aAAa;CAStB"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { tenantClassifications } from './org-scoped.decorator.js';
|
|
2
|
+
import { isOrgInScope } from './derived-scope.js';
|
|
3
|
+
import { OrgWriteOutOfScopeError } from './tenant-context.js';
|
|
4
|
+
/**
|
|
5
|
+
* The tenant guard on the **write** side (D-260/A, feature 050 FR-003).
|
|
6
|
+
*
|
|
7
|
+
* `@OrgScoped()` attaches a MikroORM global filter and nothing else, and
|
|
8
|
+
* MikroORM applies a filter to `SELECT` / `UPDATE` / `DELETE` and **not to
|
|
9
|
+
* `INSERT`** (`specs/087-tenant-scope-enforcement/r1-spike.md` §4: *"A
|
|
10
|
+
* tenant-scoped INSERT with no ambient context succeeds… The fail-closed
|
|
11
|
+
* guarantee in `tenant-context.ts`'s header is a **read** guarantee."*). So a
|
|
12
|
+
* classification bought a narrowed read and bought nothing on the write side,
|
|
13
|
+
* and the two halves compose into an escalation wherever a handler diffs a
|
|
14
|
+
* narrowed read against a caller-supplied set: an id the actor cannot see reads
|
|
15
|
+
* as *absent* and is then inserted. Measured on
|
|
16
|
+
* `PUT /api/v1/admin/stripe/methods/:id`, where a `sales_representative`
|
|
17
|
+
* assigned to org A submitted `[orgA, orgB]`, was answered **200**, and created
|
|
18
|
+
* org B's deny row.
|
|
19
|
+
*
|
|
20
|
+
* This subscriber closes that at the flush boundary, for every `scope === 'org'`
|
|
21
|
+
* class at once, out of the registry the classification decorators already
|
|
22
|
+
* write. There is no new declaration for a module to make and no per-route
|
|
23
|
+
* discipline to remember — which is the whole reason it is here and not in five
|
|
24
|
+
* payment-gateway packages that leave this repository in feature 134 wave 2.
|
|
25
|
+
*
|
|
26
|
+
* ## Why the flush boundary and not the Command Bus
|
|
27
|
+
*
|
|
28
|
+
* The bus is not on the path (D-260/A, *Alternatives rejected*): `mfa`'s org
|
|
29
|
+
* policy, `webhooks`' create and `organizations`' sales-rep assignment all write
|
|
30
|
+
* without one, so a command-level assertion would cover exactly the writes that
|
|
31
|
+
* are already the most disciplined. And a refusal here is inside
|
|
32
|
+
* `em.transactional`, so the bus's single transaction rolls back **whole** — no
|
|
33
|
+
* orphan row, no audit row, no event. That is 087 §2.2's *"silent-and-complete
|
|
34
|
+
* became loud-and-partial"* answered the other way round: loud **and** complete.
|
|
35
|
+
*
|
|
36
|
+
* ## Three deliberate limits, each with its reason
|
|
37
|
+
*
|
|
38
|
+
* 1. **`scope === 'org'` only, for v1** (D-260/A, step A3).
|
|
39
|
+
* `@TransitivelyScoped` children carry no organization column at all, so
|
|
40
|
+
* asserting one would mean loading the parent aggregate at flush time — a
|
|
41
|
+
* query inside a unit-of-work event, which is a different decision with a
|
|
42
|
+
* different cost. `@CustomerScoped` classes that *do* carry
|
|
43
|
+
* `organizationId` (`Cart` is the only one — `filters.ts:84-87`) are the
|
|
44
|
+
* second decision, and they need their own evidence: the customer axis is
|
|
45
|
+
* the primary key there and the organization column arrived later.
|
|
46
|
+
* 2. **A null or absent `organizationId` is not refused.** D-260/A's subject is
|
|
47
|
+
* *"a write that **carries** a foreign organization"*; a row with no
|
|
48
|
+
* organization carries none, so there is nothing for this predicate to
|
|
49
|
+
* compare. Two classified classes are in that state — `ReturnCase` and
|
|
50
|
+
* `AnalyticsEvent`, both `organizationId?: string | null` — and what a null
|
|
51
|
+
* tenant key *means* is D-259's open question and the owner's, not this
|
|
52
|
+
* subscriber's to answer by refusing. It is worth being explicit that this
|
|
53
|
+
* is the permissive arm: a row written with a null organization is invisible
|
|
54
|
+
* to every scoped reader (`orgFilterCond`'s `$in` and `=` both exclude
|
|
55
|
+
* null), so the leak it would permit is a row nobody can read, not a row
|
|
56
|
+
* another tenant can.
|
|
57
|
+
* 3. **`beforeCreate` and `beforeUpdate` only.** `beforeDelete` is not needed —
|
|
58
|
+
* a `DELETE` *is* filtered, so `em.remove` reaches only rows the narrowed
|
|
59
|
+
* read loaded. `beforeUpsert` is unsubscribed because nothing in this
|
|
60
|
+
* repository calls `em.upsert`, and `em.nativeUpdate` fires no event at all;
|
|
61
|
+
* both are recorded gaps rather than oversights, and both are reachable only
|
|
62
|
+
* by code that would have to *set* an organization id by hand.
|
|
63
|
+
*
|
|
64
|
+
* ## What "no ambient context" does
|
|
65
|
+
*
|
|
66
|
+
* `isOrgInScope` delegates to `orgConstraintFor`, which raises
|
|
67
|
+
* `MissingTenantContextError` when no context is established — the same answer a
|
|
68
|
+
* *read* of the same class gets today (`filters.ts`). A write with no scope
|
|
69
|
+
* therefore fails closed for the same reason and with the same error, rather
|
|
70
|
+
* than through a second arm here that would have to decide how much of the
|
|
71
|
+
* fail-closed guarantee to keep.
|
|
72
|
+
*/
|
|
73
|
+
export class OrgWriteGuardSubscriber {
|
|
74
|
+
/**
|
|
75
|
+
* Which class names are `scope === 'org'`, recomputed when the registry grows.
|
|
76
|
+
*
|
|
77
|
+
* The registry is written by decorators at entity-import time, so its contents
|
|
78
|
+
* depend on which modules a composition loaded. Caching on its **length**
|
|
79
|
+
* keeps the lookup O(1) per write event without freezing an answer taken
|
|
80
|
+
* before the last module's entities were imported — a real risk here, because
|
|
81
|
+
* this subscriber is constructed while the ORM configuration is being built.
|
|
82
|
+
*/
|
|
83
|
+
cache;
|
|
84
|
+
orgScopedClassNames() {
|
|
85
|
+
const rows = tenantClassifications();
|
|
86
|
+
if (!this.cache || this.cache.rows !== rows.length) {
|
|
87
|
+
this.cache = {
|
|
88
|
+
rows: rows.length,
|
|
89
|
+
names: new Set(rows.filter((meta) => meta.scope === 'org').map((meta) => meta.className)),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
return this.cache.names;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The subscribed set, as classes out of the classification registry.
|
|
96
|
+
*
|
|
97
|
+
* MikroORM reads this **once**, when the `EventManager` registers the
|
|
98
|
+
* subscriber (`EventManager.registerSubscriber`), which is after the host has
|
|
99
|
+
* handed `mikroOrmConfigFrom` its entity list and therefore after every
|
|
100
|
+
* classification decorator has run.
|
|
101
|
+
*
|
|
102
|
+
* It is a narrowing for cost only, and never the guard's boundary: an empty
|
|
103
|
+
* array is how MikroORM spells *"every entity"* (`entities.size === 0` in
|
|
104
|
+
* `dispatchEvent`), so a registry this read too early would silently widen the
|
|
105
|
+
* subscription to `@GlobalEntity` classes that happen to carry an
|
|
106
|
+
* `organization_id` column — `Webhook`, `Promotion`, `MfaOrganizationPolicy`,
|
|
107
|
+
* `OrganizationSalesRepAssignment`, every one of them D-260/**B**'s territory
|
|
108
|
+
* and correctly classified. `assertInScope` therefore re-checks the class
|
|
109
|
+
* against the registry on each event, so the wide subscription is at worst
|
|
110
|
+
* wasted work and never a behaviour change.
|
|
111
|
+
*/
|
|
112
|
+
getSubscribedEntities() {
|
|
113
|
+
const names = this.orgScopedClassNames();
|
|
114
|
+
return tenantClassifications()
|
|
115
|
+
.filter((meta) => names.has(meta.className))
|
|
116
|
+
.map((meta) => meta.target);
|
|
117
|
+
}
|
|
118
|
+
beforeCreate(args) {
|
|
119
|
+
this.assertInScope(args);
|
|
120
|
+
}
|
|
121
|
+
beforeUpdate(args) {
|
|
122
|
+
// `beforeUpdate` is what catches the **cross-organization move**: setting
|
|
123
|
+
// `organizationId = B` on a row legitimately loaded under org A. The read
|
|
124
|
+
// filter cannot see that write at all — the row was visible when it was
|
|
125
|
+
// loaded — and the changed value is on the entity by the time this runs.
|
|
126
|
+
this.assertInScope(args);
|
|
127
|
+
}
|
|
128
|
+
assertInScope(args) {
|
|
129
|
+
const entity = args.entity;
|
|
130
|
+
const className = args.meta?.className ?? entity.constructor.name;
|
|
131
|
+
if (!this.orgScopedClassNames().has(className))
|
|
132
|
+
return;
|
|
133
|
+
const organizationId = entity.organizationId;
|
|
134
|
+
if (typeof organizationId !== 'string')
|
|
135
|
+
return;
|
|
136
|
+
if (isOrgInScope(organizationId))
|
|
137
|
+
return;
|
|
138
|
+
throw new OrgWriteOutOfScopeError(className);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=org-write-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"org-write-guard.js","sourceRoot":"","sources":["../../src/tenancy/org-write-guard.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEG;AACH,MAAM,OAAO,uBAAuB;IAClC;;;;;;;;OAQG;IACK,KAAK,CAA6E;IAElF,mBAAmB;QACzB,MAAM,IAAI,GAAG,qBAAqB,EAAE,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACnD,IAAI,CAAC,KAAK,GAAG;gBACX,IAAI,EAAE,IAAI,CAAC,MAAM;gBACjB,KAAK,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAC1F,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC;IAC1B,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,qBAAqB;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QACzC,OAAO,qBAAqB,EAAE;aAC3B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aAC3C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAA4B,CAAC,CAAC;IACtD,CAAC;IAED,YAAY,CAAC,IAAuB;QAClC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,YAAY,CAAC,IAAuB;QAClC,0EAA0E;QAC1E,0EAA0E;QAC1E,wEAAwE;QACxE,yEAAyE;QACzE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAEO,aAAa,CAAC,IAAuB;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,IAAI,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC;QAClE,IAAI,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC;YAAE,OAAO;QACvD,MAAM,cAAc,GAAI,MAAuC,CAAC,cAAc,CAAC;QAC/E,IAAI,OAAO,cAAc,KAAK,QAAQ;YAAE,OAAO;QAC/C,IAAI,YAAY,CAAC,cAAc,CAAC;YAAE,OAAO;QACzC,MAAM,IAAI,uBAAuB,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;CACF"}
|