@objectstack/core 17.0.0-rc.5 → 17.0.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/CHANGELOG.md +3293 -0
- package/dist/index.cjs +370 -72
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +588 -43
- package/dist/index.d.ts +588 -43
- package/dist/index.js +346 -63
- package/dist/index.js.map +1 -1
- package/dist/logger.cjs +9 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.js +9 -1
- package/dist/logger.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -35,13 +35,17 @@ __export(index_exports, {
|
|
|
35
35
|
ANONYMOUS_DENY_MESSAGE: () => ANONYMOUS_DENY_MESSAGE,
|
|
36
36
|
ANONYMOUS_DENY_STATUS: () => ANONYMOUS_DENY_STATUS,
|
|
37
37
|
API_KEY_PREFIX: () => API_KEY_PREFIX,
|
|
38
|
+
AUDIENCE_BINDING_SUGGESTION_STATUSES: () => AUDIENCE_BINDING_SUGGESTION_STATUSES,
|
|
39
|
+
AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES: () => AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES,
|
|
38
40
|
CORE_FALLBACK_FACTORIES: () => CORE_FALLBACK_FACTORIES,
|
|
39
41
|
DependencyResolver: () => DependencyResolver,
|
|
42
|
+
ENTRY_EXECUTION_CONTEXT_FIELDS: () => ENTRY_EXECUTION_CONTEXT_FIELDS,
|
|
40
43
|
HotReloadManager: () => HotReloadManager,
|
|
41
44
|
LiteKernel: () => LiteKernel,
|
|
42
45
|
MigrationJournalRefusal: () => MigrationJournalRefusal,
|
|
43
46
|
MigrationPlanRegistry: () => MigrationPlanRegistry,
|
|
44
47
|
NamespaceResolver: () => NamespaceResolver,
|
|
48
|
+
OPERATION_PRIVATE_KEY_PREFIX: () => OPERATION_PRIVATE_KEY_PREFIX,
|
|
45
49
|
ObjectKernel: () => ObjectKernel,
|
|
46
50
|
ObjectKernelBase: () => ObjectKernelBase,
|
|
47
51
|
ObjectLogger: () => ObjectLogger,
|
|
@@ -63,12 +67,17 @@ __export(index_exports, {
|
|
|
63
67
|
ServiceLifecycle: () => ServiceLifecycle,
|
|
64
68
|
UnknownFilterTokenError: () => UnknownFilterTokenError,
|
|
65
69
|
UnresolvedFilterTokenError: () => UnresolvedFilterTokenError,
|
|
70
|
+
assembleExecutionContext: () => assembleExecutionContext,
|
|
71
|
+
assembleExecutionContextOrGuest: () => assembleExecutionContextOrGuest,
|
|
66
72
|
assertInitServiceRequirements: () => assertInitServiceRequirements,
|
|
73
|
+
assertMetadataRegisterContract: () => assertMetadataRegisterContract,
|
|
67
74
|
bucketKeyToCalendarRange: () => bucketKeyToCalendarRange,
|
|
68
75
|
buildPermissionsFromGrants: () => buildPermissionsFromGrants,
|
|
69
76
|
bulkWrite: () => bulkWrite,
|
|
70
77
|
calendarPartsInTz: () => calendarPartsInTz,
|
|
71
78
|
calendarPartsInTzOrUtc: () => calendarPartsInTzOrUtc,
|
|
79
|
+
canonicalMetadataServiceType: () => canonicalMetadataServiceType,
|
|
80
|
+
collectInternalWriteResponseFields: () => collectInternalWriteResponseFields,
|
|
72
81
|
counterSignPayload: () => counterSignPayload,
|
|
73
82
|
createLogger: () => createLogger,
|
|
74
83
|
createMemoryCache: () => createMemoryCache,
|
|
@@ -93,18 +102,22 @@ __export(index_exports, {
|
|
|
93
102
|
getMemoryUsage: () => getMemoryUsage,
|
|
94
103
|
hashApiKey: () => hashApiKey,
|
|
95
104
|
hashMigrationPlan: () => hashMigrationPlan,
|
|
105
|
+
isAudienceBindingSuggestionStatus: () => isAudienceBindingSuggestionStatus,
|
|
96
106
|
isAuthGateAllowlisted: () => isAuthGateAllowlisted,
|
|
97
107
|
isExpired: () => isExpired,
|
|
98
108
|
isGrantActive: () => isGrantActive,
|
|
99
109
|
isGrantExpired: () => isGrantExpired,
|
|
100
110
|
isNode: () => isNode,
|
|
101
111
|
nextUtcCalendarDay: () => import_data.nextUtcCalendarDay,
|
|
112
|
+
normalizeAuthGate: () => normalizeAuthGate,
|
|
113
|
+
omitInternalFieldsFromWriteResponse: () => omitInternalFieldsFromWriteResponse,
|
|
102
114
|
parseScopes: () => parseScopes,
|
|
103
115
|
parseSignature: () => parseSignature,
|
|
104
116
|
planChunks: () => planChunks,
|
|
105
117
|
postureVisibleRows: () => postureVisibleRows,
|
|
106
118
|
readAuthoredTranslationLayer: () => readAuthoredTranslationLayer,
|
|
107
119
|
readRunJournal: () => readRunJournal,
|
|
120
|
+
recordNotFoundError: () => recordNotFoundError,
|
|
108
121
|
resolveApiKeyPrincipal: () => resolveApiKeyPrincipal,
|
|
109
122
|
resolveAuthzContext: () => resolveAuthzContext,
|
|
110
123
|
resolveFilterToken: () => resolveFilterToken,
|
|
@@ -118,6 +131,7 @@ __export(index_exports, {
|
|
|
118
131
|
safeExit: () => safeExit,
|
|
119
132
|
shouldDenyAnonymous: () => shouldDenyAnonymous,
|
|
120
133
|
signPayload: () => signPayload,
|
|
134
|
+
unknownAudienceBindingSuggestionStatusMessage: () => unknownAudienceBindingSuggestionStatusMessage,
|
|
121
135
|
utcInstantMs: () => import_data.utcInstantMs,
|
|
122
136
|
validateInitServiceContract: () => validateInitServiceContract,
|
|
123
137
|
verifyPayload: () => verifyPayload,
|
|
@@ -126,6 +140,7 @@ __export(index_exports, {
|
|
|
126
140
|
verifyPublisherSignature: () => verifyPublisherSignature,
|
|
127
141
|
wireAuthoredTranslationSync: () => wireAuthoredTranslationSync,
|
|
128
142
|
withTransientRetry: () => withTransientRetry,
|
|
143
|
+
withoutOperationPrivateKeys: () => withoutOperationPrivateKeys,
|
|
129
144
|
zonedDateStartToUtcMs: () => zonedDateStartToUtcMs
|
|
130
145
|
});
|
|
131
146
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -213,6 +228,30 @@ function assertInitServiceRequirements(plugin, isServiceRegistered) {
|
|
|
213
228
|
}
|
|
214
229
|
}
|
|
215
230
|
|
|
231
|
+
// src/hook-dispatch.ts
|
|
232
|
+
function traceDispatch(name, handlers, logger) {
|
|
233
|
+
logger.debug(`Triggering hook: ${name}`, {
|
|
234
|
+
hook: name,
|
|
235
|
+
handlerCount: handlers.length
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
async function dispatchHookIsolating(name, handlers, logger, args = []) {
|
|
239
|
+
traceDispatch(name, handlers, logger);
|
|
240
|
+
for (const handler of handlers) {
|
|
241
|
+
try {
|
|
242
|
+
await handler(...args);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
logger.error(`Hook handler failed: ${name}`, error);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
async function dispatchHookPropagating(name, handlers, logger, args = []) {
|
|
249
|
+
if (logger) traceDispatch(name, handlers, logger);
|
|
250
|
+
for (const handler of handlers) {
|
|
251
|
+
await handler(...args);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
216
255
|
// src/kernel-base.ts
|
|
217
256
|
var ObjectKernelBase = class {
|
|
218
257
|
constructor(logger) {
|
|
@@ -292,11 +331,11 @@ var ObjectKernelBase = class {
|
|
|
292
331
|
}
|
|
293
332
|
this.hooks.get(name).push(handler);
|
|
294
333
|
},
|
|
334
|
+
// PROPAGATING dispatch, and deliberately WITHOUT the trace line the
|
|
335
|
+
// kernel's own dispatch sites emit — `context.trigger` has never
|
|
336
|
+
// logged one, so no logger is handed over (#5282).
|
|
295
337
|
trigger: async (name, ...args) => {
|
|
296
|
-
|
|
297
|
-
for (const handler of handlers) {
|
|
298
|
-
await handler(...args);
|
|
299
|
-
}
|
|
338
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], void 0, args);
|
|
300
339
|
},
|
|
301
340
|
getServices: () => {
|
|
302
341
|
if (this.services instanceof Map) {
|
|
@@ -415,22 +454,16 @@ var ObjectKernelBase = class {
|
|
|
415
454
|
* (`kernel:ready`, `kernel:bootstrapped`, `kernel:listening`) use
|
|
416
455
|
* {@link triggerHookOrThrow} (#5170, #5257).
|
|
417
456
|
*
|
|
457
|
+
* The loop itself lives in {@link dispatchHookIsolating} — one
|
|
458
|
+
* implementation shared with `ObjectKernel`'s own `kernel:shutdown`
|
|
459
|
+
* dispatch, which cannot inherit this method (`ObjectKernel` does not
|
|
460
|
+
* extend this class) and used to hand-mirror it (#5282).
|
|
461
|
+
*
|
|
418
462
|
* @param name - Hook name
|
|
419
463
|
* @param args - Arguments to pass to handlers
|
|
420
464
|
*/
|
|
421
465
|
async triggerHook(name, ...args) {
|
|
422
|
-
|
|
423
|
-
this.logger.debug(`Triggering hook: ${name}`, {
|
|
424
|
-
hook: name,
|
|
425
|
-
handlerCount: handlers.length
|
|
426
|
-
});
|
|
427
|
-
for (const handler of handlers) {
|
|
428
|
-
try {
|
|
429
|
-
await handler(...args);
|
|
430
|
-
} catch (error) {
|
|
431
|
-
this.logger.error(`Hook handler failed: ${name}`, error);
|
|
432
|
-
}
|
|
433
|
-
}
|
|
466
|
+
await dispatchHookIsolating(name, this.hooks.get(name) || [], this.logger, args);
|
|
434
467
|
}
|
|
435
468
|
/**
|
|
436
469
|
* Trigger a hook with all registered handlers, PROPAGATING the first
|
|
@@ -467,18 +500,15 @@ var ObjectKernelBase = class {
|
|
|
467
500
|
* default — and it is the reason this dispatcher is chosen per hook rather
|
|
468
501
|
* than swapped in wholesale.
|
|
469
502
|
*
|
|
503
|
+
* The loop itself lives in {@link dispatchHookPropagating} — the same
|
|
504
|
+
* function `PluginContext.trigger` runs on both kernels, so "propagating"
|
|
505
|
+
* means one thing repo-wide (#5282).
|
|
506
|
+
*
|
|
470
507
|
* @param name - Hook name
|
|
471
508
|
* @param args - Arguments to pass to handlers
|
|
472
509
|
*/
|
|
473
510
|
async triggerHookOrThrow(name, ...args) {
|
|
474
|
-
|
|
475
|
-
this.logger.debug(`Triggering hook: ${name}`, {
|
|
476
|
-
hook: name,
|
|
477
|
-
handlerCount: handlers.length
|
|
478
|
-
});
|
|
479
|
-
for (const handler of handlers) {
|
|
480
|
-
await handler(...args);
|
|
481
|
-
}
|
|
511
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], this.logger, args);
|
|
482
512
|
}
|
|
483
513
|
/**
|
|
484
514
|
* Get current kernel state
|
|
@@ -614,7 +644,15 @@ var ObjectLogger = class _ObjectLogger {
|
|
|
614
644
|
redact: config.redact ?? ["password", "token", "secret", "key"],
|
|
615
645
|
sourceLocation: config.sourceLocation ?? false,
|
|
616
646
|
file: config.file,
|
|
617
|
-
|
|
647
|
+
// Per-key, because `LoggerConfig` is the AUTHOR state (ADR-0122): the
|
|
648
|
+
// schema defaults `maxSize`/`maxFiles` *inside* `rotation`, so a caller
|
|
649
|
+
// may legitimately write `{ rotation: { maxSize: '5m' } }` and this
|
|
650
|
+
// constructor — which does not parse — has to fill the other half the
|
|
651
|
+
// same way `LoggerConfigSchema.parse` would.
|
|
652
|
+
rotation: {
|
|
653
|
+
maxSize: config.rotation?.maxSize ?? "10m",
|
|
654
|
+
maxFiles: config.rotation?.maxFiles ?? 5
|
|
655
|
+
}
|
|
618
656
|
};
|
|
619
657
|
this.bindings = bindings;
|
|
620
658
|
this.redactPatterns = this.config.redact.map(tokenizeFieldName).filter((words) => words.length > 0);
|
|
@@ -808,7 +846,7 @@ function createLogger(config) {
|
|
|
808
846
|
}
|
|
809
847
|
|
|
810
848
|
// src/kernel.ts
|
|
811
|
-
var
|
|
849
|
+
var import_system3 = require("@objectstack/spec/system");
|
|
812
850
|
|
|
813
851
|
// src/security/plugin-config-validator.ts
|
|
814
852
|
var import_zod = require("zod");
|
|
@@ -1476,6 +1514,7 @@ function createMemoryJob() {
|
|
|
1476
1514
|
}
|
|
1477
1515
|
|
|
1478
1516
|
// src/fallbacks/memory-i18n.ts
|
|
1517
|
+
var import_system = require("@objectstack/spec/system");
|
|
1479
1518
|
function deepMerge(target, source) {
|
|
1480
1519
|
const result = { ...target };
|
|
1481
1520
|
for (const key of Object.keys(source)) {
|
|
@@ -1509,6 +1548,7 @@ function createMemoryI18n() {
|
|
|
1509
1548
|
const translations = /* @__PURE__ */ new Map();
|
|
1510
1549
|
const authored = /* @__PURE__ */ new Map();
|
|
1511
1550
|
let defaultLocale = "en";
|
|
1551
|
+
let supportedLocales;
|
|
1512
1552
|
function resolveKey(data, key) {
|
|
1513
1553
|
const parts = key.split(".");
|
|
1514
1554
|
let current = data;
|
|
@@ -1574,9 +1614,29 @@ function createMemoryI18n() {
|
|
|
1574
1614
|
authored.set(locale, { ...data });
|
|
1575
1615
|
}
|
|
1576
1616
|
},
|
|
1617
|
+
/**
|
|
1618
|
+
* Report the locales this stack offers.
|
|
1619
|
+
*
|
|
1620
|
+
* [#7679] When the app declared `i18n.supportedLocales`, that declaration
|
|
1621
|
+
* IS the answer — in declared order, and including a declared locale no
|
|
1622
|
+
* bundle was ever loaded for (declared-but-unserved). Reporting the
|
|
1623
|
+
* declaration rather than an intersection is what gives a client the
|
|
1624
|
+
* signal that the locale it is being offered has nothing behind it yet;
|
|
1625
|
+
* quietly dropping it would leave the gap invisible on both sides. It is
|
|
1626
|
+
* also the only answer that does not depend on how much had loaded by the
|
|
1627
|
+
* time this was called.
|
|
1628
|
+
*
|
|
1629
|
+
* With nothing declared, the loaded set — the behaviour every app that
|
|
1630
|
+
* never opted in already has.
|
|
1631
|
+
*/
|
|
1577
1632
|
getLocales() {
|
|
1633
|
+
if (supportedLocales) return [...supportedLocales];
|
|
1578
1634
|
return [.../* @__PURE__ */ new Set([...translations.keys(), ...authored.keys()])];
|
|
1579
1635
|
},
|
|
1636
|
+
/** @see II18nService.setSupportedLocales — [#7679] */
|
|
1637
|
+
setSupportedLocales(locales) {
|
|
1638
|
+
supportedLocales = (0, import_system.normalizeSupportedLocales)(locales);
|
|
1639
|
+
},
|
|
1580
1640
|
getDefaultLocale() {
|
|
1581
1641
|
return defaultLocale;
|
|
1582
1642
|
},
|
|
@@ -1586,14 +1646,42 @@ function createMemoryI18n() {
|
|
|
1586
1646
|
};
|
|
1587
1647
|
}
|
|
1588
1648
|
|
|
1649
|
+
// src/metadata-service-contract.ts
|
|
1650
|
+
var import_shared = require("@objectstack/spec/shared");
|
|
1651
|
+
var REGISTER_REFUSAL_CODE = "VALIDATION_ERROR";
|
|
1652
|
+
function canonicalMetadataServiceType(type) {
|
|
1653
|
+
return (0, import_shared.pluralToSingular)(type);
|
|
1654
|
+
}
|
|
1655
|
+
function registerRefusal(message) {
|
|
1656
|
+
const err = new Error(message);
|
|
1657
|
+
err.code = REGISTER_REFUSAL_CODE;
|
|
1658
|
+
err.status = 400;
|
|
1659
|
+
return err;
|
|
1660
|
+
}
|
|
1661
|
+
function assertMetadataRegisterContract(type, name, data) {
|
|
1662
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) {
|
|
1663
|
+
const shape = data === null ? "null" : Array.isArray(data) ? "an array" : `a ${typeof data}`;
|
|
1664
|
+
throw registerRefusal(
|
|
1665
|
+
`IMetadataService.register('${type}', '${name}'): data is ${shape}, not a metadata document. register() stores plain-object documents only \u2014 accepting a value the service cannot key was measured as accept-then-drop on document-keyed stores (#7378 row 3: refuse loudly, never coerce into storability). Wrap the value in a document object whose shape the '${type}' type's schema accepts, or store it under a type that declares one.`
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
const documentName = data.name;
|
|
1669
|
+
if (documentName !== void 0 && documentName !== name) {
|
|
1670
|
+
throw registerRefusal(
|
|
1671
|
+
`IMetadataService.register('${type}', '${name}'): data.name is '${String(documentName)}', which disagrees with the name argument '${name}'. A disagreement is almost always an authoring bug, and resolving it silently in either direction can file the item under a key the caller never wrote (#7378 row 1: refuse loudly, locate the mismatch). Register under one name: pass the intended key as the argument and make data.name match it, or omit data.name.`
|
|
1672
|
+
);
|
|
1673
|
+
}
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1589
1676
|
// src/fallbacks/memory-metadata.ts
|
|
1590
1677
|
function createMemoryMetadata() {
|
|
1591
1678
|
const store = /* @__PURE__ */ new Map();
|
|
1592
1679
|
function getTypeMap(type) {
|
|
1593
|
-
|
|
1680
|
+
const canonical = canonicalMetadataServiceType(type);
|
|
1681
|
+
let map = store.get(canonical);
|
|
1594
1682
|
if (!map) {
|
|
1595
1683
|
map = /* @__PURE__ */ new Map();
|
|
1596
|
-
store.set(
|
|
1684
|
+
store.set(canonical, map);
|
|
1597
1685
|
}
|
|
1598
1686
|
return map;
|
|
1599
1687
|
}
|
|
@@ -1608,6 +1696,7 @@ function createMemoryMetadata() {
|
|
|
1608
1696
|
},
|
|
1609
1697
|
_serviceName: "metadata",
|
|
1610
1698
|
async register(type, name, data) {
|
|
1699
|
+
assertMetadataRegisterContract(type, name, data);
|
|
1611
1700
|
getTypeMap(type).set(name, data);
|
|
1612
1701
|
},
|
|
1613
1702
|
// Mirror MetadataManager.registerInMemory (synchronous, no persistence).
|
|
@@ -1619,7 +1708,11 @@ function createMemoryMetadata() {
|
|
|
1619
1708
|
// so `defineStack({ datasources })` entries silently never reached the
|
|
1620
1709
|
// registry and were absent from GET /api/v1/datasources and
|
|
1621
1710
|
// GET /api/v1/meta/datasource (ADR-0015 §18). This store is already
|
|
1622
|
-
// in-memory only, so registerInMemory and register share
|
|
1711
|
+
// in-memory only, so registerInMemory and register share a store — but
|
|
1712
|
+
// NOT the [#7378] refusals: the ruling names `register`, and this member
|
|
1713
|
+
// is a boot-time seeding primitive for source-control-owned artefacts
|
|
1714
|
+
// (see assertMetadataRegisterContract's header for the boundary). It does
|
|
1715
|
+
// share the row-2 canonical type fold, via getTypeMap.
|
|
1623
1716
|
registerInMemory(type, name, data) {
|
|
1624
1717
|
getTypeMap(type).set(name, data);
|
|
1625
1718
|
},
|
|
@@ -1648,7 +1741,7 @@ function createMemoryMetadata() {
|
|
|
1648
1741
|
}
|
|
1649
1742
|
|
|
1650
1743
|
// src/fallbacks/authored-translation-sync.ts
|
|
1651
|
-
var
|
|
1744
|
+
var import_system2 = require("@objectstack/spec/system");
|
|
1652
1745
|
var OWNER_PROP = "__authoredTranslationSyncOwner";
|
|
1653
1746
|
var LOCALE_LIKE = /^[a-z]{2,3}([_-]([A-Za-z]{4}|[A-Za-z]{2}|[0-9]{3}))?$/;
|
|
1654
1747
|
async function readAuthoredTranslationLayer(engine, logger) {
|
|
@@ -1678,7 +1771,7 @@ async function readAuthoredTranslationLayer(engine, logger) {
|
|
|
1678
1771
|
continue;
|
|
1679
1772
|
}
|
|
1680
1773
|
if (!data || typeof data !== "object") continue;
|
|
1681
|
-
const legacyKeys =
|
|
1774
|
+
const legacyKeys = import_system2.LEGACY_OBJECT_FIRST_KEYS.filter((key) => data[key] !== void 0);
|
|
1682
1775
|
if (legacyKeys.length > 0) {
|
|
1683
1776
|
logger?.warn?.(
|
|
1684
1777
|
`[i18n] authored translation '${row?.name}' uses the retired object-first shape (${legacyKeys.join(", ")}) \u2014 nothing resolves from it; re-author it under 'objects.<object_name>' with a top-level 'locale' \u2014 skipped`
|
|
@@ -1843,11 +1936,12 @@ var ObjectKernel = class {
|
|
|
1843
1936
|
}
|
|
1844
1937
|
this.hooks.get(name).push(handler);
|
|
1845
1938
|
},
|
|
1939
|
+
// PROPAGATING dispatch — the same shared loop `LiteKernel`'s
|
|
1940
|
+
// context.trigger runs, and deliberately WITHOUT a trace line:
|
|
1941
|
+
// `context.trigger` has never emitted one on either kernel, so no
|
|
1942
|
+
// logger is handed over (#5282).
|
|
1846
1943
|
trigger: async (name, ...args) => {
|
|
1847
|
-
|
|
1848
|
-
for (const handler of handlers) {
|
|
1849
|
-
await handler(...args);
|
|
1850
|
-
}
|
|
1944
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], void 0, args);
|
|
1851
1945
|
},
|
|
1852
1946
|
getServices: () => {
|
|
1853
1947
|
return new Map(this.services);
|
|
@@ -1915,7 +2009,7 @@ var ObjectKernel = class {
|
|
|
1915
2009
|
*/
|
|
1916
2010
|
preInjectCoreFallbacks() {
|
|
1917
2011
|
if (this.config.skipSystemValidation) return;
|
|
1918
|
-
for (const [serviceName, criticality] of Object.entries(
|
|
2012
|
+
for (const [serviceName, criticality] of Object.entries(import_system3.ServiceRequirementDef)) {
|
|
1919
2013
|
if (criticality !== "core") continue;
|
|
1920
2014
|
const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);
|
|
1921
2015
|
if (!hasService) {
|
|
@@ -1939,7 +2033,7 @@ var ObjectKernel = class {
|
|
|
1939
2033
|
this.logger.debug("Validating system service requirements...");
|
|
1940
2034
|
const missingServices = [];
|
|
1941
2035
|
const missingCoreServices = [];
|
|
1942
|
-
for (const [serviceName, criticality] of Object.entries(
|
|
2036
|
+
for (const [serviceName, criticality] of Object.entries(import_system3.ServiceRequirementDef)) {
|
|
1943
2037
|
const hasService = this.services.has(serviceName) || this.pluginLoader.hasService(serviceName);
|
|
1944
2038
|
if (!hasService) {
|
|
1945
2039
|
if (criticality === "required") {
|
|
@@ -2271,27 +2365,21 @@ var ObjectKernel = class {
|
|
|
2271
2365
|
* one bad handler must not amplify into leaked resources and unflushed
|
|
2272
2366
|
* writes. Same reasoning, same wording, same `Hook handler failed:
|
|
2273
2367
|
* kernel:shutdown` log line as `LiteKernel`'s dispatch site, which reaches
|
|
2274
|
-
* the
|
|
2368
|
+
* the isolating dispatcher through `ObjectKernelBase.triggerHook` (#5257).
|
|
2275
2369
|
*
|
|
2276
|
-
*
|
|
2370
|
+
* Until #5282 "same wording" was literally that — the loop was typed out a
|
|
2371
|
+
* second time here, because `ObjectKernel` does not extend
|
|
2277
2372
|
* `ObjectKernelBase` (only `LiteKernel` does) and owns its own `hooks` map,
|
|
2278
|
-
* so the
|
|
2279
|
-
*
|
|
2280
|
-
*
|
|
2373
|
+
* so the base's `protected triggerHook` is out of reach. The loop now lives
|
|
2374
|
+
* in {@link dispatchHookIsolating}, which BOTH sides call: the storage is
|
|
2375
|
+
* still two maps (deliberately — unifying it was out of #5282's scope), but
|
|
2376
|
+
* "isolating" is one implementation, so it can no longer drift on one
|
|
2377
|
+
* kernel while the other keeps the old shape. That drift is exactly the bug
|
|
2378
|
+
* #5170 / #5257 / #5274 each closed one hook at a time, and the paired-pin
|
|
2379
|
+
* gate (`scripts/check-kernel-hook-pairs.mjs`) covers the residue.
|
|
2281
2380
|
*/
|
|
2282
2381
|
async triggerShutdownHookIsolating() {
|
|
2283
|
-
|
|
2284
|
-
this.logger.debug("Triggering hook: kernel:shutdown", {
|
|
2285
|
-
hook: "kernel:shutdown",
|
|
2286
|
-
handlerCount: handlers.length
|
|
2287
|
-
});
|
|
2288
|
-
for (const handler of handlers) {
|
|
2289
|
-
try {
|
|
2290
|
-
await handler();
|
|
2291
|
-
} catch (error) {
|
|
2292
|
-
this.logger.error("Hook handler failed: kernel:shutdown", error);
|
|
2293
|
-
}
|
|
2294
|
-
}
|
|
2382
|
+
await dispatchHookIsolating("kernel:shutdown", this.hooks.get("kernel:shutdown") || [], this.logger);
|
|
2295
2383
|
}
|
|
2296
2384
|
async performShutdown() {
|
|
2297
2385
|
await this.triggerShutdownHookIsolating();
|
|
@@ -2459,6 +2547,20 @@ __export(qa_exports, {
|
|
|
2459
2547
|
});
|
|
2460
2548
|
|
|
2461
2549
|
// src/qa/runner.ts
|
|
2550
|
+
function describeActualType(value) {
|
|
2551
|
+
if (value === null) return "null";
|
|
2552
|
+
if (Array.isArray(value)) return "array";
|
|
2553
|
+
return typeof value;
|
|
2554
|
+
}
|
|
2555
|
+
function containsInapplicableHint(actual) {
|
|
2556
|
+
if (actual === void 0) {
|
|
2557
|
+
return "The path resolved to nothing \u2014 the field is absent from the result, or the path is misspelled. Use 'is_null' if asserting absence is what you meant.";
|
|
2558
|
+
}
|
|
2559
|
+
if (actual === null) {
|
|
2560
|
+
return "The path resolved to null. Use 'is_null' if asserting absence is what you meant.";
|
|
2561
|
+
}
|
|
2562
|
+
return "'contains' tests array membership and string substrings only. Use 'equals' to compare a scalar, or point the field at the array or string you meant to look inside.";
|
|
2563
|
+
}
|
|
2462
2564
|
var TestRunner = class {
|
|
2463
2565
|
constructor(adapter) {
|
|
2464
2566
|
this.adapter = adapter;
|
|
@@ -2586,6 +2688,10 @@ var TestRunner = class {
|
|
|
2586
2688
|
if (!actual.includes(expected)) throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);
|
|
2587
2689
|
} else if (typeof actual === "string") {
|
|
2588
2690
|
if (!actual.includes(String(expected))) throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);
|
|
2691
|
+
} else {
|
|
2692
|
+
throw new Error(
|
|
2693
|
+
`Assertion failed: ${assertion.field} cannot be evaluated by 'contains' \u2014 expected an array or a string at that path, got ${describeActualType(actual)}. ` + containsInapplicableHint(actual)
|
|
2694
|
+
);
|
|
2589
2695
|
}
|
|
2590
2696
|
break;
|
|
2591
2697
|
case "not_null":
|
|
@@ -2602,11 +2708,29 @@ var TestRunner = class {
|
|
|
2602
2708
|
};
|
|
2603
2709
|
|
|
2604
2710
|
// src/qa/http-adapter.ts
|
|
2711
|
+
var import_api = require("@objectstack/spec/api");
|
|
2712
|
+
var dataPathCache;
|
|
2713
|
+
function defaultDataPath() {
|
|
2714
|
+
if (dataPathCache === void 0) {
|
|
2715
|
+
const api = import_api.RestApiConfigSchema.parse({});
|
|
2716
|
+
const crud = import_api.CrudEndpointsConfigSchema.parse({});
|
|
2717
|
+
dataPathCache = `${api.apiPath ?? `${api.basePath}/${api.version}`}${crud.dataPrefix}`;
|
|
2718
|
+
}
|
|
2719
|
+
return dataPathCache;
|
|
2720
|
+
}
|
|
2605
2721
|
var HttpTestAdapter = class {
|
|
2606
2722
|
constructor(baseUrl, authToken) {
|
|
2607
2723
|
this.baseUrl = baseUrl;
|
|
2608
2724
|
this.authToken = authToken;
|
|
2609
2725
|
}
|
|
2726
|
+
/** `{baseUrl}{apiBasePath}{dataPrefix}/{object}` — the collection URL. */
|
|
2727
|
+
collectionUrl(objectName) {
|
|
2728
|
+
return `${this.baseUrl}${defaultDataPath()}/${encodeURIComponent(objectName)}`;
|
|
2729
|
+
}
|
|
2730
|
+
/** `{collection}/{id}` — the single-record URL. */
|
|
2731
|
+
recordUrl(objectName, id) {
|
|
2732
|
+
return `${this.collectionUrl(objectName)}/${encodeURIComponent(String(id))}`;
|
|
2733
|
+
}
|
|
2610
2734
|
async execute(action, _context) {
|
|
2611
2735
|
const headers = {
|
|
2612
2736
|
"Content-Type": "application/json"
|
|
@@ -2638,7 +2762,7 @@ var HttpTestAdapter = class {
|
|
|
2638
2762
|
}
|
|
2639
2763
|
}
|
|
2640
2764
|
async createRecord(objectName, data, headers) {
|
|
2641
|
-
const response = await fetch(
|
|
2765
|
+
const response = await fetch(this.collectionUrl(objectName), {
|
|
2642
2766
|
method: "POST",
|
|
2643
2767
|
headers,
|
|
2644
2768
|
body: JSON.stringify(data)
|
|
@@ -2646,19 +2770,19 @@ var HttpTestAdapter = class {
|
|
|
2646
2770
|
return this.handleResponse(response);
|
|
2647
2771
|
}
|
|
2648
2772
|
async updateRecord(objectName, data, headers) {
|
|
2649
|
-
const id = data
|
|
2773
|
+
const { id, ...fields } = data;
|
|
2650
2774
|
if (!id) throw new Error("Update record requires id in payload");
|
|
2651
|
-
const response = await fetch(
|
|
2652
|
-
method: "
|
|
2775
|
+
const response = await fetch(this.recordUrl(objectName, id), {
|
|
2776
|
+
method: "PATCH",
|
|
2653
2777
|
headers,
|
|
2654
|
-
body: JSON.stringify(
|
|
2778
|
+
body: JSON.stringify(fields)
|
|
2655
2779
|
});
|
|
2656
2780
|
return this.handleResponse(response);
|
|
2657
2781
|
}
|
|
2658
2782
|
async deleteRecord(objectName, data, headers) {
|
|
2659
2783
|
const id = data.id;
|
|
2660
2784
|
if (!id) throw new Error("Delete record requires id in payload");
|
|
2661
|
-
const response = await fetch(
|
|
2785
|
+
const response = await fetch(this.recordUrl(objectName, id), {
|
|
2662
2786
|
method: "DELETE",
|
|
2663
2787
|
headers
|
|
2664
2788
|
});
|
|
@@ -2667,14 +2791,14 @@ var HttpTestAdapter = class {
|
|
|
2667
2791
|
async readRecord(objectName, data, headers) {
|
|
2668
2792
|
const id = data.id;
|
|
2669
2793
|
if (!id) throw new Error("Read record requires id in payload");
|
|
2670
|
-
const response = await fetch(
|
|
2794
|
+
const response = await fetch(this.recordUrl(objectName, id), {
|
|
2671
2795
|
method: "GET",
|
|
2672
2796
|
headers
|
|
2673
2797
|
});
|
|
2674
2798
|
return this.handleResponse(response);
|
|
2675
2799
|
}
|
|
2676
2800
|
async queryRecords(objectName, data, headers) {
|
|
2677
|
-
const response = await fetch(`${this.
|
|
2801
|
+
const response = await fetch(`${this.collectionUrl(objectName)}/query`, {
|
|
2678
2802
|
method: "POST",
|
|
2679
2803
|
headers,
|
|
2680
2804
|
body: JSON.stringify(data)
|
|
@@ -4466,7 +4590,116 @@ async function resolveLocalizationContext(input) {
|
|
|
4466
4590
|
};
|
|
4467
4591
|
}
|
|
4468
4592
|
|
|
4593
|
+
// src/security/assemble-execution-context.ts
|
|
4594
|
+
var ENTRY_EXECUTION_CONTEXT_FIELDS = [
|
|
4595
|
+
"positions",
|
|
4596
|
+
"permissions",
|
|
4597
|
+
"systemPermissions",
|
|
4598
|
+
"isSystem",
|
|
4599
|
+
"principalKind",
|
|
4600
|
+
"onBehalfOf",
|
|
4601
|
+
"audience",
|
|
4602
|
+
"userId",
|
|
4603
|
+
"tenantId",
|
|
4604
|
+
"email",
|
|
4605
|
+
"accessToken",
|
|
4606
|
+
"tabPermissions",
|
|
4607
|
+
"posture",
|
|
4608
|
+
"authGate",
|
|
4609
|
+
"org_user_ids",
|
|
4610
|
+
"accessible_org_ids",
|
|
4611
|
+
"oauthScopes",
|
|
4612
|
+
"timezone",
|
|
4613
|
+
"locale",
|
|
4614
|
+
"currency"
|
|
4615
|
+
];
|
|
4616
|
+
function emit(fields) {
|
|
4617
|
+
const ctx = {};
|
|
4618
|
+
for (const key of ENTRY_EXECUTION_CONTEXT_FIELDS) {
|
|
4619
|
+
const value = fields[key];
|
|
4620
|
+
if (value !== void 0) ctx[key] = value;
|
|
4621
|
+
}
|
|
4622
|
+
return ctx;
|
|
4623
|
+
}
|
|
4624
|
+
function entryFields(input, anonymous) {
|
|
4625
|
+
const { authz, oauth, localization, requestLocale, accessToken, authGate } = input;
|
|
4626
|
+
const agent = !anonymous && oauth?.clientId ? oauth : void 0;
|
|
4627
|
+
return {
|
|
4628
|
+
// [ADR-0090 D9/D10] Principal taxonomy at the HTTP entry: a session-backed
|
|
4629
|
+
// request is a human principal; a sessionless one is a guest, holding the
|
|
4630
|
+
// built-in `guest` position implicitly and exclusively. Internal engine
|
|
4631
|
+
// calls that construct bare contexts never pass through here, so the
|
|
4632
|
+
// security plugin's empty-context skip path keeps its meaning.
|
|
4633
|
+
positions: agent ? [] : anonymous ? ["guest"] : authz.positions,
|
|
4634
|
+
permissions: agent ? agent.scopePermissions : authz.permissions,
|
|
4635
|
+
// [ADR-0090 D10] System capabilities on the agent principal gate business
|
|
4636
|
+
// ACTION invocation (`actionPermissionError` reads `ctx.systemPermissions`)
|
|
4637
|
+
// — a door SEPARATE from the object CRUD/FLS/RLS intersection, which is
|
|
4638
|
+
// driven by the resolved ceiling SETS (they carry no caps, so cap-gated
|
|
4639
|
+
// OBJECT access stays denied to the agent regardless of this line). The
|
|
4640
|
+
// `actions:execute` scope IS the user's consent to let this agent invoke
|
|
4641
|
+
// actions on their behalf; without it the agent holds none.
|
|
4642
|
+
systemPermissions: agent ? agent.delegatesActions ? authz.systemPermissions ?? [] : [] : authz.systemPermissions,
|
|
4643
|
+
isSystem: false,
|
|
4644
|
+
principalKind: agent ? "agent" : anonymous ? "guest" : "human",
|
|
4645
|
+
onBehalfOf: agent ? { userId: authz.userId, principalKind: "human" } : void 0,
|
|
4646
|
+
// [ADR-0090 D10/D11 — P1 shape] No transport resolves an external
|
|
4647
|
+
// (portal/partner) audience yet; `undefined` reads as 'internal'. Named
|
|
4648
|
+
// here rather than excluded so the gap is visible in the closed set instead
|
|
4649
|
+
// of being invisible outside it — when an external principal type lands,
|
|
4650
|
+
// this is the line that must change, on every face at once.
|
|
4651
|
+
audience: void 0,
|
|
4652
|
+
userId: authz.userId,
|
|
4653
|
+
tenantId: authz.tenantId,
|
|
4654
|
+
email: authz.email,
|
|
4655
|
+
accessToken,
|
|
4656
|
+
tabPermissions: authz.tabPermissions,
|
|
4657
|
+
// [ADR-0095 D2 / #2947] The derived posture rung, carried so every
|
|
4658
|
+
// transport presents enforcement the SAME value. Present only for an
|
|
4659
|
+
// authenticated principal (guest → absent).
|
|
4660
|
+
posture: authz.posture,
|
|
4661
|
+
// [ADR-0069 / #7280] The AUTHENTICATION-policy gate, carried for the seam
|
|
4662
|
+
// that reads it off the envelope (REST's `enforceAuth`). Anonymous → never:
|
|
4663
|
+
// a guest has no authenticated session for a policy gate to attach to, so
|
|
4664
|
+
// "gated guest" is not a state this entry can emit even if a face passed
|
|
4665
|
+
// one.
|
|
4666
|
+
authGate: anonymous ? void 0 : authGate,
|
|
4667
|
+
/** Fellow-org user IDs for RLS scoping of identity tables. */
|
|
4668
|
+
org_user_ids: authz.org_user_ids,
|
|
4669
|
+
// [ADR-0105 D2] The caller's org access set — the `group` posture's Layer 0
|
|
4670
|
+
// wall reads it directly, so every transport must carry it (#6206).
|
|
4671
|
+
accessible_org_ids: authz.accessible_org_ids,
|
|
4672
|
+
// OAuth provenance: surface the token's granted scopes so the MCP
|
|
4673
|
+
// dispatcher can narrow the exposed tool families (undefined for every
|
|
4674
|
+
// other provenance = not scope-limited).
|
|
4675
|
+
oauthScopes: oauth && authz.userId === oauth.userId ? oauth.scopes : void 0,
|
|
4676
|
+
// Anonymous → no localization (no scope to resolve against); the engine
|
|
4677
|
+
// default stands. [#3957] The request's OWN language preference wins over
|
|
4678
|
+
// the workspace default, so a rejection message is not rendered in English
|
|
4679
|
+
// beside the Chinese label of the very field it names.
|
|
4680
|
+
timezone: anonymous ? void 0 : localization?.timezone,
|
|
4681
|
+
locale: anonymous ? void 0 : requestLocale ?? localization?.locale,
|
|
4682
|
+
currency: anonymous ? void 0 : localization?.currency
|
|
4683
|
+
};
|
|
4684
|
+
}
|
|
4685
|
+
function assembleExecutionContext(input) {
|
|
4686
|
+
if (!input.authz.userId) return void 0;
|
|
4687
|
+
return emit(entryFields(input, false));
|
|
4688
|
+
}
|
|
4689
|
+
function assembleExecutionContextOrGuest(input) {
|
|
4690
|
+
return emit(entryFields(input, !input.authz.userId));
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4469
4693
|
// src/security/auth-gate.ts
|
|
4694
|
+
var DEFAULT_AUTH_GATE_MESSAGE = "Access is blocked by an authentication policy.";
|
|
4695
|
+
function normalizeAuthGate(sessionUser) {
|
|
4696
|
+
const gate = sessionUser?.authGate;
|
|
4697
|
+
if (!gate || typeof gate.code !== "string") return null;
|
|
4698
|
+
return {
|
|
4699
|
+
code: gate.code,
|
|
4700
|
+
message: typeof gate.message === "string" && gate.message ? gate.message : DEFAULT_AUTH_GATE_MESSAGE
|
|
4701
|
+
};
|
|
4702
|
+
}
|
|
4470
4703
|
var ALLOW_PREFIXES = ["/api/v1/auth/", "/api/auth/", "/auth/"];
|
|
4471
4704
|
var ALLOW_SUFFIXES = ["/health", "/ready", "/discovery", "/me/apps", "/me/localization"];
|
|
4472
4705
|
function isAuthGateAllowlisted(rawPath) {
|
|
@@ -4485,13 +4718,10 @@ function isAuthGateAllowlisted(rawPath) {
|
|
|
4485
4718
|
return false;
|
|
4486
4719
|
}
|
|
4487
4720
|
function evaluateAuthGate(sessionUser, path) {
|
|
4488
|
-
const gate = sessionUser
|
|
4489
|
-
if (!gate
|
|
4721
|
+
const gate = normalizeAuthGate(sessionUser);
|
|
4722
|
+
if (!gate) return null;
|
|
4490
4723
|
if (isAuthGateAllowlisted(path)) return null;
|
|
4491
|
-
return
|
|
4492
|
-
code: gate.code,
|
|
4493
|
-
message: typeof gate.message === "string" && gate.message ? gate.message : "Access is blocked by an authentication policy."
|
|
4494
|
-
};
|
|
4724
|
+
return gate;
|
|
4495
4725
|
}
|
|
4496
4726
|
|
|
4497
4727
|
// src/security/anonymous-deny.ts
|
|
@@ -4513,6 +4743,29 @@ function shouldDenyAnonymous(input) {
|
|
|
4513
4743
|
return true;
|
|
4514
4744
|
}
|
|
4515
4745
|
|
|
4746
|
+
// src/security/audience-binding-suggestion-status.ts
|
|
4747
|
+
var AUDIENCE_BINDING_SUGGESTION_STATUSES = {
|
|
4748
|
+
pending: true,
|
|
4749
|
+
confirmed: true,
|
|
4750
|
+
dismissed: true
|
|
4751
|
+
};
|
|
4752
|
+
var AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES = Object.keys(
|
|
4753
|
+
AUDIENCE_BINDING_SUGGESTION_STATUSES
|
|
4754
|
+
);
|
|
4755
|
+
var isAudienceBindingSuggestionStatus = (value) => Object.prototype.hasOwnProperty.call(AUDIENCE_BINDING_SUGGESTION_STATUSES, value);
|
|
4756
|
+
var unknownAudienceBindingSuggestionStatusMessage = (value) => `Unknown status filter '${value}' \u2014 expected one of: ${AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES.join(", ")}`;
|
|
4757
|
+
|
|
4758
|
+
// src/security/operation-private-keys.ts
|
|
4759
|
+
var OPERATION_PRIVATE_KEY_PREFIX = "__";
|
|
4760
|
+
function withoutOperationPrivateKeys(exec) {
|
|
4761
|
+
const out = {};
|
|
4762
|
+
for (const [key, value] of Object.entries(exec)) {
|
|
4763
|
+
if (key.startsWith(OPERATION_PRIVATE_KEY_PREFIX)) continue;
|
|
4764
|
+
out[key] = value;
|
|
4765
|
+
}
|
|
4766
|
+
return out;
|
|
4767
|
+
}
|
|
4768
|
+
|
|
4516
4769
|
// src/utils/datetime.ts
|
|
4517
4770
|
var import_data = require("@objectstack/spec/data");
|
|
4518
4771
|
function calendarPartsInTz(d, tz) {
|
|
@@ -4755,9 +5008,30 @@ async function bulkWrite(rows, opts) {
|
|
|
4755
5008
|
return results;
|
|
4756
5009
|
}
|
|
4757
5010
|
|
|
5011
|
+
// src/utils/internal-write-response.ts
|
|
5012
|
+
function collectInternalWriteResponseFields(schema) {
|
|
5013
|
+
const fields = schema?.fields;
|
|
5014
|
+
if (!fields || typeof fields !== "object") return [];
|
|
5015
|
+
const out = [];
|
|
5016
|
+
for (const [name, def] of Object.entries(fields)) {
|
|
5017
|
+
if (def && def.internal === true) out.push(name);
|
|
5018
|
+
}
|
|
5019
|
+
return out;
|
|
5020
|
+
}
|
|
5021
|
+
function omitInternalFieldsFromWriteResponse(schema, records) {
|
|
5022
|
+
if (!records) return;
|
|
5023
|
+
const internalFields = collectInternalWriteResponseFields(schema);
|
|
5024
|
+
if (internalFields.length === 0) return;
|
|
5025
|
+
const list = Array.isArray(records) ? records : [records];
|
|
5026
|
+
for (const row of list) {
|
|
5027
|
+
if (!row || typeof row !== "object") continue;
|
|
5028
|
+
for (const field of internalFields) delete row[field];
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
5031
|
+
|
|
4758
5032
|
// src/utils/migration-journal.ts
|
|
4759
5033
|
var import_node_crypto3 = require("crypto");
|
|
4760
|
-
var
|
|
5034
|
+
var import_system4 = require("@objectstack/spec/system");
|
|
4761
5035
|
var SYSTEM_CTX = { isSystem: true };
|
|
4762
5036
|
var DEFAULT_CHUNK_SIZE = 200;
|
|
4763
5037
|
function engineCanRollBack(engine) {
|
|
@@ -4815,14 +5089,14 @@ function hashMigrationPlan(plan, chunks) {
|
|
|
4815
5089
|
}
|
|
4816
5090
|
async function appendEvent(engine, event, execContext) {
|
|
4817
5091
|
await engine.insert(
|
|
4818
|
-
|
|
5092
|
+
import_system4.MIGRATION_JOURNAL_OBJECT,
|
|
4819
5093
|
{ ...event, created_at: event.created_at ?? (/* @__PURE__ */ new Date()).toISOString() },
|
|
4820
5094
|
{ context: execContext ?? { ...SYSTEM_CTX } }
|
|
4821
5095
|
);
|
|
4822
5096
|
}
|
|
4823
5097
|
async function readRunJournal(engine, runId) {
|
|
4824
5098
|
const rows = await engine.find(
|
|
4825
|
-
|
|
5099
|
+
import_system4.MIGRATION_JOURNAL_OBJECT,
|
|
4826
5100
|
{ where: { run_id: runId } },
|
|
4827
5101
|
{ context: { ...SYSTEM_CTX } }
|
|
4828
5102
|
);
|
|
@@ -4837,7 +5111,7 @@ function chunkSetOf(events, kind) {
|
|
|
4837
5111
|
}
|
|
4838
5112
|
async function findInterruptedRuns(engine) {
|
|
4839
5113
|
const started = await engine.find(
|
|
4840
|
-
|
|
5114
|
+
import_system4.MIGRATION_JOURNAL_OBJECT,
|
|
4841
5115
|
{ where: { kind: "run_started" } },
|
|
4842
5116
|
{ context: { ...SYSTEM_CTX } }
|
|
4843
5117
|
);
|
|
@@ -5345,6 +5619,15 @@ function filterTokenContextFrom(execCtx, now) {
|
|
|
5345
5619
|
};
|
|
5346
5620
|
}
|
|
5347
5621
|
|
|
5622
|
+
// src/utils/record-not-found.ts
|
|
5623
|
+
function recordNotFoundError(object, id) {
|
|
5624
|
+
const err = new Error(`Record ${id} not found in ${object}`);
|
|
5625
|
+
err.code = "RECORD_NOT_FOUND";
|
|
5626
|
+
err.status = 404;
|
|
5627
|
+
err.object = object;
|
|
5628
|
+
return err;
|
|
5629
|
+
}
|
|
5630
|
+
|
|
5348
5631
|
// src/health-monitor.ts
|
|
5349
5632
|
var PluginHealthMonitor = class {
|
|
5350
5633
|
constructor(logger) {
|
|
@@ -6328,13 +6611,17 @@ var NamespaceResolver = class {
|
|
|
6328
6611
|
ANONYMOUS_DENY_MESSAGE,
|
|
6329
6612
|
ANONYMOUS_DENY_STATUS,
|
|
6330
6613
|
API_KEY_PREFIX,
|
|
6614
|
+
AUDIENCE_BINDING_SUGGESTION_STATUSES,
|
|
6615
|
+
AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES,
|
|
6331
6616
|
CORE_FALLBACK_FACTORIES,
|
|
6332
6617
|
DependencyResolver,
|
|
6618
|
+
ENTRY_EXECUTION_CONTEXT_FIELDS,
|
|
6333
6619
|
HotReloadManager,
|
|
6334
6620
|
LiteKernel,
|
|
6335
6621
|
MigrationJournalRefusal,
|
|
6336
6622
|
MigrationPlanRegistry,
|
|
6337
6623
|
NamespaceResolver,
|
|
6624
|
+
OPERATION_PRIVATE_KEY_PREFIX,
|
|
6338
6625
|
ObjectKernel,
|
|
6339
6626
|
ObjectKernelBase,
|
|
6340
6627
|
ObjectLogger,
|
|
@@ -6356,12 +6643,17 @@ var NamespaceResolver = class {
|
|
|
6356
6643
|
ServiceLifecycle,
|
|
6357
6644
|
UnknownFilterTokenError,
|
|
6358
6645
|
UnresolvedFilterTokenError,
|
|
6646
|
+
assembleExecutionContext,
|
|
6647
|
+
assembleExecutionContextOrGuest,
|
|
6359
6648
|
assertInitServiceRequirements,
|
|
6649
|
+
assertMetadataRegisterContract,
|
|
6360
6650
|
bucketKeyToCalendarRange,
|
|
6361
6651
|
buildPermissionsFromGrants,
|
|
6362
6652
|
bulkWrite,
|
|
6363
6653
|
calendarPartsInTz,
|
|
6364
6654
|
calendarPartsInTzOrUtc,
|
|
6655
|
+
canonicalMetadataServiceType,
|
|
6656
|
+
collectInternalWriteResponseFields,
|
|
6365
6657
|
counterSignPayload,
|
|
6366
6658
|
createLogger,
|
|
6367
6659
|
createMemoryCache,
|
|
@@ -6386,18 +6678,22 @@ var NamespaceResolver = class {
|
|
|
6386
6678
|
getMemoryUsage,
|
|
6387
6679
|
hashApiKey,
|
|
6388
6680
|
hashMigrationPlan,
|
|
6681
|
+
isAudienceBindingSuggestionStatus,
|
|
6389
6682
|
isAuthGateAllowlisted,
|
|
6390
6683
|
isExpired,
|
|
6391
6684
|
isGrantActive,
|
|
6392
6685
|
isGrantExpired,
|
|
6393
6686
|
isNode,
|
|
6394
6687
|
nextUtcCalendarDay,
|
|
6688
|
+
normalizeAuthGate,
|
|
6689
|
+
omitInternalFieldsFromWriteResponse,
|
|
6395
6690
|
parseScopes,
|
|
6396
6691
|
parseSignature,
|
|
6397
6692
|
planChunks,
|
|
6398
6693
|
postureVisibleRows,
|
|
6399
6694
|
readAuthoredTranslationLayer,
|
|
6400
6695
|
readRunJournal,
|
|
6696
|
+
recordNotFoundError,
|
|
6401
6697
|
resolveApiKeyPrincipal,
|
|
6402
6698
|
resolveAuthzContext,
|
|
6403
6699
|
resolveFilterToken,
|
|
@@ -6411,6 +6707,7 @@ var NamespaceResolver = class {
|
|
|
6411
6707
|
safeExit,
|
|
6412
6708
|
shouldDenyAnonymous,
|
|
6413
6709
|
signPayload,
|
|
6710
|
+
unknownAudienceBindingSuggestionStatusMessage,
|
|
6414
6711
|
utcInstantMs,
|
|
6415
6712
|
validateInitServiceContract,
|
|
6416
6713
|
verifyPayload,
|
|
@@ -6419,6 +6716,7 @@ var NamespaceResolver = class {
|
|
|
6419
6716
|
verifyPublisherSignature,
|
|
6420
6717
|
wireAuthoredTranslationSync,
|
|
6421
6718
|
withTransientRetry,
|
|
6719
|
+
withoutOperationPrivateKeys,
|
|
6422
6720
|
zonedDateStartToUtcMs
|
|
6423
6721
|
});
|
|
6424
6722
|
//# sourceMappingURL=index.cjs.map
|