@open-mercato/shared 0.6.7 → 0.6.8-develop.6874.1.982d6097d8
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/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +57 -6
- package/build.mjs +2 -4
- package/dist/lib/ai/safety-identifier.js +32 -0
- package/dist/lib/ai/safety-identifier.js.map +7 -0
- package/dist/lib/auth/organizationScope.js +34 -0
- package/dist/lib/auth/organizationScope.js.map +7 -0
- package/dist/lib/auth/server.js +15 -2
- package/dist/lib/auth/server.js.map +2 -2
- package/dist/lib/bootstrap/clientOnlyModules.js +55 -0
- package/dist/lib/bootstrap/clientOnlyModules.js.map +7 -0
- package/dist/lib/bootstrap/dynamicLoader.js +117 -43
- package/dist/lib/bootstrap/dynamicLoader.js.map +2 -2
- package/dist/lib/commands/command-bus.js +5 -1
- package/dist/lib/commands/command-bus.js.map +2 -2
- package/dist/lib/commands/command-interceptor-runner.js +2 -2
- package/dist/lib/commands/command-interceptor-runner.js.map +2 -2
- package/dist/lib/crud/enricher-runner.js +2 -11
- package/dist/lib/crud/enricher-runner.js.map +2 -2
- package/dist/lib/crud/factory.js +72 -9
- package/dist/lib/crud/factory.js.map +2 -2
- package/dist/lib/crud/interceptor-runner.js +2 -2
- package/dist/lib/crud/interceptor-runner.js.map +2 -2
- package/dist/lib/crud/mutation-guard-registry.js +2 -2
- package/dist/lib/crud/mutation-guard-registry.js.map +2 -2
- package/dist/lib/crud/types.js +4 -0
- package/dist/lib/crud/types.js.map +3 -3
- package/dist/lib/data/consistency.js +19 -0
- package/dist/lib/data/consistency.js.map +7 -0
- package/dist/lib/data/engine.js +37 -11
- package/dist/lib/data/engine.js.map +2 -2
- package/dist/lib/db/entityMetadata.js +26 -0
- package/dist/lib/db/entityMetadata.js.map +7 -0
- package/dist/lib/db/pg-errors.js +42 -0
- package/dist/lib/db/pg-errors.js.map +2 -2
- package/dist/lib/di/container.js +48 -6
- package/dist/lib/di/container.js.map +2 -2
- package/dist/lib/email/send.js +56 -0
- package/dist/lib/email/send.js.map +2 -2
- package/dist/lib/encryption/subscriber.js +2 -10
- package/dist/lib/encryption/subscriber.js.map +2 -2
- package/dist/lib/encryption/tenantDataEncryptionService.js +52 -17
- package/dist/lib/encryption/tenantDataEncryptionService.js.map +2 -2
- package/dist/lib/i18n/config.js +1 -1
- package/dist/lib/i18n/config.js.map +2 -2
- package/dist/lib/i18n/server.js +4 -4
- package/dist/lib/i18n/server.js.map +3 -3
- package/dist/lib/logger/extension.js +29 -0
- package/dist/lib/logger/extension.js.map +7 -0
- package/dist/lib/logger/index.js +47 -3
- package/dist/lib/logger/index.js.map +3 -3
- package/dist/lib/modules/registry.js +5 -1
- package/dist/lib/modules/registry.js.map +2 -2
- package/dist/lib/modules/surfaceFingerprint.js +47 -0
- package/dist/lib/modules/surfaceFingerprint.js.map +7 -0
- package/dist/lib/query/ciphertext-search-warning.js +45 -0
- package/dist/lib/query/ciphertext-search-warning.js.map +7 -0
- package/dist/lib/query/engine.js +54 -40
- package/dist/lib/query/engine.js.map +2 -2
- package/dist/lib/query/types.js.map +1 -1
- package/dist/lib/redis/connection.js +7 -2
- package/dist/lib/redis/connection.js.map +2 -2
- package/dist/lib/search/auto-indexing.js +14 -0
- package/dist/lib/search/auto-indexing.js.map +7 -0
- package/dist/lib/search/availability.js +107 -0
- package/dist/lib/search/availability.js.map +7 -0
- package/dist/lib/search/config.js +61 -2
- package/dist/lib/search/config.js.map +2 -2
- package/dist/lib/search/tokenLookup.js +46 -0
- package/dist/lib/search/tokenLookup.js.map +7 -0
- package/dist/lib/search/tokenize.js +23 -11
- package/dist/lib/search/tokenize.js.map +2 -2
- package/dist/lib/telemetry/runtime.js +35 -0
- package/dist/lib/telemetry/runtime.js.map +7 -0
- package/dist/lib/version.js +1 -1
- package/dist/lib/version.js.map +1 -1
- package/dist/lib/webhooks/body.js +57 -0
- package/dist/lib/webhooks/body.js.map +7 -0
- package/dist/lib/webhooks/inbound-types.js +1 -0
- package/dist/lib/webhooks/inbound-types.js.map +7 -0
- package/dist/lib/webhooks/index.js +13 -1
- package/dist/lib/webhooks/index.js.map +2 -2
- package/dist/lib/webhooks/verify.js +12 -7
- package/dist/lib/webhooks/verify.js.map +2 -2
- package/dist/modules/analytics.js.map +2 -2
- package/dist/modules/overrides.js +50 -1
- package/dist/modules/overrides.js.map +2 -2
- package/dist/modules/payment_gateways/types.js +8 -1
- package/dist/modules/payment_gateways/types.js.map +2 -2
- package/dist/modules/registry.js +1 -0
- package/dist/modules/registry.js.map +2 -2
- package/dist/modules/widgets/extension-points.js +96 -0
- package/dist/modules/widgets/extension-points.js.map +7 -0
- package/dist/security/enabledModulesRegistry.js +56 -11
- package/dist/security/enabledModulesRegistry.js.map +2 -2
- package/dist/security/featurePolicy.js +62 -0
- package/dist/security/featurePolicy.js.map +7 -0
- package/jest.config.cjs +2 -1
- package/package.json +19 -9
- package/scripts/versionSource.cjs +65 -0
- package/src/lib/__tests__/versionSource.test.ts +46 -0
- package/src/lib/ai/__tests__/llm-provider-contract.test.ts +59 -0
- package/src/lib/ai/__tests__/safety-identifier.test.ts +71 -0
- package/src/lib/ai/llm-provider.ts +33 -0
- package/src/lib/ai/safety-identifier.ts +73 -0
- package/src/lib/auth/__tests__/organizationScope.test.ts +107 -0
- package/src/lib/auth/__tests__/server.test.ts +23 -0
- package/src/lib/auth/organizationScope.ts +65 -0
- package/src/lib/auth/server.ts +23 -2
- package/src/lib/bootstrap/__tests__/clientOnlyModules.test.ts +189 -0
- package/src/lib/bootstrap/__tests__/dynamicLoader.aliasResolver.test.ts +98 -0
- package/src/lib/bootstrap/__tests__/dynamicLoader.appDi.test.ts +211 -0
- package/src/lib/bootstrap/__tests__/dynamicLoader.commandInterceptors.test.ts +63 -8
- package/src/lib/bootstrap/__tests__/dynamicLoader.generatedCacheRecovery.test.ts +256 -0
- package/src/lib/bootstrap/__tests__/dynamicLoader.tsconfig.test.ts +21 -1
- package/src/lib/bootstrap/clientOnlyModules.ts +85 -0
- package/src/lib/bootstrap/dynamicLoader.ts +213 -65
- package/src/lib/commands/__tests__/command-interceptor-runner.test.ts +28 -0
- package/src/lib/commands/command-bus.ts +5 -1
- package/src/lib/commands/command-interceptor-runner.ts +2 -2
- package/src/lib/crud/__tests__/crud-factory.cache-user-scope.test.ts +171 -0
- package/src/lib/crud/__tests__/crud-factory.test.ts +351 -0
- package/src/lib/crud/__tests__/mutation-guard-registry.test.ts +26 -0
- package/src/lib/crud/enricher-runner.ts +2 -11
- package/src/lib/crud/factory.ts +82 -6
- package/src/lib/crud/interceptor-runner.ts +2 -2
- package/src/lib/crud/mutation-guard-registry.ts +2 -2
- package/src/lib/crud/types.ts +3 -0
- package/src/lib/data/__tests__/consistency.test.ts +38 -0
- package/src/lib/data/__tests__/engine.bulk-suppress.test.ts +18 -3
- package/src/lib/data/consistency.ts +17 -0
- package/src/lib/data/engine.ts +50 -16
- package/src/lib/db/__tests__/entityMetadata.test.ts +38 -0
- package/src/lib/db/__tests__/pg-errors.test.ts +48 -0
- package/src/lib/db/entityMetadata.ts +43 -0
- package/src/lib/db/pg-errors.ts +58 -0
- package/src/lib/di/__tests__/container-app-di-absent.test.ts +155 -0
- package/src/lib/di/__tests__/container-app-di.test.ts +173 -0
- package/src/lib/di/__tests__/registrar-error-log.test.ts +154 -0
- package/src/lib/di/container.ts +72 -8
- package/src/lib/email/__tests__/send.test.ts +37 -1
- package/src/lib/email/send.ts +79 -0
- package/src/lib/encryption/__tests__/subscriber.test.ts +54 -2
- package/src/lib/encryption/__tests__/tenantDataEncryptionService.test.ts +58 -0
- package/src/lib/encryption/subscriber.ts +2 -14
- package/src/lib/encryption/tenantDataEncryptionService.ts +64 -18
- package/src/lib/i18n/__tests__/config.test.ts +8 -0
- package/src/lib/i18n/__tests__/server-dictionary-cache.test.ts +30 -0
- package/src/lib/i18n/__tests__/server-unbootstrapped.test.ts +29 -0
- package/src/lib/i18n/config.ts +2 -2
- package/src/lib/i18n/server.ts +6 -2
- package/src/lib/logger/__tests__/logger.test.ts +77 -0
- package/src/lib/logger/extension.ts +59 -0
- package/src/lib/logger/index.ts +59 -1
- package/src/lib/modules/__tests__/surfaceFingerprint.test.ts +122 -0
- package/src/lib/modules/registry.ts +10 -0
- package/src/lib/modules/surfaceFingerprint.ts +87 -0
- package/src/lib/query/__tests__/ciphertext-search-warning.test.ts +178 -0
- package/src/lib/query/__tests__/engine.test.ts +65 -13
- package/src/lib/query/ciphertext-search-warning.ts +95 -0
- package/src/lib/query/engine.ts +75 -58
- package/src/lib/query/types.ts +4 -5
- package/src/lib/redis/__tests__/connection.test.ts +16 -0
- package/src/lib/redis/connection.ts +10 -7
- package/src/lib/search/__tests__/availability.test.ts +211 -0
- package/src/lib/search/__tests__/config.test.ts +177 -0
- package/src/lib/search/__tests__/tokenLookup.test.ts +206 -0
- package/src/lib/search/__tests__/tokenize.test.ts +49 -0
- package/src/lib/search/auto-indexing.ts +22 -0
- package/src/lib/search/availability.ts +232 -0
- package/src/lib/search/config.ts +106 -8
- package/src/lib/search/tokenLookup.ts +133 -0
- package/src/lib/search/tokenize.ts +33 -11
- package/src/lib/telemetry/runtime.ts +72 -0
- package/src/lib/webhooks/__tests__/body.test.ts +95 -0
- package/src/lib/webhooks/__tests__/verify.test.ts +20 -1
- package/src/lib/webhooks/body.ts +70 -0
- package/src/lib/webhooks/inbound-types.ts +125 -0
- package/src/lib/webhooks/index.ts +19 -1
- package/src/lib/webhooks/verify.ts +17 -9
- package/src/modules/__tests__/nav-group-order-override.test.ts +183 -0
- package/src/modules/__tests__/registry.test.ts +10 -2
- package/src/modules/analytics.ts +7 -0
- package/src/modules/customer-auth.ts +1 -0
- package/src/modules/encryption.ts +3 -0
- package/src/modules/navigation/backendChrome.ts +15 -0
- package/src/modules/overrides.ts +103 -0
- package/src/modules/payment_gateways/__tests__/types.test.ts +37 -0
- package/src/modules/payment_gateways/types.ts +41 -0
- package/src/modules/registry.ts +3 -0
- package/src/modules/widgets/__tests__/extension-points.test.ts +101 -0
- package/src/modules/widgets/extension-points.ts +524 -0
- package/src/security/__tests__/featurePolicy.test.ts +166 -0
- package/src/security/enabledModulesRegistry.ts +64 -12
- package/src/security/featurePolicy.ts +89 -0
|
@@ -31,6 +31,7 @@ type FeatureRegistry = {
|
|
|
31
31
|
enabledModuleSet: Set<string>
|
|
32
32
|
featureToModule: Map<string, string>
|
|
33
33
|
prefixToModule: Map<string, string>
|
|
34
|
+
concreteFeatureIds: string[]
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
let cachedRegistry: FeatureRegistry | null = null
|
|
@@ -41,23 +42,63 @@ function buildRegistry(modules: readonly Module[]): FeatureRegistry {
|
|
|
41
42
|
const enabledModuleSet = new Set(enabledModuleIds)
|
|
42
43
|
const featureToModule = new Map<string, string>()
|
|
43
44
|
const prefixToModule = new Map<string, string>()
|
|
45
|
+
const concreteFeatureIds: string[] = []
|
|
46
|
+
const concreteFeatureSet = new Set<string>()
|
|
47
|
+
|
|
48
|
+
const addConcreteFeature = (featureId: string, owningModule: string, authoritative: boolean) => {
|
|
49
|
+
if (!featureId || featureId === '*' || featureId.endsWith('.*')) return
|
|
50
|
+
if (!concreteFeatureSet.has(featureId)) {
|
|
51
|
+
concreteFeatureSet.add(featureId)
|
|
52
|
+
concreteFeatureIds.push(featureId)
|
|
53
|
+
}
|
|
54
|
+
if (authoritative || !featureToModule.has(featureId)) {
|
|
55
|
+
featureToModule.set(featureId, owningModule)
|
|
56
|
+
}
|
|
57
|
+
const dot = featureId.indexOf('.')
|
|
58
|
+
if (dot > 0) {
|
|
59
|
+
const prefix = featureId.slice(0, dot)
|
|
60
|
+
if (!prefixToModule.has(prefix)) prefixToModule.set(prefix, owningModule)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
44
64
|
for (const mod of modules) {
|
|
45
65
|
const features = mod.features
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
66
|
+
if (Array.isArray(features)) {
|
|
67
|
+
for (const feature of features) {
|
|
68
|
+
if (!feature || typeof feature.id !== 'string' || !feature.id) continue
|
|
69
|
+
const declared = typeof feature.module === 'string' && feature.module.length > 0
|
|
70
|
+
? feature.module
|
|
71
|
+
: mod.id
|
|
72
|
+
addConcreteFeature(feature.id, declared, true)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const customerDefaults = mod.setup?.defaultCustomerRoleFeatures
|
|
77
|
+
if (customerDefaults) {
|
|
78
|
+
for (const roleFeatures of Object.values(customerDefaults)) {
|
|
79
|
+
if (!Array.isArray(roleFeatures)) continue
|
|
80
|
+
for (const featureId of roleFeatures) {
|
|
81
|
+
if (typeof featureId === 'string') addConcreteFeature(featureId, mod.id, false)
|
|
82
|
+
}
|
|
57
83
|
}
|
|
58
84
|
}
|
|
85
|
+
|
|
86
|
+
if (Array.isArray(mod.frontendRoutes)) {
|
|
87
|
+
for (const route of mod.frontendRoutes) {
|
|
88
|
+
if (!Array.isArray(route.requireCustomerFeatures)) continue
|
|
89
|
+
for (const featureId of route.requireCustomerFeatures) {
|
|
90
|
+
if (typeof featureId === 'string') addConcreteFeature(featureId, mod.id, false)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
enabledModuleIds,
|
|
97
|
+
enabledModuleSet,
|
|
98
|
+
featureToModule,
|
|
99
|
+
prefixToModule,
|
|
100
|
+
concreteFeatureIds,
|
|
59
101
|
}
|
|
60
|
-
return { enabledModuleIds, enabledModuleSet, featureToModule, prefixToModule }
|
|
61
102
|
}
|
|
62
103
|
|
|
63
104
|
function getRegistry(): FeatureRegistry | null {
|
|
@@ -93,6 +134,17 @@ export function getEnabledModuleIds(): string[] {
|
|
|
93
134
|
return registry ? [...registry.enabledModuleIds] : []
|
|
94
135
|
}
|
|
95
136
|
|
|
137
|
+
/** @internal Infrastructure input for concrete feature-policy projection. */
|
|
138
|
+
export function getConcreteFeatureIds(): string[] {
|
|
139
|
+
const registry = getRegistry()
|
|
140
|
+
return registry ? [...registry.concreteFeatureIds] : []
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/** @internal Distinguishes an empty registry from an unavailable bootstrap registry. */
|
|
144
|
+
export function hasEnabledModulesRegistry(): boolean {
|
|
145
|
+
return getRegistry() !== null
|
|
146
|
+
}
|
|
147
|
+
|
|
96
148
|
/**
|
|
97
149
|
* Filters a raw granted-features list down to the grants whose owning
|
|
98
150
|
* module is currently enabled. Expands `*` (superadmin) into one wildcard
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { hasAllFeatures as matchesAllFeatures } from './features'
|
|
2
|
+
import {
|
|
3
|
+
filterGrantsByEnabledModules,
|
|
4
|
+
getConcreteFeatureIds,
|
|
5
|
+
getEnabledModuleIds,
|
|
6
|
+
getOwningModuleId,
|
|
7
|
+
hasEnabledModulesRegistry,
|
|
8
|
+
} from './enabledModulesRegistry'
|
|
9
|
+
import { composeAclFeatureOverrides } from '../modules/overrides'
|
|
10
|
+
|
|
11
|
+
export type FeaturePolicySubject = {
|
|
12
|
+
grantedFeatures: readonly string[]
|
|
13
|
+
unrestricted?: boolean
|
|
14
|
+
scopeAllowed?: boolean
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getRemovedAclFeatureIds(): string[] {
|
|
18
|
+
return Object.entries(composeAclFeatureOverrides())
|
|
19
|
+
.filter(([, override]) => override === null)
|
|
20
|
+
.map(([featureId]) => featureId)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function isAclFeatureRemoved(featureId: string): boolean {
|
|
24
|
+
return composeAclFeatureOverrides()[featureId] === null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function isFeatureEnabled(featureId: string): boolean {
|
|
28
|
+
if (!hasEnabledModulesRegistry()) return true
|
|
29
|
+
const enabledModuleIds = getEnabledModuleIds()
|
|
30
|
+
return enabledModuleIds.includes(getOwningModuleId(featureId))
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function authorizeFeatures(
|
|
34
|
+
required: readonly string[],
|
|
35
|
+
subject: FeaturePolicySubject,
|
|
36
|
+
): boolean {
|
|
37
|
+
if (required.length === 0) return true
|
|
38
|
+
if (subject.scopeAllowed === false) return false
|
|
39
|
+
if (required.some((featureId) => (
|
|
40
|
+
isAclFeatureRemoved(featureId) || !isFeatureEnabled(featureId)
|
|
41
|
+
))) {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
if (subject.unrestricted === true) return true
|
|
45
|
+
return matchesAllFeatures(
|
|
46
|
+
filterGrantsByEnabledModules(subject.grantedFeatures),
|
|
47
|
+
required,
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function resolveEffectiveFeatures(
|
|
52
|
+
grantedFeatures: readonly string[],
|
|
53
|
+
): string[] {
|
|
54
|
+
const filteredGrants = filterGrantsByEnabledModules(grantedFeatures)
|
|
55
|
+
.filter((featureId) => !isAclFeatureRemoved(featureId))
|
|
56
|
+
|
|
57
|
+
if (!hasEnabledModulesRegistry()) {
|
|
58
|
+
return filteredGrants.filter((featureId, index, features) => (
|
|
59
|
+
featureId !== '*'
|
|
60
|
+
&& !featureId.endsWith('.*')
|
|
61
|
+
&& features.indexOf(featureId) === index
|
|
62
|
+
))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const result: string[] = []
|
|
66
|
+
const seen = new Set<string>()
|
|
67
|
+
const addFeature = (featureId: string) => {
|
|
68
|
+
if (
|
|
69
|
+
seen.has(featureId)
|
|
70
|
+
|| isAclFeatureRemoved(featureId)
|
|
71
|
+
|| !isFeatureEnabled(featureId)
|
|
72
|
+
) {
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
seen.add(featureId)
|
|
76
|
+
result.push(featureId)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
for (const featureId of getConcreteFeatureIds()) {
|
|
80
|
+
if (matchesAllFeatures(filteredGrants, [featureId])) addFeature(featureId)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
for (const featureId of filteredGrants) {
|
|
84
|
+
if (featureId === '*' || featureId.endsWith('.*')) continue
|
|
85
|
+
addFeature(featureId)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return result
|
|
89
|
+
}
|