@objectstack/core 17.0.0-rc.4 → 17.0.0-rc.6
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 +521 -0
- package/dist/index.cjs +217 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +419 -45
- package/dist/index.d.ts +419 -45
- package/dist/index.js +211 -52
- 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
|
@@ -37,11 +37,13 @@ __export(index_exports, {
|
|
|
37
37
|
API_KEY_PREFIX: () => API_KEY_PREFIX,
|
|
38
38
|
CORE_FALLBACK_FACTORIES: () => CORE_FALLBACK_FACTORIES,
|
|
39
39
|
DependencyResolver: () => DependencyResolver,
|
|
40
|
+
ENTRY_EXECUTION_CONTEXT_FIELDS: () => ENTRY_EXECUTION_CONTEXT_FIELDS,
|
|
40
41
|
HotReloadManager: () => HotReloadManager,
|
|
41
42
|
LiteKernel: () => LiteKernel,
|
|
42
43
|
MigrationJournalRefusal: () => MigrationJournalRefusal,
|
|
43
44
|
MigrationPlanRegistry: () => MigrationPlanRegistry,
|
|
44
45
|
NamespaceResolver: () => NamespaceResolver,
|
|
46
|
+
OPERATION_PRIVATE_KEY_PREFIX: () => OPERATION_PRIVATE_KEY_PREFIX,
|
|
45
47
|
ObjectKernel: () => ObjectKernel,
|
|
46
48
|
ObjectKernelBase: () => ObjectKernelBase,
|
|
47
49
|
ObjectLogger: () => ObjectLogger,
|
|
@@ -63,6 +65,8 @@ __export(index_exports, {
|
|
|
63
65
|
ServiceLifecycle: () => ServiceLifecycle,
|
|
64
66
|
UnknownFilterTokenError: () => UnknownFilterTokenError,
|
|
65
67
|
UnresolvedFilterTokenError: () => UnresolvedFilterTokenError,
|
|
68
|
+
assembleExecutionContext: () => assembleExecutionContext,
|
|
69
|
+
assembleExecutionContextOrGuest: () => assembleExecutionContextOrGuest,
|
|
66
70
|
assertInitServiceRequirements: () => assertInitServiceRequirements,
|
|
67
71
|
bucketKeyToCalendarRange: () => bucketKeyToCalendarRange,
|
|
68
72
|
buildPermissionsFromGrants: () => buildPermissionsFromGrants,
|
|
@@ -99,6 +103,7 @@ __export(index_exports, {
|
|
|
99
103
|
isGrantExpired: () => isGrantExpired,
|
|
100
104
|
isNode: () => isNode,
|
|
101
105
|
nextUtcCalendarDay: () => import_data.nextUtcCalendarDay,
|
|
106
|
+
normalizeAuthGate: () => normalizeAuthGate,
|
|
102
107
|
parseScopes: () => parseScopes,
|
|
103
108
|
parseSignature: () => parseSignature,
|
|
104
109
|
planChunks: () => planChunks,
|
|
@@ -126,6 +131,7 @@ __export(index_exports, {
|
|
|
126
131
|
verifyPublisherSignature: () => verifyPublisherSignature,
|
|
127
132
|
wireAuthoredTranslationSync: () => wireAuthoredTranslationSync,
|
|
128
133
|
withTransientRetry: () => withTransientRetry,
|
|
134
|
+
withoutOperationPrivateKeys: () => withoutOperationPrivateKeys,
|
|
129
135
|
zonedDateStartToUtcMs: () => zonedDateStartToUtcMs
|
|
130
136
|
});
|
|
131
137
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -213,6 +219,30 @@ function assertInitServiceRequirements(plugin, isServiceRegistered) {
|
|
|
213
219
|
}
|
|
214
220
|
}
|
|
215
221
|
|
|
222
|
+
// src/hook-dispatch.ts
|
|
223
|
+
function traceDispatch(name, handlers, logger) {
|
|
224
|
+
logger.debug(`Triggering hook: ${name}`, {
|
|
225
|
+
hook: name,
|
|
226
|
+
handlerCount: handlers.length
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
async function dispatchHookIsolating(name, handlers, logger, args = []) {
|
|
230
|
+
traceDispatch(name, handlers, logger);
|
|
231
|
+
for (const handler of handlers) {
|
|
232
|
+
try {
|
|
233
|
+
await handler(...args);
|
|
234
|
+
} catch (error) {
|
|
235
|
+
logger.error(`Hook handler failed: ${name}`, error);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async function dispatchHookPropagating(name, handlers, logger, args = []) {
|
|
240
|
+
if (logger) traceDispatch(name, handlers, logger);
|
|
241
|
+
for (const handler of handlers) {
|
|
242
|
+
await handler(...args);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
216
246
|
// src/kernel-base.ts
|
|
217
247
|
var ObjectKernelBase = class {
|
|
218
248
|
constructor(logger) {
|
|
@@ -292,11 +322,11 @@ var ObjectKernelBase = class {
|
|
|
292
322
|
}
|
|
293
323
|
this.hooks.get(name).push(handler);
|
|
294
324
|
},
|
|
325
|
+
// PROPAGATING dispatch, and deliberately WITHOUT the trace line the
|
|
326
|
+
// kernel's own dispatch sites emit — `context.trigger` has never
|
|
327
|
+
// logged one, so no logger is handed over (#5282).
|
|
295
328
|
trigger: async (name, ...args) => {
|
|
296
|
-
|
|
297
|
-
for (const handler of handlers) {
|
|
298
|
-
await handler(...args);
|
|
299
|
-
}
|
|
329
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], void 0, args);
|
|
300
330
|
},
|
|
301
331
|
getServices: () => {
|
|
302
332
|
if (this.services instanceof Map) {
|
|
@@ -415,22 +445,16 @@ var ObjectKernelBase = class {
|
|
|
415
445
|
* (`kernel:ready`, `kernel:bootstrapped`, `kernel:listening`) use
|
|
416
446
|
* {@link triggerHookOrThrow} (#5170, #5257).
|
|
417
447
|
*
|
|
448
|
+
* The loop itself lives in {@link dispatchHookIsolating} — one
|
|
449
|
+
* implementation shared with `ObjectKernel`'s own `kernel:shutdown`
|
|
450
|
+
* dispatch, which cannot inherit this method (`ObjectKernel` does not
|
|
451
|
+
* extend this class) and used to hand-mirror it (#5282).
|
|
452
|
+
*
|
|
418
453
|
* @param name - Hook name
|
|
419
454
|
* @param args - Arguments to pass to handlers
|
|
420
455
|
*/
|
|
421
456
|
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
|
-
}
|
|
457
|
+
await dispatchHookIsolating(name, this.hooks.get(name) || [], this.logger, args);
|
|
434
458
|
}
|
|
435
459
|
/**
|
|
436
460
|
* Trigger a hook with all registered handlers, PROPAGATING the first
|
|
@@ -467,18 +491,15 @@ var ObjectKernelBase = class {
|
|
|
467
491
|
* default — and it is the reason this dispatcher is chosen per hook rather
|
|
468
492
|
* than swapped in wholesale.
|
|
469
493
|
*
|
|
494
|
+
* The loop itself lives in {@link dispatchHookPropagating} — the same
|
|
495
|
+
* function `PluginContext.trigger` runs on both kernels, so "propagating"
|
|
496
|
+
* means one thing repo-wide (#5282).
|
|
497
|
+
*
|
|
470
498
|
* @param name - Hook name
|
|
471
499
|
* @param args - Arguments to pass to handlers
|
|
472
500
|
*/
|
|
473
501
|
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
|
-
}
|
|
502
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], this.logger, args);
|
|
482
503
|
}
|
|
483
504
|
/**
|
|
484
505
|
* Get current kernel state
|
|
@@ -614,7 +635,15 @@ var ObjectLogger = class _ObjectLogger {
|
|
|
614
635
|
redact: config.redact ?? ["password", "token", "secret", "key"],
|
|
615
636
|
sourceLocation: config.sourceLocation ?? false,
|
|
616
637
|
file: config.file,
|
|
617
|
-
|
|
638
|
+
// Per-key, because `LoggerConfig` is the AUTHOR state (ADR-0122): the
|
|
639
|
+
// schema defaults `maxSize`/`maxFiles` *inside* `rotation`, so a caller
|
|
640
|
+
// may legitimately write `{ rotation: { maxSize: '5m' } }` and this
|
|
641
|
+
// constructor — which does not parse — has to fill the other half the
|
|
642
|
+
// same way `LoggerConfigSchema.parse` would.
|
|
643
|
+
rotation: {
|
|
644
|
+
maxSize: config.rotation?.maxSize ?? "10m",
|
|
645
|
+
maxFiles: config.rotation?.maxFiles ?? 5
|
|
646
|
+
}
|
|
618
647
|
};
|
|
619
648
|
this.bindings = bindings;
|
|
620
649
|
this.redactPatterns = this.config.redact.map(tokenizeFieldName).filter((words) => words.length > 0);
|
|
@@ -1843,11 +1872,12 @@ var ObjectKernel = class {
|
|
|
1843
1872
|
}
|
|
1844
1873
|
this.hooks.get(name).push(handler);
|
|
1845
1874
|
},
|
|
1875
|
+
// PROPAGATING dispatch — the same shared loop `LiteKernel`'s
|
|
1876
|
+
// context.trigger runs, and deliberately WITHOUT a trace line:
|
|
1877
|
+
// `context.trigger` has never emitted one on either kernel, so no
|
|
1878
|
+
// logger is handed over (#5282).
|
|
1846
1879
|
trigger: async (name, ...args) => {
|
|
1847
|
-
|
|
1848
|
-
for (const handler of handlers) {
|
|
1849
|
-
await handler(...args);
|
|
1850
|
-
}
|
|
1880
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], void 0, args);
|
|
1851
1881
|
},
|
|
1852
1882
|
getServices: () => {
|
|
1853
1883
|
return new Map(this.services);
|
|
@@ -2271,27 +2301,21 @@ var ObjectKernel = class {
|
|
|
2271
2301
|
* one bad handler must not amplify into leaked resources and unflushed
|
|
2272
2302
|
* writes. Same reasoning, same wording, same `Hook handler failed:
|
|
2273
2303
|
* kernel:shutdown` log line as `LiteKernel`'s dispatch site, which reaches
|
|
2274
|
-
* the
|
|
2304
|
+
* the isolating dispatcher through `ObjectKernelBase.triggerHook` (#5257).
|
|
2275
2305
|
*
|
|
2276
|
-
*
|
|
2306
|
+
* Until #5282 "same wording" was literally that — the loop was typed out a
|
|
2307
|
+
* second time here, because `ObjectKernel` does not extend
|
|
2277
2308
|
* `ObjectKernelBase` (only `LiteKernel` does) and owns its own `hooks` map,
|
|
2278
|
-
* so the
|
|
2279
|
-
*
|
|
2280
|
-
*
|
|
2309
|
+
* so the base's `protected triggerHook` is out of reach. The loop now lives
|
|
2310
|
+
* in {@link dispatchHookIsolating}, which BOTH sides call: the storage is
|
|
2311
|
+
* still two maps (deliberately — unifying it was out of #5282's scope), but
|
|
2312
|
+
* "isolating" is one implementation, so it can no longer drift on one
|
|
2313
|
+
* kernel while the other keeps the old shape. That drift is exactly the bug
|
|
2314
|
+
* #5170 / #5257 / #5274 each closed one hook at a time, and the paired-pin
|
|
2315
|
+
* gate (`scripts/check-kernel-hook-pairs.mjs`) covers the residue.
|
|
2281
2316
|
*/
|
|
2282
2317
|
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
|
-
}
|
|
2318
|
+
await dispatchHookIsolating("kernel:shutdown", this.hooks.get("kernel:shutdown") || [], this.logger);
|
|
2295
2319
|
}
|
|
2296
2320
|
async performShutdown() {
|
|
2297
2321
|
await this.triggerShutdownHookIsolating();
|
|
@@ -2459,6 +2483,20 @@ __export(qa_exports, {
|
|
|
2459
2483
|
});
|
|
2460
2484
|
|
|
2461
2485
|
// src/qa/runner.ts
|
|
2486
|
+
function describeActualType(value) {
|
|
2487
|
+
if (value === null) return "null";
|
|
2488
|
+
if (Array.isArray(value)) return "array";
|
|
2489
|
+
return typeof value;
|
|
2490
|
+
}
|
|
2491
|
+
function containsInapplicableHint(actual) {
|
|
2492
|
+
if (actual === void 0) {
|
|
2493
|
+
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.";
|
|
2494
|
+
}
|
|
2495
|
+
if (actual === null) {
|
|
2496
|
+
return "The path resolved to null. Use 'is_null' if asserting absence is what you meant.";
|
|
2497
|
+
}
|
|
2498
|
+
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.";
|
|
2499
|
+
}
|
|
2462
2500
|
var TestRunner = class {
|
|
2463
2501
|
constructor(adapter) {
|
|
2464
2502
|
this.adapter = adapter;
|
|
@@ -2586,6 +2624,10 @@ var TestRunner = class {
|
|
|
2586
2624
|
if (!actual.includes(expected)) throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);
|
|
2587
2625
|
} else if (typeof actual === "string") {
|
|
2588
2626
|
if (!actual.includes(String(expected))) throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);
|
|
2627
|
+
} else {
|
|
2628
|
+
throw new Error(
|
|
2629
|
+
`Assertion failed: ${assertion.field} cannot be evaluated by 'contains' \u2014 expected an array or a string at that path, got ${describeActualType(actual)}. ` + containsInapplicableHint(actual)
|
|
2630
|
+
);
|
|
2589
2631
|
}
|
|
2590
2632
|
break;
|
|
2591
2633
|
case "not_null":
|
|
@@ -4466,7 +4508,116 @@ async function resolveLocalizationContext(input) {
|
|
|
4466
4508
|
};
|
|
4467
4509
|
}
|
|
4468
4510
|
|
|
4511
|
+
// src/security/assemble-execution-context.ts
|
|
4512
|
+
var ENTRY_EXECUTION_CONTEXT_FIELDS = [
|
|
4513
|
+
"positions",
|
|
4514
|
+
"permissions",
|
|
4515
|
+
"systemPermissions",
|
|
4516
|
+
"isSystem",
|
|
4517
|
+
"principalKind",
|
|
4518
|
+
"onBehalfOf",
|
|
4519
|
+
"audience",
|
|
4520
|
+
"userId",
|
|
4521
|
+
"tenantId",
|
|
4522
|
+
"email",
|
|
4523
|
+
"accessToken",
|
|
4524
|
+
"tabPermissions",
|
|
4525
|
+
"posture",
|
|
4526
|
+
"authGate",
|
|
4527
|
+
"org_user_ids",
|
|
4528
|
+
"accessible_org_ids",
|
|
4529
|
+
"oauthScopes",
|
|
4530
|
+
"timezone",
|
|
4531
|
+
"locale",
|
|
4532
|
+
"currency"
|
|
4533
|
+
];
|
|
4534
|
+
function emit(fields) {
|
|
4535
|
+
const ctx = {};
|
|
4536
|
+
for (const key of ENTRY_EXECUTION_CONTEXT_FIELDS) {
|
|
4537
|
+
const value = fields[key];
|
|
4538
|
+
if (value !== void 0) ctx[key] = value;
|
|
4539
|
+
}
|
|
4540
|
+
return ctx;
|
|
4541
|
+
}
|
|
4542
|
+
function entryFields(input, anonymous) {
|
|
4543
|
+
const { authz, oauth, localization, requestLocale, accessToken, authGate } = input;
|
|
4544
|
+
const agent = !anonymous && oauth?.clientId ? oauth : void 0;
|
|
4545
|
+
return {
|
|
4546
|
+
// [ADR-0090 D9/D10] Principal taxonomy at the HTTP entry: a session-backed
|
|
4547
|
+
// request is a human principal; a sessionless one is a guest, holding the
|
|
4548
|
+
// built-in `guest` position implicitly and exclusively. Internal engine
|
|
4549
|
+
// calls that construct bare contexts never pass through here, so the
|
|
4550
|
+
// security plugin's empty-context skip path keeps its meaning.
|
|
4551
|
+
positions: agent ? [] : anonymous ? ["guest"] : authz.positions,
|
|
4552
|
+
permissions: agent ? agent.scopePermissions : authz.permissions,
|
|
4553
|
+
// [ADR-0090 D10] System capabilities on the agent principal gate business
|
|
4554
|
+
// ACTION invocation (`actionPermissionError` reads `ctx.systemPermissions`)
|
|
4555
|
+
// — a door SEPARATE from the object CRUD/FLS/RLS intersection, which is
|
|
4556
|
+
// driven by the resolved ceiling SETS (they carry no caps, so cap-gated
|
|
4557
|
+
// OBJECT access stays denied to the agent regardless of this line). The
|
|
4558
|
+
// `actions:execute` scope IS the user's consent to let this agent invoke
|
|
4559
|
+
// actions on their behalf; without it the agent holds none.
|
|
4560
|
+
systemPermissions: agent ? agent.delegatesActions ? authz.systemPermissions ?? [] : [] : authz.systemPermissions,
|
|
4561
|
+
isSystem: false,
|
|
4562
|
+
principalKind: agent ? "agent" : anonymous ? "guest" : "human",
|
|
4563
|
+
onBehalfOf: agent ? { userId: authz.userId, principalKind: "human" } : void 0,
|
|
4564
|
+
// [ADR-0090 D10/D11 — P1 shape] No transport resolves an external
|
|
4565
|
+
// (portal/partner) audience yet; `undefined` reads as 'internal'. Named
|
|
4566
|
+
// here rather than excluded so the gap is visible in the closed set instead
|
|
4567
|
+
// of being invisible outside it — when an external principal type lands,
|
|
4568
|
+
// this is the line that must change, on every face at once.
|
|
4569
|
+
audience: void 0,
|
|
4570
|
+
userId: authz.userId,
|
|
4571
|
+
tenantId: authz.tenantId,
|
|
4572
|
+
email: authz.email,
|
|
4573
|
+
accessToken,
|
|
4574
|
+
tabPermissions: authz.tabPermissions,
|
|
4575
|
+
// [ADR-0095 D2 / #2947] The derived posture rung, carried so every
|
|
4576
|
+
// transport presents enforcement the SAME value. Present only for an
|
|
4577
|
+
// authenticated principal (guest → absent).
|
|
4578
|
+
posture: authz.posture,
|
|
4579
|
+
// [ADR-0069 / #7280] The AUTHENTICATION-policy gate, carried for the seam
|
|
4580
|
+
// that reads it off the envelope (REST's `enforceAuth`). Anonymous → never:
|
|
4581
|
+
// a guest has no authenticated session for a policy gate to attach to, so
|
|
4582
|
+
// "gated guest" is not a state this entry can emit even if a face passed
|
|
4583
|
+
// one.
|
|
4584
|
+
authGate: anonymous ? void 0 : authGate,
|
|
4585
|
+
/** Fellow-org user IDs for RLS scoping of identity tables. */
|
|
4586
|
+
org_user_ids: authz.org_user_ids,
|
|
4587
|
+
// [ADR-0105 D2] The caller's org access set — the `group` posture's Layer 0
|
|
4588
|
+
// wall reads it directly, so every transport must carry it (#6206).
|
|
4589
|
+
accessible_org_ids: authz.accessible_org_ids,
|
|
4590
|
+
// OAuth provenance: surface the token's granted scopes so the MCP
|
|
4591
|
+
// dispatcher can narrow the exposed tool families (undefined for every
|
|
4592
|
+
// other provenance = not scope-limited).
|
|
4593
|
+
oauthScopes: oauth && authz.userId === oauth.userId ? oauth.scopes : void 0,
|
|
4594
|
+
// Anonymous → no localization (no scope to resolve against); the engine
|
|
4595
|
+
// default stands. [#3957] The request's OWN language preference wins over
|
|
4596
|
+
// the workspace default, so a rejection message is not rendered in English
|
|
4597
|
+
// beside the Chinese label of the very field it names.
|
|
4598
|
+
timezone: anonymous ? void 0 : localization?.timezone,
|
|
4599
|
+
locale: anonymous ? void 0 : requestLocale ?? localization?.locale,
|
|
4600
|
+
currency: anonymous ? void 0 : localization?.currency
|
|
4601
|
+
};
|
|
4602
|
+
}
|
|
4603
|
+
function assembleExecutionContext(input) {
|
|
4604
|
+
if (!input.authz.userId) return void 0;
|
|
4605
|
+
return emit(entryFields(input, false));
|
|
4606
|
+
}
|
|
4607
|
+
function assembleExecutionContextOrGuest(input) {
|
|
4608
|
+
return emit(entryFields(input, !input.authz.userId));
|
|
4609
|
+
}
|
|
4610
|
+
|
|
4469
4611
|
// src/security/auth-gate.ts
|
|
4612
|
+
var DEFAULT_AUTH_GATE_MESSAGE = "Access is blocked by an authentication policy.";
|
|
4613
|
+
function normalizeAuthGate(sessionUser) {
|
|
4614
|
+
const gate = sessionUser?.authGate;
|
|
4615
|
+
if (!gate || typeof gate.code !== "string") return null;
|
|
4616
|
+
return {
|
|
4617
|
+
code: gate.code,
|
|
4618
|
+
message: typeof gate.message === "string" && gate.message ? gate.message : DEFAULT_AUTH_GATE_MESSAGE
|
|
4619
|
+
};
|
|
4620
|
+
}
|
|
4470
4621
|
var ALLOW_PREFIXES = ["/api/v1/auth/", "/api/auth/", "/auth/"];
|
|
4471
4622
|
var ALLOW_SUFFIXES = ["/health", "/ready", "/discovery", "/me/apps", "/me/localization"];
|
|
4472
4623
|
function isAuthGateAllowlisted(rawPath) {
|
|
@@ -4485,13 +4636,10 @@ function isAuthGateAllowlisted(rawPath) {
|
|
|
4485
4636
|
return false;
|
|
4486
4637
|
}
|
|
4487
4638
|
function evaluateAuthGate(sessionUser, path) {
|
|
4488
|
-
const gate = sessionUser
|
|
4489
|
-
if (!gate
|
|
4639
|
+
const gate = normalizeAuthGate(sessionUser);
|
|
4640
|
+
if (!gate) return null;
|
|
4490
4641
|
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
|
-
};
|
|
4642
|
+
return gate;
|
|
4495
4643
|
}
|
|
4496
4644
|
|
|
4497
4645
|
// src/security/anonymous-deny.ts
|
|
@@ -4513,6 +4661,17 @@ function shouldDenyAnonymous(input) {
|
|
|
4513
4661
|
return true;
|
|
4514
4662
|
}
|
|
4515
4663
|
|
|
4664
|
+
// src/security/operation-private-keys.ts
|
|
4665
|
+
var OPERATION_PRIVATE_KEY_PREFIX = "__";
|
|
4666
|
+
function withoutOperationPrivateKeys(exec) {
|
|
4667
|
+
const out = {};
|
|
4668
|
+
for (const [key, value] of Object.entries(exec)) {
|
|
4669
|
+
if (key.startsWith(OPERATION_PRIVATE_KEY_PREFIX)) continue;
|
|
4670
|
+
out[key] = value;
|
|
4671
|
+
}
|
|
4672
|
+
return out;
|
|
4673
|
+
}
|
|
4674
|
+
|
|
4516
4675
|
// src/utils/datetime.ts
|
|
4517
4676
|
var import_data = require("@objectstack/spec/data");
|
|
4518
4677
|
function calendarPartsInTz(d, tz) {
|
|
@@ -6330,11 +6489,13 @@ var NamespaceResolver = class {
|
|
|
6330
6489
|
API_KEY_PREFIX,
|
|
6331
6490
|
CORE_FALLBACK_FACTORIES,
|
|
6332
6491
|
DependencyResolver,
|
|
6492
|
+
ENTRY_EXECUTION_CONTEXT_FIELDS,
|
|
6333
6493
|
HotReloadManager,
|
|
6334
6494
|
LiteKernel,
|
|
6335
6495
|
MigrationJournalRefusal,
|
|
6336
6496
|
MigrationPlanRegistry,
|
|
6337
6497
|
NamespaceResolver,
|
|
6498
|
+
OPERATION_PRIVATE_KEY_PREFIX,
|
|
6338
6499
|
ObjectKernel,
|
|
6339
6500
|
ObjectKernelBase,
|
|
6340
6501
|
ObjectLogger,
|
|
@@ -6356,6 +6517,8 @@ var NamespaceResolver = class {
|
|
|
6356
6517
|
ServiceLifecycle,
|
|
6357
6518
|
UnknownFilterTokenError,
|
|
6358
6519
|
UnresolvedFilterTokenError,
|
|
6520
|
+
assembleExecutionContext,
|
|
6521
|
+
assembleExecutionContextOrGuest,
|
|
6359
6522
|
assertInitServiceRequirements,
|
|
6360
6523
|
bucketKeyToCalendarRange,
|
|
6361
6524
|
buildPermissionsFromGrants,
|
|
@@ -6392,6 +6555,7 @@ var NamespaceResolver = class {
|
|
|
6392
6555
|
isGrantExpired,
|
|
6393
6556
|
isNode,
|
|
6394
6557
|
nextUtcCalendarDay,
|
|
6558
|
+
normalizeAuthGate,
|
|
6395
6559
|
parseScopes,
|
|
6396
6560
|
parseSignature,
|
|
6397
6561
|
planChunks,
|
|
@@ -6419,6 +6583,7 @@ var NamespaceResolver = class {
|
|
|
6419
6583
|
verifyPublisherSignature,
|
|
6420
6584
|
wireAuthoredTranslationSync,
|
|
6421
6585
|
withTransientRetry,
|
|
6586
|
+
withoutOperationPrivateKeys,
|
|
6422
6587
|
zonedDateStartToUtcMs
|
|
6423
6588
|
});
|
|
6424
6589
|
//# sourceMappingURL=index.cjs.map
|