pi-kiosk-shared 2.2.87 → 2.2.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/analytics/tenantCommandCenter.d.ts +6 -1
  2. package/dist/analytics/tenantCommandCenter.d.ts.map +1 -1
  3. package/dist/analyticsEventDescriptions.js +10 -10
  4. package/dist/analyticsEventLabels.js +3 -3
  5. package/dist/auditEventDescriptions.js +10 -10
  6. package/dist/auditEventLabels.js +6 -6
  7. package/dist/barcode-scanner.d.ts +2 -1
  8. package/dist/barcode-scanner.d.ts.map +1 -1
  9. package/dist/barcode-scanner.js +1 -1
  10. package/dist/barcode-scanner.js.map +1 -1
  11. package/dist/errors.js +1 -1
  12. package/dist/hooks/scannerCameraConstraints.d.ts +13 -0
  13. package/dist/hooks/scannerCameraConstraints.d.ts.map +1 -0
  14. package/dist/hooks/scannerCameraConstraints.js +49 -0
  15. package/dist/hooks/scannerCameraConstraints.js.map +1 -0
  16. package/dist/hooks/selectEngine.d.ts +10 -4
  17. package/dist/hooks/selectEngine.d.ts.map +1 -1
  18. package/dist/hooks/selectEngine.js +1 -16
  19. package/dist/hooks/selectEngine.js.map +1 -1
  20. package/dist/hooks/useBarcodeScanner.d.ts +18 -1
  21. package/dist/hooks/useBarcodeScanner.d.ts.map +1 -1
  22. package/dist/hooks/useBarcodeScanner.js +208 -34
  23. package/dist/hooks/useBarcodeScanner.js.map +1 -1
  24. package/dist/hooks/zxingWasmEngine.d.ts +66 -0
  25. package/dist/hooks/zxingWasmEngine.d.ts.map +1 -0
  26. package/dist/hooks/zxingWasmEngine.js +203 -0
  27. package/dist/hooks/zxingWasmEngine.js.map +1 -0
  28. package/dist/order/fulfillmentContracts.d.ts +2 -0
  29. package/dist/order/fulfillmentContracts.d.ts.map +1 -1
  30. package/dist/permissions/permissionLabels.js +4 -4
  31. package/dist/tenant-entitlements/adminMfaEntitlement.d.ts +1 -1
  32. package/dist/tenant-entitlements/adminMfaEntitlement.d.ts.map +1 -1
  33. package/dist/tenant-entitlements/adminMfaEntitlement.js +5 -1
  34. package/dist/tenant-entitlements/adminMfaEntitlement.js.map +1 -1
  35. package/dist/tenant-entitlements/applyTenantScopeToSimpleStates.d.ts.map +1 -1
  36. package/dist/tenant-entitlements/applyTenantScopeToSimpleStates.js +3 -0
  37. package/dist/tenant-entitlements/applyTenantScopeToSimpleStates.js.map +1 -1
  38. package/dist/tenant-entitlements/capabilityEntitlementRequirements.d.ts +65 -0
  39. package/dist/tenant-entitlements/capabilityEntitlementRequirements.d.ts.map +1 -0
  40. package/dist/tenant-entitlements/capabilityEntitlementRequirements.js +1154 -0
  41. package/dist/tenant-entitlements/capabilityEntitlementRequirements.js.map +1 -0
  42. package/dist/tenant-entitlements/catalog.d.ts +1 -1
  43. package/dist/tenant-entitlements/catalog.d.ts.map +1 -1
  44. package/dist/tenant-entitlements/catalog.js +12 -4
  45. package/dist/tenant-entitlements/catalog.js.map +1 -1
  46. package/dist/tenant-entitlements/index.d.ts +3 -0
  47. package/dist/tenant-entitlements/index.d.ts.map +1 -1
  48. package/dist/tenant-entitlements/index.js +2 -0
  49. package/dist/tenant-entitlements/index.js.map +1 -1
  50. package/dist/tenant-entitlements/tenantBrandKitEntitlement.d.ts +2 -0
  51. package/dist/tenant-entitlements/tenantBrandKitEntitlement.d.ts.map +1 -0
  52. package/dist/tenant-entitlements/tenantBrandKitEntitlement.js +2 -0
  53. package/dist/tenant-entitlements/tenantBrandKitEntitlement.js.map +1 -0
  54. package/dist/tenant-entitlements/types.d.ts +4 -4
  55. package/dist/tenant-entitlements/types.d.ts.map +1 -1
  56. package/dist/tenant-entitlements/types.js +3 -2
  57. package/dist/tenant-entitlements/types.js.map +1 -1
  58. package/package.json +399 -394
@@ -0,0 +1,1154 @@
1
+ /**
2
+ * Capability → entitlement-block grant requirements (commercial RBAC ceiling map).
3
+ *
4
+ * Authoring tokens use PIPE / SLASH / GLOB / LITERAL per expandAuthoringTokens.
5
+ * Runtime CAPABILITY_ENTITLEMENT_REQUIREMENTS stores expanded literals only.
6
+ *
7
+ * NEVER import admin-app or up-backend into this module.
8
+ */
9
+ /** Copied PAYMENTS_HUB_NAV_ENTITLEMENT_ALL_OF literals (do not import admin-app). */
10
+ export const PAYMENTS_HUB_NAV_ENTITLEMENT_ALL_OF = [
11
+ 'payments_hub_ui',
12
+ 'bank_inbox_claims_api',
13
+ ];
14
+ /** Copied EXPLORE_ENTITLEMENT_ALL_OF literals (do not import admin-app). */
15
+ export const EXPLORE_ENTITLEMENT_ALL_OF = [
16
+ 'analytics_detailed',
17
+ 'analytics_pii',
18
+ ];
19
+ /**
20
+ * Catalog CORE_IMMUTABLE keys — CI fails if any grant row lists these as requiredBlockKeys.
21
+ * Do NOT list CONDITIONAL blocks here (they must remain requirable for fail-closed
22
+ * grant ceilings when a pack is off). Commercial admin:outbox:* / tenant.outbox.* are
23
+ * entitlementExempt — Události visibility is route-gated via incident_centre_ui only;
24
+ * outbox_runtime stays CORE_IMMUTABLE ALWAYS_ON (workers), never a grant requirement.
25
+ */
26
+ export const NEVER_REQUIRED_BLOCK_KEYS = [
27
+ 'platform_core',
28
+ 'dev_entitlement_policy_editor',
29
+ 'audit_event_collection',
30
+ 'gdpr_consent_admin_ui',
31
+ 'payment_processing_runtime',
32
+ 'outbox_runtime',
33
+ ];
34
+ const FORBIDDEN_INVENTORY_GLOB = 'ops:inventory:*';
35
+ function lastSeparatorIndex(segmentBeforeSlash) {
36
+ return Math.max(segmentBeforeSlash.lastIndexOf('.'), segmentBeforeSlash.lastIndexOf(':'));
37
+ }
38
+ function isIllegalFinanceOrSystemPipeShorthand(token) {
39
+ const legalFinance = 'finance:view:*|finance:detailed:*|finance:pii:*|finance:export:*';
40
+ const legalSystem = 'system:health:*|system:feature-flags:*|system:secrets:*';
41
+ if (token === legalFinance || token === legalSystem) {
42
+ return false;
43
+ }
44
+ if (!(token.startsWith('finance:') || token.startsWith('system:'))) {
45
+ return false;
46
+ }
47
+ // Reject finance:view|detailed|pii|export:* and system:health|feature-flags|secrets:*
48
+ if (/^finance:view\|/.test(token) || /^system:health\|/.test(token)) {
49
+ return true;
50
+ }
51
+ const pieces = token.split('|');
52
+ return pieces.some((piece) => !piece.includes(':') && !piece.includes('.'));
53
+ }
54
+ function expandSingleToken(token, liveIds) {
55
+ if (token === FORBIDDEN_INVENTORY_GLOB) {
56
+ throw new Error('expandAuthoringTokens: forbids ops:inventory:* (would pull incident_review_high_impact onto inventory_management); use ops:inventory:read/manage');
57
+ }
58
+ if (token.includes('|')) {
59
+ if (/\([^)]*\|[^)]*\)/.test(token)) {
60
+ throw new Error(`expandAuthoringTokens: illegal nested pipe group in ${JSON.stringify(token)}`);
61
+ }
62
+ if (isIllegalFinanceOrSystemPipeShorthand(token)) {
63
+ throw new Error(`expandAuthoringTokens: illegal pipe shorthand ${JSON.stringify(token)}; use fully-qualified unions (finance:view:*|finance:detailed:*|finance:pii:*|finance:export:* or system:health:*|system:feature-flags:*|system:secrets:*)`);
64
+ }
65
+ const out = new Set();
66
+ for (const piece of token.split('|')) {
67
+ for (const key of expandSingleToken(piece, liveIds)) {
68
+ out.add(key);
69
+ }
70
+ }
71
+ return [...out];
72
+ }
73
+ if (token.includes('/')) {
74
+ if (token.includes('*')) {
75
+ throw new Error(`expandAuthoringTokens: mixed / and glob on one token: ${JSON.stringify(token)}`);
76
+ }
77
+ const firstSlash = token.indexOf('/');
78
+ const beforeSlash = token.slice(0, firstSlash);
79
+ const sepIdx = lastSeparatorIndex(beforeSlash);
80
+ if (sepIdx < 0) {
81
+ throw new Error(`expandAuthoringTokens: slash token missing . or : prefix: ${JSON.stringify(token)}`);
82
+ }
83
+ const prefix = token.slice(0, sepIdx + 1);
84
+ const forks = token.slice(sepIdx + 1).split('/');
85
+ const out = [];
86
+ for (const fork of forks) {
87
+ const key = `${prefix}${fork}`;
88
+ if (!liveIds.has(key)) {
89
+ throw new Error(`expandAuthoringTokens: slash fork ${JSON.stringify(key)} not in liveIds (from ${JSON.stringify(token)})`);
90
+ }
91
+ out.push(key);
92
+ }
93
+ return out;
94
+ }
95
+ if (token.endsWith('.*') || token.endsWith(':*')) {
96
+ const separator = token.endsWith('.*') ? '.' : ':';
97
+ const prefix = token.slice(0, -2);
98
+ const fullPrefix = `${prefix}${separator}`;
99
+ const out = [];
100
+ for (const id of liveIds) {
101
+ if (!id.startsWith(fullPrefix))
102
+ continue;
103
+ const rest = id.slice(fullPrefix.length);
104
+ if (rest.length === 0)
105
+ continue;
106
+ // One-level only — never recursive
107
+ if (rest.includes('.') || rest.includes(':'))
108
+ continue;
109
+ out.push(id);
110
+ }
111
+ if (out.length === 0) {
112
+ throw new Error(`expandAuthoringTokens: glob ${JSON.stringify(token)} matched no liveIds`);
113
+ }
114
+ return out;
115
+ }
116
+ if (!liveIds.has(token)) {
117
+ throw new Error(`expandAuthoringTokens: literal ${JSON.stringify(token)} not in liveIds`);
118
+ }
119
+ return [token];
120
+ }
121
+ /**
122
+ * Expand authoring tokens to sorted unique capability literals.
123
+ * Algorithm: PIPE → SLASH → GLOB (one-level) → LITERAL. Pure; CI passes real LIVE_IDS.
124
+ */
125
+ export function expandAuthoringTokens(tokens, liveIds) {
126
+ const liveSet = new Set(liveIds);
127
+ const out = new Set();
128
+ for (const token of tokens) {
129
+ for (const key of expandSingleToken(token, liveSet)) {
130
+ out.add(key);
131
+ }
132
+ }
133
+ return [...out].sort((a, b) => a.localeCompare(b));
134
+ }
135
+ /**
136
+ * LIVE_IDS snapshot for in-module authoring expansion only.
137
+ * CI gate-capability-entitlement-requirements must assert equality with
138
+ * getAllCanonicalRecords ∪ getAllCapabilityNames.
139
+ */
140
+ export const CAPABILITY_ENTITLEMENT_LIVE_IDS_SNAPSHOT = [
141
+ "account.self.manage",
142
+ "admin:outbox:manage",
143
+ "admin:outbox:read",
144
+ "analytics:benchmark:read",
145
+ "analytics:detailed:manage",
146
+ "analytics:detailed:read",
147
+ "analytics:mission-control:export",
148
+ "analytics:mission-control:read",
149
+ "analytics:pii:manage",
150
+ "analytics:pii:read",
151
+ "analytics:summary:manage",
152
+ "analytics:summary:read",
153
+ "config:payments:manage",
154
+ "config:payments:read",
155
+ "config:pricing:kiosk:override",
156
+ "config:pricing:manage",
157
+ "config:pricing:read",
158
+ "config:tenant:manage",
159
+ "config:tenant:read",
160
+ "dev:aggregates:read",
161
+ "dev:aggregates:run",
162
+ "dev:analytics:explore:export",
163
+ "dev:analytics:explore:read",
164
+ "dev:analytics:mission-control:export",
165
+ "dev:analytics:mission-control:read",
166
+ "dev:analytics:read",
167
+ "dev:analytics:run",
168
+ "dev:compliance:audit:read",
169
+ "dev:compliance:gdpr:read",
170
+ "dev:outbox:approve:replay",
171
+ "dev:outbox:manage",
172
+ "dev:outbox:operate:abandon",
173
+ "dev:outbox:operate:replay:dryrun",
174
+ "dev:outbox:operate:replay:execute",
175
+ "dev:outbox:operate:retry",
176
+ "dev:outbox:read",
177
+ "dev:overview:manage",
178
+ "dev:overview:read",
179
+ "dev:reconciliation:manage",
180
+ "dev:reconciliation:read",
181
+ "dev:retention:manage",
182
+ "dev:retention:read",
183
+ "dev:tenants:create",
184
+ "dev:tenants:delete",
185
+ "dev:tenants:manage",
186
+ "dev:tenants:payments:manage",
187
+ "dev:tenants:read",
188
+ "dev:users:manage",
189
+ "dev:users:read",
190
+ "dev:workers:read",
191
+ "dev:workers:resolve-refund-candidate",
192
+ "dev:workers:run",
193
+ "exceptions.complianceSensitiveAccess",
194
+ "exceptions.crossTenantReplayExecute",
195
+ "exceptions.refundResolve",
196
+ "exceptions.tenantPermanentDelete",
197
+ "finance:detailed:manage",
198
+ "finance:detailed:read",
199
+ "finance:export:manage",
200
+ "finance:export:read",
201
+ "finance:pii:manage",
202
+ "finance:pii:read",
203
+ "finance:refunds:manage",
204
+ "finance:refunds:read",
205
+ "finance:settlements:manage",
206
+ "finance:settlements:read",
207
+ "finance:view:manage",
208
+ "finance:view:read",
209
+ "hold_floor_override",
210
+ "loyalty:campaigns:manage",
211
+ "loyalty:campaigns:read",
212
+ "loyalty:config:manage",
213
+ "loyalty:config:read",
214
+ "loyalty:coupons:activate",
215
+ "loyalty:coupons:read",
216
+ "loyalty:enrollment:manage",
217
+ "loyalty:platform-campaigns:manage",
218
+ "loyalty:profiling:consent",
219
+ "loyalty:reports:read",
220
+ "loyalty:wallet:read",
221
+ "ops:branding:manage",
222
+ "ops:branding:read",
223
+ "ops:donation-projects:manage",
224
+ "ops:donation-projects:read",
225
+ "ops:donation-templates:manage",
226
+ "ops:donation-templates:read",
227
+ "ops:inventory:checkup.hold_floor_override",
228
+ "ops:inventory:incident_review_high_impact",
229
+ "ops:inventory:manage",
230
+ "ops:inventory:read",
231
+ "ops:orders:complete",
232
+ "ops:orders:fulfill:read",
233
+ "ops:orders:fulfill:update",
234
+ "ops:products:manage",
235
+ "ops:products:read",
236
+ "ops:sales-points:donation:amounts",
237
+ "ops:sales-points:donation:assign",
238
+ "ops:sales-points:manage",
239
+ "ops:sales-points:provider-slots:read",
240
+ "ops:sales-points:read",
241
+ "ops:transactions:manage",
242
+ "ops:transactions:read",
243
+ "permissionsCatalog.view",
244
+ "pickup_devices:read",
245
+ "pickup_devices:write",
246
+ "platform.aggregates.manage",
247
+ "platform.aggregates.view",
248
+ "platform.analyticsExplore.manage",
249
+ "platform.analyticsExplore.view",
250
+ "platform.analyticsPipeline.manage",
251
+ "platform.analyticsPipeline.view",
252
+ "platform.auditFinalizeIncident.manage",
253
+ "platform.categories.manage",
254
+ "platform.categories.view",
255
+ "platform.complianceAudit.view",
256
+ "platform.complianceGdpr.view",
257
+ "platform.complianceRetentionDelete.manage",
258
+ "platform.devUsers.manage",
259
+ "platform.devUsers.view",
260
+ "platform.hardeningMetrics.view",
261
+ "platform.httpStorm.manage",
262
+ "platform.httpStorm.view",
263
+ "platform.outbox.manage",
264
+ "platform.outbox.view",
265
+ "platform.outboxReplay.approvalRequestApprove",
266
+ "platform.outboxReplay.approvalRequestCreate",
267
+ "platform.outboxReplay.approvalRequestRevoke",
268
+ "platform.outboxReplay.dryRun",
269
+ "platform.outboxReplay.execute",
270
+ "platform.overview.manage",
271
+ "platform.overview.view",
272
+ "platform.reconciliation.manage",
273
+ "platform.reconciliation.view",
274
+ "platform.retention.manage",
275
+ "platform.retention.view",
276
+ "platform.retentionWorkers.manage",
277
+ "platform.retentionWorkers.view",
278
+ "platform.successIncident.manage",
279
+ "platform.successIncident.view",
280
+ "platform.tenantPayments.manage",
281
+ "platform.tenants.manage",
282
+ "platform.tenants.view",
283
+ "platform.userCapabilities.manage",
284
+ "platform.userCapabilities.view",
285
+ "platform.userTenantAssignments.manage",
286
+ "platform.userTenantAssignments.view",
287
+ "platform.users.manage",
288
+ "platform.users.view",
289
+ "principal.view",
290
+ "promo:events:enroll",
291
+ "promo:events:manage",
292
+ "promo:rewards:activate",
293
+ "promo:rewards:read",
294
+ "system:feature-flags:manage",
295
+ "system:feature-flags:read",
296
+ "system:health:manage",
297
+ "system:health:read",
298
+ "system:logs:manage",
299
+ "system:logs:read",
300
+ "system:pii:manage",
301
+ "system:pii:read",
302
+ "system:secrets:manage",
303
+ "system:secrets:read",
304
+ "tenant.adminEvents.subscribe",
305
+ "tenant.adminUserCapabilities.manage",
306
+ "tenant.adminUserCapabilities.view",
307
+ "tenant.adminUsers.manage",
308
+ "tenant.adminUsers.view",
309
+ "tenant.analyticsBenchmark.view",
310
+ "tenant.analyticsDetailed.manage",
311
+ "tenant.analyticsDetailed.view",
312
+ "tenant.analyticsPii.manage",
313
+ "tenant.analyticsPii.view",
314
+ "tenant.analyticsSummary.manage",
315
+ "tenant.analyticsSummary.view",
316
+ "tenant.bankAccounts.manage",
317
+ "tenant.bankAccounts.read",
318
+ "tenant.bankInbox.manage",
319
+ "tenant.bankInbox.read",
320
+ "tenant.branding.manage",
321
+ "tenant.branding.view",
322
+ "tenant.comms.credentials.read",
323
+ "tenant.comms.credentials.write",
324
+ "tenant.configPricing.manage",
325
+ "tenant.configPricing.view",
326
+ "tenant.configTenant.manage",
327
+ "tenant.configTenant.view",
328
+ "tenant.donationProjects.manage",
329
+ "tenant.donationProjects.view",
330
+ "tenant.donationTemplates.manage",
331
+ "tenant.donationTemplates.view",
332
+ "tenant.financeApproveSettlement.manage",
333
+ "tenant.financeDetailed.manage",
334
+ "tenant.financeDetailed.view",
335
+ "tenant.financeExport.manage",
336
+ "tenant.financeExport.view",
337
+ "tenant.financePii.manage",
338
+ "tenant.financePii.view",
339
+ "tenant.financeRefunds.manage",
340
+ "tenant.financeRefunds.view",
341
+ "tenant.financeSettlements.manage",
342
+ "tenant.financeSettlements.view",
343
+ "tenant.financeView.manage",
344
+ "tenant.financeView.view",
345
+ "tenant.inventory.incidentHighImpact.review",
346
+ "tenant.inventory.manage",
347
+ "tenant.inventory.view",
348
+ "tenant.kioskDonationAmounts.manage",
349
+ "tenant.kioskDonationAssign.manage",
350
+ "tenant.kiosks.manage",
351
+ "tenant.kiosks.view",
352
+ "tenant.orders.complete",
353
+ "tenant.orders.fulfill.read",
354
+ "tenant.orders.fulfill.update",
355
+ "tenant.orders.pickup.hold",
356
+ "tenant.orders.pickup.holdFloorOverride",
357
+ "tenant.orders.pickup.refuse",
358
+ "tenant.orders.pickup.reprint",
359
+ "tenant.orders.pickup.scan",
360
+ "tenant.outbox.manage",
361
+ "tenant.outbox.view",
362
+ "tenant.paymentClaims.approve",
363
+ "tenant.paymentCredentials.manage",
364
+ "tenant.paymentCredentials.view",
365
+ "tenant.paymentPreferences.manage",
366
+ "tenant.paymentPreferences.view",
367
+ "tenant.paymentsIntegration.manage",
368
+ "tenant.paymentsIntegration.view",
369
+ "tenant.pickupDevices.manage",
370
+ "tenant.pickupDevices.read",
371
+ "tenant.pickupPoints.manage",
372
+ "tenant.pickupPoints.read",
373
+ "tenant.policyApproval.manage",
374
+ "tenant.pricingKioskOverride.manage",
375
+ "tenant.products.manage",
376
+ "tenant.products.view",
377
+ "tenant.reconciliation.read",
378
+ "tenant.systemFeatureFlags.manage",
379
+ "tenant.systemFeatureFlags.view",
380
+ "tenant.systemHealth.manage",
381
+ "tenant.systemHealth.view",
382
+ "tenant.systemLogs.manage",
383
+ "tenant.systemLogs.view",
384
+ "tenant.systemPii.manage",
385
+ "tenant.systemPii.view",
386
+ "tenant.systemSecrets.manage",
387
+ "tenant.systemSecrets.view",
388
+ "tenant.transactions.manage",
389
+ "tenant.transactions.view",
390
+ "users:admins:create",
391
+ "users:view:manage",
392
+ "users:view:read",
393
+ ];
394
+ const AUTHORING_REQUIREMENT_SEED = [
395
+ // RBAC / users
396
+ {
397
+ authoringTokens: [
398
+ "tenant.adminUsers.view/manage",
399
+ "users:view:read",
400
+ "users:admins:create",
401
+ "users:view:manage",
402
+ ],
403
+ requiredBlockKeys: [
404
+ "permission_management_rbac",
405
+ ],
406
+ match: 'ALL',
407
+ },
408
+ // RBAC / users
409
+ {
410
+ authoringTokens: [
411
+ "tenant.adminUserCapabilities.view/manage",
412
+ ],
413
+ requiredBlockKeys: [
414
+ "permission_management_rbac",
415
+ ],
416
+ match: 'ALL',
417
+ },
418
+ // RBAC / users
419
+ {
420
+ authoringTokens: [
421
+ "permissionsCatalog.view",
422
+ ],
423
+ requiredBlockKeys: [
424
+ "permission_management_rbac",
425
+ ],
426
+ match: 'ALL',
427
+ },
428
+ // RBAC / users
429
+ {
430
+ authoringTokens: [
431
+ "tenant.policyApproval.manage",
432
+ ],
433
+ entitlementExempt: true,
434
+ match: 'ALL',
435
+ },
436
+ // Catalog
437
+ {
438
+ authoringTokens: [
439
+ "tenant.products.*",
440
+ "ops:products:read/manage",
441
+ ],
442
+ requiredBlockKeys: [
443
+ "product_vending",
444
+ ],
445
+ match: 'ALL',
446
+ },
447
+ // Catalog
448
+ {
449
+ authoringTokens: [
450
+ "tenant.kiosks.*",
451
+ "ops:sales-points:read/manage",
452
+ ],
453
+ requiredBlockKeys: [
454
+ "sales_point_management",
455
+ ],
456
+ match: 'ALL',
457
+ },
458
+ // Catalog
459
+ {
460
+ authoringTokens: [
461
+ "tenant.inventory.view/manage",
462
+ "ops:inventory:read/manage",
463
+ ],
464
+ requiredBlockKeys: [
465
+ "inventory_management",
466
+ ],
467
+ match: 'ALL',
468
+ },
469
+ // Catalog
470
+ {
471
+ authoringTokens: [
472
+ "tenant.inventory.incidentHighImpact.review",
473
+ "ops:inventory:incident_review_high_impact",
474
+ ],
475
+ requiredBlockKeys: [
476
+ "inventory_incidents",
477
+ ],
478
+ match: 'ALL',
479
+ },
480
+ // Catalog
481
+ {
482
+ authoringTokens: [
483
+ "tenant.donationProjects.*",
484
+ "ops:donation-projects:read/manage",
485
+ ],
486
+ requiredBlockKeys: [
487
+ "donation",
488
+ ],
489
+ match: 'ALL',
490
+ },
491
+ // Catalog
492
+ {
493
+ authoringTokens: [
494
+ "tenant.donationTemplates.*",
495
+ "ops:donation-templates:read/manage",
496
+ ],
497
+ requiredBlockKeys: [
498
+ "donation",
499
+ ],
500
+ match: 'ALL',
501
+ },
502
+ // Catalog
503
+ {
504
+ authoringTokens: [
505
+ "tenant.kioskDonationAssign.manage",
506
+ "tenant.kioskDonationAmounts.manage",
507
+ "ops:sales-points:donation:assign/amounts",
508
+ ],
509
+ requiredBlockKeys: [
510
+ "donation",
511
+ ],
512
+ match: 'ALL',
513
+ },
514
+ // Catalog
515
+ {
516
+ authoringTokens: [
517
+ "tenant.branding.*",
518
+ "ops:branding:read/manage",
519
+ ],
520
+ requiredBlockKeys: [
521
+ "tenant_ops_settings",
522
+ ],
523
+ match: 'ALL',
524
+ },
525
+ // Orders
526
+ {
527
+ authoringTokens: [
528
+ "tenant.orders.complete",
529
+ "ops:orders:complete",
530
+ ],
531
+ requiredBlockKeys: [
532
+ "fulfillment_queue",
533
+ ],
534
+ match: 'ALL',
535
+ },
536
+ // Orders
537
+ {
538
+ authoringTokens: [
539
+ "tenant.orders.fulfill.read/update",
540
+ "ops:orders:fulfill:read/update",
541
+ ],
542
+ requiredBlockKeys: [
543
+ "fulfillment_queue",
544
+ ],
545
+ match: 'ALL',
546
+ },
547
+ // Orders
548
+ {
549
+ authoringTokens: [
550
+ "tenant.orders.pickup.scan/refuse/hold/reprint",
551
+ ],
552
+ requiredBlockKeys: [
553
+ "staff_pickup_scan",
554
+ ],
555
+ match: 'ALL',
556
+ },
557
+ // Orders
558
+ {
559
+ authoringTokens: [
560
+ "tenant.orders.pickup.holdFloorOverride",
561
+ "hold_floor_override",
562
+ "ops:inventory:checkup.hold_floor_override",
563
+ ],
564
+ requiredBlockKeys: [
565
+ "inventory_management",
566
+ ],
567
+ match: 'ALL',
568
+ },
569
+ // Orders
570
+ {
571
+ authoringTokens: [
572
+ "tenant.pickupPoints.*",
573
+ ],
574
+ requiredBlockKeys: [
575
+ "pickup_points",
576
+ ],
577
+ match: 'ALL',
578
+ },
579
+ // Orders
580
+ {
581
+ authoringTokens: [
582
+ "tenant.pickupDevices.*",
583
+ "pickup_devices:read/write",
584
+ ],
585
+ requiredBlockKeys: [
586
+ "fulfillment_queue",
587
+ ],
588
+ match: 'ALL',
589
+ },
590
+ // Payments
591
+ {
592
+ authoringTokens: [
593
+ "tenant.paymentCredentials.*",
594
+ "tenant.paymentsIntegration.*",
595
+ "config:payments:read/manage",
596
+ ],
597
+ requiredBlockKeys: [
598
+ "payment_rails_strategy",
599
+ ],
600
+ match: 'ALL',
601
+ },
602
+ // Payments
603
+ {
604
+ authoringTokens: [
605
+ "tenant.paymentPreferences.*",
606
+ ],
607
+ requiredBlockKeys: [
608
+ "tenant_ops_settings",
609
+ ],
610
+ match: 'ALL',
611
+ },
612
+ // Payments
613
+ {
614
+ authoringTokens: [
615
+ "tenant.bankAccounts.*",
616
+ ],
617
+ requiredBlockKeys: [
618
+ "bank_account_administration",
619
+ ],
620
+ match: 'ALL',
621
+ },
622
+ // Payments
623
+ {
624
+ authoringTokens: [
625
+ "tenant.bankInbox.*",
626
+ "tenant.paymentClaims.approve",
627
+ ],
628
+ requiredBlockKeys: [
629
+ "bank_inbox_claims_api",
630
+ ],
631
+ match: 'ALL',
632
+ },
633
+ // Payments — copy PAYMENTS_HUB_NAV_ENTITLEMENT_ALL_OF
634
+ {
635
+ authoringTokens: [
636
+ "tenant.reconciliation.read",
637
+ ],
638
+ requiredBlockKeys: [...PAYMENTS_HUB_NAV_ENTITLEMENT_ALL_OF],
639
+ match: 'ALL',
640
+ },
641
+ // Payments
642
+ {
643
+ authoringTokens: [
644
+ "tenant.transactions.*",
645
+ "ops:transactions:read/manage",
646
+ ],
647
+ requiredBlockKeys: [
648
+ "transactions",
649
+ ],
650
+ match: 'ALL',
651
+ },
652
+ // Payments — hub chrome (same ALL_OF as reconciliation)
653
+ {
654
+ authoringTokens: [
655
+ "tenant.financeView.*",
656
+ "tenant.financeDetailed.*",
657
+ "tenant.financePii.*",
658
+ "tenant.financeExport.*",
659
+ "finance:view:*|finance:detailed:*|finance:pii:*|finance:export:*",
660
+ ],
661
+ requiredBlockKeys: [...PAYMENTS_HUB_NAV_ENTITLEMENT_ALL_OF],
662
+ match: 'ALL',
663
+ },
664
+ // Payments
665
+ {
666
+ authoringTokens: [
667
+ "tenant.financeSettlements.*",
668
+ "finance:settlements:*",
669
+ ],
670
+ requiredBlockKeys: [
671
+ "payment_reconciliation",
672
+ ],
673
+ match: 'ALL',
674
+ },
675
+ // Payments
676
+ {
677
+ authoringTokens: [
678
+ "tenant.financeRefunds.*",
679
+ "finance:refunds:*",
680
+ ],
681
+ requiredBlockKeys: [
682
+ "transactions",
683
+ ],
684
+ match: 'ALL',
685
+ },
686
+ // Payments
687
+ {
688
+ authoringTokens: [
689
+ "tenant.financeApproveSettlement.manage",
690
+ ],
691
+ requiredBlockKeys: [
692
+ "payment_reconciliation",
693
+ ],
694
+ match: 'ALL',
695
+ },
696
+ // Payments
697
+ {
698
+ authoringTokens: [
699
+ "exceptions.refundResolve",
700
+ ],
701
+ requiredBlockKeys: [
702
+ "transactions",
703
+ ],
704
+ match: 'ALL',
705
+ },
706
+ // Comms
707
+ {
708
+ authoringTokens: [
709
+ "tenant.comms.credentials.*",
710
+ ],
711
+ requiredBlockKeys: [
712
+ "comms_governance",
713
+ ],
714
+ match: 'ALL',
715
+ },
716
+ // Comms — commercial admin:outbox / tenant.outbox caps are entitlementExempt.
717
+ // Události tab/nav/SIC APIs gate solely via incident_centre_ui (route registry).
718
+ // Inbox routes gate via admin_notifications. Do NOT couple outbox grants to SIC.
719
+ // Platform platform.successIncident.* / platform.outbox.* / dev:outbox:* stay
720
+ // entitlementExempt (SUPER_DEV_ONLY) via other rows.
721
+ {
722
+ authoringTokens: [
723
+ "tenant.outbox.*",
724
+ "admin:outbox:read/manage",
725
+ ],
726
+ entitlementExempt: true,
727
+ match: 'ALL',
728
+ },
729
+ // Comms
730
+ {
731
+ authoringTokens: [
732
+ "tenant.adminEvents.subscribe",
733
+ ],
734
+ requiredBlockKeys: [
735
+ "tenant_ops_settings",
736
+ ],
737
+ match: 'ALL',
738
+ },
739
+ // Analytics
740
+ {
741
+ authoringTokens: [
742
+ "tenant.analyticsSummary.*",
743
+ "analytics:summary:read/manage",
744
+ ],
745
+ requiredBlockKeys: [
746
+ "analytics_summary",
747
+ ],
748
+ match: 'ALL',
749
+ },
750
+ // Analytics
751
+ {
752
+ authoringTokens: [
753
+ "tenant.analyticsDetailed.*",
754
+ "analytics:detailed:read/manage",
755
+ ],
756
+ requiredBlockKeys: [
757
+ "analytics_detailed",
758
+ ],
759
+ match: 'ALL',
760
+ },
761
+ // Analytics — copy EXPLORE_ENTITLEMENT_ALL_OF
762
+ {
763
+ authoringTokens: [
764
+ "tenant.analyticsPii.*",
765
+ "analytics:pii:read/manage",
766
+ ],
767
+ requiredBlockKeys: [...EXPLORE_ENTITLEMENT_ALL_OF],
768
+ match: 'ALL',
769
+ },
770
+ // Analytics
771
+ {
772
+ authoringTokens: [
773
+ "tenant.analyticsBenchmark.view",
774
+ "analytics:benchmark:read",
775
+ ],
776
+ requiredBlockKeys: [
777
+ "analytics_benchmark",
778
+ ],
779
+ match: 'ALL',
780
+ },
781
+ // Analytics
782
+ {
783
+ authoringTokens: [
784
+ "analytics:mission-control:read/export",
785
+ ],
786
+ requiredBlockKeys: [
787
+ "mission_control",
788
+ ],
789
+ match: 'ALL',
790
+ },
791
+ // Tax/config
792
+ {
793
+ authoringTokens: [
794
+ "tenant.configPricing.*",
795
+ "tenant.pricingKioskOverride.manage",
796
+ "config:pricing:*",
797
+ "config:pricing:kiosk:override",
798
+ ],
799
+ requiredBlockKeys: [
800
+ "tax_management",
801
+ ],
802
+ match: 'ALL',
803
+ },
804
+ // Tax/config
805
+ {
806
+ authoringTokens: [
807
+ "tenant.configTenant.*",
808
+ "config:tenant:read/manage",
809
+ ],
810
+ requiredBlockKeys: [
811
+ "tenant_ops_settings",
812
+ ],
813
+ match: 'ALL',
814
+ },
815
+ // Tax/config
816
+ {
817
+ authoringTokens: [
818
+ "tenant.systemHealth.*",
819
+ "tenant.systemFeatureFlags.*",
820
+ "tenant.systemSecrets.*",
821
+ "system:health:*|system:feature-flags:*|system:secrets:*",
822
+ ],
823
+ requiredBlockKeys: [
824
+ "tenant_ops_settings",
825
+ ],
826
+ match: 'ALL',
827
+ },
828
+ // Tax/config
829
+ {
830
+ authoringTokens: [
831
+ "tenant.systemLogs.*",
832
+ "system:logs:*",
833
+ ],
834
+ requiredBlockKeys: [
835
+ "audit_logs_admin_ui",
836
+ ],
837
+ match: 'ALL',
838
+ },
839
+ // Tax/config
840
+ {
841
+ authoringTokens: [
842
+ "tenant.systemPii.*",
843
+ "system:pii:*",
844
+ ],
845
+ entitlementExempt: true,
846
+ match: 'ALL',
847
+ },
848
+ // Tax/config
849
+ {
850
+ authoringTokens: [
851
+ "exceptions.complianceSensitiveAccess",
852
+ ],
853
+ entitlementExempt: true,
854
+ match: 'ALL',
855
+ },
856
+ // Tax/config
857
+ {
858
+ authoringTokens: [
859
+ "exceptions.tenantPermanentDelete",
860
+ ],
861
+ entitlementExempt: true,
862
+ match: 'ALL',
863
+ },
864
+ // Loyalty
865
+ {
866
+ authoringTokens: [
867
+ "loyalty:wallet:read",
868
+ "loyalty:coupons:*",
869
+ "loyalty:campaigns:*",
870
+ "loyalty:enrollment:manage",
871
+ "loyalty:reports:read",
872
+ "loyalty:config:*",
873
+ "loyalty:profiling:consent",
874
+ ],
875
+ requiredBlockKeys: [
876
+ "loyalty_program",
877
+ ],
878
+ match: 'ALL',
879
+ },
880
+ // Loyalty
881
+ {
882
+ authoringTokens: [
883
+ "promo:rewards:*",
884
+ "promo:events:*",
885
+ ],
886
+ requiredBlockKeys: [
887
+ "promotions_program",
888
+ ],
889
+ match: 'ALL',
890
+ },
891
+ // Loyalty
892
+ {
893
+ authoringTokens: [
894
+ "ops:sales-points:provider-slots:read",
895
+ ],
896
+ requiredBlockKeys: [
897
+ "surface_kiosk",
898
+ ],
899
+ match: 'ALL',
900
+ },
901
+ // Loyalty
902
+ {
903
+ authoringTokens: [
904
+ "loyalty:platform-campaigns:manage",
905
+ ],
906
+ entitlementExempt: true,
907
+ match: 'ALL',
908
+ },
909
+ // Out-of-U
910
+ {
911
+ authoringTokens: [
912
+ "platform.aggregates.manage",
913
+ "platform.aggregates.view",
914
+ "platform.analyticsExplore.manage",
915
+ "platform.analyticsExplore.view",
916
+ "platform.analyticsPipeline.manage",
917
+ "platform.analyticsPipeline.view",
918
+ "platform.auditFinalizeIncident.manage",
919
+ "platform.categories.manage",
920
+ "platform.categories.view",
921
+ "platform.complianceAudit.view",
922
+ "platform.complianceGdpr.view",
923
+ "platform.complianceRetentionDelete.manage",
924
+ "platform.devUsers.manage",
925
+ "platform.devUsers.view",
926
+ "platform.hardeningMetrics.view",
927
+ "platform.httpStorm.manage",
928
+ "platform.httpStorm.view",
929
+ "platform.outbox.manage",
930
+ "platform.outbox.view",
931
+ "platform.outboxReplay.approvalRequestApprove",
932
+ "platform.outboxReplay.approvalRequestCreate",
933
+ "platform.outboxReplay.approvalRequestRevoke",
934
+ "platform.outboxReplay.dryRun",
935
+ "platform.outboxReplay.execute",
936
+ "platform.overview.manage",
937
+ "platform.overview.view",
938
+ "platform.reconciliation.manage",
939
+ "platform.reconciliation.view",
940
+ "platform.retention.manage",
941
+ "platform.retention.view",
942
+ "platform.retentionWorkers.manage",
943
+ "platform.retentionWorkers.view",
944
+ "platform.successIncident.manage",
945
+ "platform.successIncident.view",
946
+ "platform.tenantPayments.manage",
947
+ "platform.tenants.manage",
948
+ "platform.tenants.view",
949
+ "platform.userCapabilities.manage",
950
+ "platform.userCapabilities.view",
951
+ "platform.userTenantAssignments.manage",
952
+ "platform.userTenantAssignments.view",
953
+ "platform.users.manage",
954
+ "platform.users.view",
955
+ ],
956
+ entitlementExempt: true,
957
+ match: 'ALL',
958
+ },
959
+ // Out-of-U
960
+ {
961
+ authoringTokens: [
962
+ "exceptions.crossTenantReplayExecute",
963
+ ],
964
+ entitlementExempt: true,
965
+ match: 'ALL',
966
+ },
967
+ // Out-of-U
968
+ {
969
+ authoringTokens: [
970
+ "dev:aggregates:read",
971
+ "dev:aggregates:run",
972
+ "dev:analytics:explore:export",
973
+ "dev:analytics:explore:read",
974
+ "dev:analytics:mission-control:export",
975
+ "dev:analytics:mission-control:read",
976
+ "dev:analytics:read",
977
+ "dev:analytics:run",
978
+ "dev:compliance:audit:read",
979
+ "dev:compliance:gdpr:read",
980
+ "dev:outbox:approve:replay",
981
+ "dev:outbox:manage",
982
+ "dev:outbox:operate:abandon",
983
+ "dev:outbox:operate:replay:dryrun",
984
+ "dev:outbox:operate:replay:execute",
985
+ "dev:outbox:operate:retry",
986
+ "dev:outbox:read",
987
+ "dev:overview:manage",
988
+ "dev:overview:read",
989
+ "dev:reconciliation:manage",
990
+ "dev:reconciliation:read",
991
+ "dev:retention:manage",
992
+ "dev:retention:read",
993
+ "dev:tenants:create",
994
+ "dev:tenants:delete",
995
+ "dev:tenants:manage",
996
+ "dev:tenants:payments:manage",
997
+ "dev:tenants:read",
998
+ "dev:users:manage",
999
+ "dev:users:read",
1000
+ "dev:workers:read",
1001
+ "dev:workers:resolve-refund-candidate",
1002
+ "dev:workers:run",
1003
+ ],
1004
+ entitlementExempt: true,
1005
+ match: 'ALL',
1006
+ },
1007
+ // Out-of-U
1008
+ {
1009
+ authoringTokens: [
1010
+ "principal.view",
1011
+ "account.self.manage",
1012
+ ],
1013
+ entitlementExempt: true,
1014
+ match: 'ALL',
1015
+ },
1016
+ ];
1017
+ function buildRuntimeRequirements(seed, liveIds) {
1018
+ const rows = [];
1019
+ for (const row of seed) {
1020
+ const capabilityKeys = expandAuthoringTokens(row.authoringTokens, liveIds);
1021
+ for (const key of capabilityKeys) {
1022
+ if (key.includes('*') || key.includes('|') || key.includes('/')) {
1023
+ throw new Error(`capabilityKeys must be expanded literals only; got ${JSON.stringify(key)}`);
1024
+ }
1025
+ }
1026
+ if (row.entitlementExempt === true) {
1027
+ rows.push({
1028
+ capabilityKeys,
1029
+ entitlementExempt: true,
1030
+ match: row.match,
1031
+ });
1032
+ continue;
1033
+ }
1034
+ const requiredBlockKeys = row.requiredBlockKeys ?? [];
1035
+ if (requiredBlockKeys.length === 0) {
1036
+ throw new Error('non-exempt grant row requires non-empty requiredBlockKeys');
1037
+ }
1038
+ for (const block of requiredBlockKeys) {
1039
+ if (NEVER_REQUIRED_BLOCK_KEYS.includes(block)) {
1040
+ throw new Error(`requiredBlockKeys must not include CORE_IMMUTABLE ${block}`);
1041
+ }
1042
+ if (block === 'order_pickup_infrastructure') {
1043
+ throw new Error('pickup grants must use leaf staff_pickup_scan only');
1044
+ }
1045
+ }
1046
+ rows.push({
1047
+ capabilityKeys,
1048
+ requiredBlockKeys,
1049
+ match: row.match,
1050
+ });
1051
+ }
1052
+ return rows;
1053
+ }
1054
+ export const CAPABILITY_ENTITLEMENT_REQUIREMENTS = buildRuntimeRequirements(AUTHORING_REQUIREMENT_SEED, CAPABILITY_ENTITLEMENT_LIVE_IDS_SNAPSHOT);
1055
+ function requirementSignature(entry) {
1056
+ if (entry.kind === 'exempt')
1057
+ return 'exempt';
1058
+ return `blocks:${entry.match}:${[...entry.blockKeys].join(',')}`;
1059
+ }
1060
+ function buildCapabilityIndex(requirements) {
1061
+ const index = new Map();
1062
+ for (const row of requirements) {
1063
+ const entry = row.entitlementExempt === true
1064
+ ? { kind: 'exempt' }
1065
+ : {
1066
+ kind: 'blocks',
1067
+ blockKeys: row.requiredBlockKeys ?? [],
1068
+ match: row.match,
1069
+ };
1070
+ if (entry.kind === 'blocks' && entry.blockKeys.length === 0) {
1071
+ throw new Error('empty requiredBlockKeys on non-exempt row');
1072
+ }
1073
+ // ALL = every listed block write-ALLOW; ANY = at least one (shared caps across packs).
1074
+ const sig = requirementSignature(entry);
1075
+ for (const key of row.capabilityKeys) {
1076
+ const existing = index.get(key);
1077
+ if (existing !== undefined) {
1078
+ if (requirementSignature(existing) !== sig) {
1079
+ throw new Error(`capability ${JSON.stringify(key)} mapped to conflicting entitlement requirements`);
1080
+ }
1081
+ continue;
1082
+ }
1083
+ index.set(key, entry);
1084
+ }
1085
+ }
1086
+ return index;
1087
+ }
1088
+ const CAPABILITY_REQUIREMENT_INDEX = buildCapabilityIndex(CAPABILITY_ENTITLEMENT_REQUIREMENTS);
1089
+ const BLOCK_TO_CAPABILITIES = (() => {
1090
+ const map = new Map();
1091
+ for (const [capabilityKey, entry] of CAPABILITY_REQUIREMENT_INDEX) {
1092
+ if (entry.kind !== 'blocks')
1093
+ continue;
1094
+ for (const blockKey of entry.blockKeys) {
1095
+ const list = map.get(blockKey) ?? [];
1096
+ list.push(capabilityKey);
1097
+ map.set(blockKey, list);
1098
+ }
1099
+ }
1100
+ for (const [blockKey, list] of map) {
1101
+ list.sort((a, b) => a.localeCompare(b));
1102
+ map.set(blockKey, list);
1103
+ }
1104
+ return map;
1105
+ })();
1106
+ export function requiredBlocksForCapability(capabilityKey) {
1107
+ const entry = CAPABILITY_REQUIREMENT_INDEX.get(capabilityKey);
1108
+ if (entry === undefined) {
1109
+ return { kind: 'unmapped' };
1110
+ }
1111
+ if (entry.kind === 'exempt') {
1112
+ return { kind: 'exempt' };
1113
+ }
1114
+ return {
1115
+ kind: 'blocks',
1116
+ blockKeys: entry.blockKeys,
1117
+ match: entry.match,
1118
+ };
1119
+ }
1120
+ export function capabilitiesRequiringBlock(blockKey) {
1121
+ return BLOCK_TO_CAPABILITIES.get(blockKey) ?? [];
1122
+ }
1123
+ /**
1124
+ * Evaluate whether a capability is entitled given a write-ALLOW predicate on block keys.
1125
+ * ALL: every required block must be write-allowed.
1126
+ * ANY: at least one required block must be write-allowed (reserved; CapMap is ALL-only —
1127
+ * commercial outbox grants are entitlementExempt, not ANY(SIC|notifications)).
1128
+ */
1129
+ export function evaluateCapabilityEntitlement(capabilityKey, options) {
1130
+ const lookup = requiredBlocksForCapability(capabilityKey);
1131
+ if (lookup.kind === 'exempt') {
1132
+ return { allowed: true, missingBlockKeys: [] };
1133
+ }
1134
+ if (lookup.kind === 'unmapped') {
1135
+ return { allowed: false, missingBlockKeys: [] };
1136
+ }
1137
+ if (lookup.blockKeys.length === 0) {
1138
+ return { allowed: false, missingBlockKeys: [] };
1139
+ }
1140
+ if (lookup.match === 'ANY') {
1141
+ const anyAllowed = lookup.blockKeys.some((k) => options.isWriteAllowed(k));
1142
+ if (anyAllowed) {
1143
+ return { allowed: true, missingBlockKeys: [] };
1144
+ }
1145
+ return { allowed: false, missingBlockKeys: [...lookup.blockKeys] };
1146
+ }
1147
+ // ALL
1148
+ const missingBlockKeys = lookup.blockKeys.filter((k) => !options.isWriteAllowed(k));
1149
+ return {
1150
+ allowed: missingBlockKeys.length === 0,
1151
+ missingBlockKeys,
1152
+ };
1153
+ }
1154
+ //# sourceMappingURL=capabilityEntitlementRequirements.js.map