@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.js
CHANGED
|
@@ -93,6 +93,30 @@ function assertInitServiceRequirements(plugin, isServiceRegistered) {
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
// src/hook-dispatch.ts
|
|
97
|
+
function traceDispatch(name, handlers, logger) {
|
|
98
|
+
logger.debug(`Triggering hook: ${name}`, {
|
|
99
|
+
hook: name,
|
|
100
|
+
handlerCount: handlers.length
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async function dispatchHookIsolating(name, handlers, logger, args = []) {
|
|
104
|
+
traceDispatch(name, handlers, logger);
|
|
105
|
+
for (const handler of handlers) {
|
|
106
|
+
try {
|
|
107
|
+
await handler(...args);
|
|
108
|
+
} catch (error) {
|
|
109
|
+
logger.error(`Hook handler failed: ${name}`, error);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async function dispatchHookPropagating(name, handlers, logger, args = []) {
|
|
114
|
+
if (logger) traceDispatch(name, handlers, logger);
|
|
115
|
+
for (const handler of handlers) {
|
|
116
|
+
await handler(...args);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
96
120
|
// src/kernel-base.ts
|
|
97
121
|
var ObjectKernelBase = class {
|
|
98
122
|
constructor(logger) {
|
|
@@ -172,11 +196,11 @@ var ObjectKernelBase = class {
|
|
|
172
196
|
}
|
|
173
197
|
this.hooks.get(name).push(handler);
|
|
174
198
|
},
|
|
199
|
+
// PROPAGATING dispatch, and deliberately WITHOUT the trace line the
|
|
200
|
+
// kernel's own dispatch sites emit — `context.trigger` has never
|
|
201
|
+
// logged one, so no logger is handed over (#5282).
|
|
175
202
|
trigger: async (name, ...args) => {
|
|
176
|
-
|
|
177
|
-
for (const handler of handlers) {
|
|
178
|
-
await handler(...args);
|
|
179
|
-
}
|
|
203
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], void 0, args);
|
|
180
204
|
},
|
|
181
205
|
getServices: () => {
|
|
182
206
|
if (this.services instanceof Map) {
|
|
@@ -295,22 +319,16 @@ var ObjectKernelBase = class {
|
|
|
295
319
|
* (`kernel:ready`, `kernel:bootstrapped`, `kernel:listening`) use
|
|
296
320
|
* {@link triggerHookOrThrow} (#5170, #5257).
|
|
297
321
|
*
|
|
322
|
+
* The loop itself lives in {@link dispatchHookIsolating} — one
|
|
323
|
+
* implementation shared with `ObjectKernel`'s own `kernel:shutdown`
|
|
324
|
+
* dispatch, which cannot inherit this method (`ObjectKernel` does not
|
|
325
|
+
* extend this class) and used to hand-mirror it (#5282).
|
|
326
|
+
*
|
|
298
327
|
* @param name - Hook name
|
|
299
328
|
* @param args - Arguments to pass to handlers
|
|
300
329
|
*/
|
|
301
330
|
async triggerHook(name, ...args) {
|
|
302
|
-
|
|
303
|
-
this.logger.debug(`Triggering hook: ${name}`, {
|
|
304
|
-
hook: name,
|
|
305
|
-
handlerCount: handlers.length
|
|
306
|
-
});
|
|
307
|
-
for (const handler of handlers) {
|
|
308
|
-
try {
|
|
309
|
-
await handler(...args);
|
|
310
|
-
} catch (error) {
|
|
311
|
-
this.logger.error(`Hook handler failed: ${name}`, error);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
331
|
+
await dispatchHookIsolating(name, this.hooks.get(name) || [], this.logger, args);
|
|
314
332
|
}
|
|
315
333
|
/**
|
|
316
334
|
* Trigger a hook with all registered handlers, PROPAGATING the first
|
|
@@ -347,18 +365,15 @@ var ObjectKernelBase = class {
|
|
|
347
365
|
* default — and it is the reason this dispatcher is chosen per hook rather
|
|
348
366
|
* than swapped in wholesale.
|
|
349
367
|
*
|
|
368
|
+
* The loop itself lives in {@link dispatchHookPropagating} — the same
|
|
369
|
+
* function `PluginContext.trigger` runs on both kernels, so "propagating"
|
|
370
|
+
* means one thing repo-wide (#5282).
|
|
371
|
+
*
|
|
350
372
|
* @param name - Hook name
|
|
351
373
|
* @param args - Arguments to pass to handlers
|
|
352
374
|
*/
|
|
353
375
|
async triggerHookOrThrow(name, ...args) {
|
|
354
|
-
|
|
355
|
-
this.logger.debug(`Triggering hook: ${name}`, {
|
|
356
|
-
hook: name,
|
|
357
|
-
handlerCount: handlers.length
|
|
358
|
-
});
|
|
359
|
-
for (const handler of handlers) {
|
|
360
|
-
await handler(...args);
|
|
361
|
-
}
|
|
376
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], this.logger, args);
|
|
362
377
|
}
|
|
363
378
|
/**
|
|
364
379
|
* Get current kernel state
|
|
@@ -494,7 +509,15 @@ var ObjectLogger = class _ObjectLogger {
|
|
|
494
509
|
redact: config.redact ?? ["password", "token", "secret", "key"],
|
|
495
510
|
sourceLocation: config.sourceLocation ?? false,
|
|
496
511
|
file: config.file,
|
|
497
|
-
|
|
512
|
+
// Per-key, because `LoggerConfig` is the AUTHOR state (ADR-0122): the
|
|
513
|
+
// schema defaults `maxSize`/`maxFiles` *inside* `rotation`, so a caller
|
|
514
|
+
// may legitimately write `{ rotation: { maxSize: '5m' } }` and this
|
|
515
|
+
// constructor — which does not parse — has to fill the other half the
|
|
516
|
+
// same way `LoggerConfigSchema.parse` would.
|
|
517
|
+
rotation: {
|
|
518
|
+
maxSize: config.rotation?.maxSize ?? "10m",
|
|
519
|
+
maxFiles: config.rotation?.maxFiles ?? 5
|
|
520
|
+
}
|
|
498
521
|
};
|
|
499
522
|
this.bindings = bindings;
|
|
500
523
|
this.redactPatterns = this.config.redact.map(tokenizeFieldName).filter((words) => words.length > 0);
|
|
@@ -1729,11 +1752,12 @@ var ObjectKernel = class {
|
|
|
1729
1752
|
}
|
|
1730
1753
|
this.hooks.get(name).push(handler);
|
|
1731
1754
|
},
|
|
1755
|
+
// PROPAGATING dispatch — the same shared loop `LiteKernel`'s
|
|
1756
|
+
// context.trigger runs, and deliberately WITHOUT a trace line:
|
|
1757
|
+
// `context.trigger` has never emitted one on either kernel, so no
|
|
1758
|
+
// logger is handed over (#5282).
|
|
1732
1759
|
trigger: async (name, ...args) => {
|
|
1733
|
-
|
|
1734
|
-
for (const handler of handlers) {
|
|
1735
|
-
await handler(...args);
|
|
1736
|
-
}
|
|
1760
|
+
await dispatchHookPropagating(name, this.hooks.get(name) || [], void 0, args);
|
|
1737
1761
|
},
|
|
1738
1762
|
getServices: () => {
|
|
1739
1763
|
return new Map(this.services);
|
|
@@ -2157,27 +2181,21 @@ var ObjectKernel = class {
|
|
|
2157
2181
|
* one bad handler must not amplify into leaked resources and unflushed
|
|
2158
2182
|
* writes. Same reasoning, same wording, same `Hook handler failed:
|
|
2159
2183
|
* kernel:shutdown` log line as `LiteKernel`'s dispatch site, which reaches
|
|
2160
|
-
* the
|
|
2184
|
+
* the isolating dispatcher through `ObjectKernelBase.triggerHook` (#5257).
|
|
2161
2185
|
*
|
|
2162
|
-
*
|
|
2186
|
+
* Until #5282 "same wording" was literally that — the loop was typed out a
|
|
2187
|
+
* second time here, because `ObjectKernel` does not extend
|
|
2163
2188
|
* `ObjectKernelBase` (only `LiteKernel` does) and owns its own `hooks` map,
|
|
2164
|
-
* so the
|
|
2165
|
-
*
|
|
2166
|
-
*
|
|
2189
|
+
* so the base's `protected triggerHook` is out of reach. The loop now lives
|
|
2190
|
+
* in {@link dispatchHookIsolating}, which BOTH sides call: the storage is
|
|
2191
|
+
* still two maps (deliberately — unifying it was out of #5282's scope), but
|
|
2192
|
+
* "isolating" is one implementation, so it can no longer drift on one
|
|
2193
|
+
* kernel while the other keeps the old shape. That drift is exactly the bug
|
|
2194
|
+
* #5170 / #5257 / #5274 each closed one hook at a time, and the paired-pin
|
|
2195
|
+
* gate (`scripts/check-kernel-hook-pairs.mjs`) covers the residue.
|
|
2167
2196
|
*/
|
|
2168
2197
|
async triggerShutdownHookIsolating() {
|
|
2169
|
-
|
|
2170
|
-
this.logger.debug("Triggering hook: kernel:shutdown", {
|
|
2171
|
-
hook: "kernel:shutdown",
|
|
2172
|
-
handlerCount: handlers.length
|
|
2173
|
-
});
|
|
2174
|
-
for (const handler of handlers) {
|
|
2175
|
-
try {
|
|
2176
|
-
await handler();
|
|
2177
|
-
} catch (error) {
|
|
2178
|
-
this.logger.error("Hook handler failed: kernel:shutdown", error);
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2198
|
+
await dispatchHookIsolating("kernel:shutdown", this.hooks.get("kernel:shutdown") || [], this.logger);
|
|
2181
2199
|
}
|
|
2182
2200
|
async performShutdown() {
|
|
2183
2201
|
await this.triggerShutdownHookIsolating();
|
|
@@ -2345,6 +2363,20 @@ __export(qa_exports, {
|
|
|
2345
2363
|
});
|
|
2346
2364
|
|
|
2347
2365
|
// src/qa/runner.ts
|
|
2366
|
+
function describeActualType(value) {
|
|
2367
|
+
if (value === null) return "null";
|
|
2368
|
+
if (Array.isArray(value)) return "array";
|
|
2369
|
+
return typeof value;
|
|
2370
|
+
}
|
|
2371
|
+
function containsInapplicableHint(actual) {
|
|
2372
|
+
if (actual === void 0) {
|
|
2373
|
+
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.";
|
|
2374
|
+
}
|
|
2375
|
+
if (actual === null) {
|
|
2376
|
+
return "The path resolved to null. Use 'is_null' if asserting absence is what you meant.";
|
|
2377
|
+
}
|
|
2378
|
+
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.";
|
|
2379
|
+
}
|
|
2348
2380
|
var TestRunner = class {
|
|
2349
2381
|
constructor(adapter) {
|
|
2350
2382
|
this.adapter = adapter;
|
|
@@ -2472,6 +2504,10 @@ var TestRunner = class {
|
|
|
2472
2504
|
if (!actual.includes(expected)) throw new Error(`Assertion failed: ${assertion.field} array does not contain ${expected}`);
|
|
2473
2505
|
} else if (typeof actual === "string") {
|
|
2474
2506
|
if (!actual.includes(String(expected))) throw new Error(`Assertion failed: ${assertion.field} string does not contain ${expected}`);
|
|
2507
|
+
} else {
|
|
2508
|
+
throw new Error(
|
|
2509
|
+
`Assertion failed: ${assertion.field} cannot be evaluated by 'contains' \u2014 expected an array or a string at that path, got ${describeActualType(actual)}. ` + containsInapplicableHint(actual)
|
|
2510
|
+
);
|
|
2475
2511
|
}
|
|
2476
2512
|
break;
|
|
2477
2513
|
case "not_null":
|
|
@@ -4357,7 +4393,116 @@ async function resolveLocalizationContext(input) {
|
|
|
4357
4393
|
};
|
|
4358
4394
|
}
|
|
4359
4395
|
|
|
4396
|
+
// src/security/assemble-execution-context.ts
|
|
4397
|
+
var ENTRY_EXECUTION_CONTEXT_FIELDS = [
|
|
4398
|
+
"positions",
|
|
4399
|
+
"permissions",
|
|
4400
|
+
"systemPermissions",
|
|
4401
|
+
"isSystem",
|
|
4402
|
+
"principalKind",
|
|
4403
|
+
"onBehalfOf",
|
|
4404
|
+
"audience",
|
|
4405
|
+
"userId",
|
|
4406
|
+
"tenantId",
|
|
4407
|
+
"email",
|
|
4408
|
+
"accessToken",
|
|
4409
|
+
"tabPermissions",
|
|
4410
|
+
"posture",
|
|
4411
|
+
"authGate",
|
|
4412
|
+
"org_user_ids",
|
|
4413
|
+
"accessible_org_ids",
|
|
4414
|
+
"oauthScopes",
|
|
4415
|
+
"timezone",
|
|
4416
|
+
"locale",
|
|
4417
|
+
"currency"
|
|
4418
|
+
];
|
|
4419
|
+
function emit(fields) {
|
|
4420
|
+
const ctx = {};
|
|
4421
|
+
for (const key of ENTRY_EXECUTION_CONTEXT_FIELDS) {
|
|
4422
|
+
const value = fields[key];
|
|
4423
|
+
if (value !== void 0) ctx[key] = value;
|
|
4424
|
+
}
|
|
4425
|
+
return ctx;
|
|
4426
|
+
}
|
|
4427
|
+
function entryFields(input, anonymous) {
|
|
4428
|
+
const { authz, oauth, localization, requestLocale, accessToken, authGate } = input;
|
|
4429
|
+
const agent = !anonymous && oauth?.clientId ? oauth : void 0;
|
|
4430
|
+
return {
|
|
4431
|
+
// [ADR-0090 D9/D10] Principal taxonomy at the HTTP entry: a session-backed
|
|
4432
|
+
// request is a human principal; a sessionless one is a guest, holding the
|
|
4433
|
+
// built-in `guest` position implicitly and exclusively. Internal engine
|
|
4434
|
+
// calls that construct bare contexts never pass through here, so the
|
|
4435
|
+
// security plugin's empty-context skip path keeps its meaning.
|
|
4436
|
+
positions: agent ? [] : anonymous ? ["guest"] : authz.positions,
|
|
4437
|
+
permissions: agent ? agent.scopePermissions : authz.permissions,
|
|
4438
|
+
// [ADR-0090 D10] System capabilities on the agent principal gate business
|
|
4439
|
+
// ACTION invocation (`actionPermissionError` reads `ctx.systemPermissions`)
|
|
4440
|
+
// — a door SEPARATE from the object CRUD/FLS/RLS intersection, which is
|
|
4441
|
+
// driven by the resolved ceiling SETS (they carry no caps, so cap-gated
|
|
4442
|
+
// OBJECT access stays denied to the agent regardless of this line). The
|
|
4443
|
+
// `actions:execute` scope IS the user's consent to let this agent invoke
|
|
4444
|
+
// actions on their behalf; without it the agent holds none.
|
|
4445
|
+
systemPermissions: agent ? agent.delegatesActions ? authz.systemPermissions ?? [] : [] : authz.systemPermissions,
|
|
4446
|
+
isSystem: false,
|
|
4447
|
+
principalKind: agent ? "agent" : anonymous ? "guest" : "human",
|
|
4448
|
+
onBehalfOf: agent ? { userId: authz.userId, principalKind: "human" } : void 0,
|
|
4449
|
+
// [ADR-0090 D10/D11 — P1 shape] No transport resolves an external
|
|
4450
|
+
// (portal/partner) audience yet; `undefined` reads as 'internal'. Named
|
|
4451
|
+
// here rather than excluded so the gap is visible in the closed set instead
|
|
4452
|
+
// of being invisible outside it — when an external principal type lands,
|
|
4453
|
+
// this is the line that must change, on every face at once.
|
|
4454
|
+
audience: void 0,
|
|
4455
|
+
userId: authz.userId,
|
|
4456
|
+
tenantId: authz.tenantId,
|
|
4457
|
+
email: authz.email,
|
|
4458
|
+
accessToken,
|
|
4459
|
+
tabPermissions: authz.tabPermissions,
|
|
4460
|
+
// [ADR-0095 D2 / #2947] The derived posture rung, carried so every
|
|
4461
|
+
// transport presents enforcement the SAME value. Present only for an
|
|
4462
|
+
// authenticated principal (guest → absent).
|
|
4463
|
+
posture: authz.posture,
|
|
4464
|
+
// [ADR-0069 / #7280] The AUTHENTICATION-policy gate, carried for the seam
|
|
4465
|
+
// that reads it off the envelope (REST's `enforceAuth`). Anonymous → never:
|
|
4466
|
+
// a guest has no authenticated session for a policy gate to attach to, so
|
|
4467
|
+
// "gated guest" is not a state this entry can emit even if a face passed
|
|
4468
|
+
// one.
|
|
4469
|
+
authGate: anonymous ? void 0 : authGate,
|
|
4470
|
+
/** Fellow-org user IDs for RLS scoping of identity tables. */
|
|
4471
|
+
org_user_ids: authz.org_user_ids,
|
|
4472
|
+
// [ADR-0105 D2] The caller's org access set — the `group` posture's Layer 0
|
|
4473
|
+
// wall reads it directly, so every transport must carry it (#6206).
|
|
4474
|
+
accessible_org_ids: authz.accessible_org_ids,
|
|
4475
|
+
// OAuth provenance: surface the token's granted scopes so the MCP
|
|
4476
|
+
// dispatcher can narrow the exposed tool families (undefined for every
|
|
4477
|
+
// other provenance = not scope-limited).
|
|
4478
|
+
oauthScopes: oauth && authz.userId === oauth.userId ? oauth.scopes : void 0,
|
|
4479
|
+
// Anonymous → no localization (no scope to resolve against); the engine
|
|
4480
|
+
// default stands. [#3957] The request's OWN language preference wins over
|
|
4481
|
+
// the workspace default, so a rejection message is not rendered in English
|
|
4482
|
+
// beside the Chinese label of the very field it names.
|
|
4483
|
+
timezone: anonymous ? void 0 : localization?.timezone,
|
|
4484
|
+
locale: anonymous ? void 0 : requestLocale ?? localization?.locale,
|
|
4485
|
+
currency: anonymous ? void 0 : localization?.currency
|
|
4486
|
+
};
|
|
4487
|
+
}
|
|
4488
|
+
function assembleExecutionContext(input) {
|
|
4489
|
+
if (!input.authz.userId) return void 0;
|
|
4490
|
+
return emit(entryFields(input, false));
|
|
4491
|
+
}
|
|
4492
|
+
function assembleExecutionContextOrGuest(input) {
|
|
4493
|
+
return emit(entryFields(input, !input.authz.userId));
|
|
4494
|
+
}
|
|
4495
|
+
|
|
4360
4496
|
// src/security/auth-gate.ts
|
|
4497
|
+
var DEFAULT_AUTH_GATE_MESSAGE = "Access is blocked by an authentication policy.";
|
|
4498
|
+
function normalizeAuthGate(sessionUser) {
|
|
4499
|
+
const gate = sessionUser?.authGate;
|
|
4500
|
+
if (!gate || typeof gate.code !== "string") return null;
|
|
4501
|
+
return {
|
|
4502
|
+
code: gate.code,
|
|
4503
|
+
message: typeof gate.message === "string" && gate.message ? gate.message : DEFAULT_AUTH_GATE_MESSAGE
|
|
4504
|
+
};
|
|
4505
|
+
}
|
|
4361
4506
|
var ALLOW_PREFIXES = ["/api/v1/auth/", "/api/auth/", "/auth/"];
|
|
4362
4507
|
var ALLOW_SUFFIXES = ["/health", "/ready", "/discovery", "/me/apps", "/me/localization"];
|
|
4363
4508
|
function isAuthGateAllowlisted(rawPath) {
|
|
@@ -4376,13 +4521,10 @@ function isAuthGateAllowlisted(rawPath) {
|
|
|
4376
4521
|
return false;
|
|
4377
4522
|
}
|
|
4378
4523
|
function evaluateAuthGate(sessionUser, path) {
|
|
4379
|
-
const gate = sessionUser
|
|
4380
|
-
if (!gate
|
|
4524
|
+
const gate = normalizeAuthGate(sessionUser);
|
|
4525
|
+
if (!gate) return null;
|
|
4381
4526
|
if (isAuthGateAllowlisted(path)) return null;
|
|
4382
|
-
return
|
|
4383
|
-
code: gate.code,
|
|
4384
|
-
message: typeof gate.message === "string" && gate.message ? gate.message : "Access is blocked by an authentication policy."
|
|
4385
|
-
};
|
|
4527
|
+
return gate;
|
|
4386
4528
|
}
|
|
4387
4529
|
|
|
4388
4530
|
// src/security/anonymous-deny.ts
|
|
@@ -4404,6 +4546,17 @@ function shouldDenyAnonymous(input) {
|
|
|
4404
4546
|
return true;
|
|
4405
4547
|
}
|
|
4406
4548
|
|
|
4549
|
+
// src/security/operation-private-keys.ts
|
|
4550
|
+
var OPERATION_PRIVATE_KEY_PREFIX = "__";
|
|
4551
|
+
function withoutOperationPrivateKeys(exec) {
|
|
4552
|
+
const out = {};
|
|
4553
|
+
for (const [key, value] of Object.entries(exec)) {
|
|
4554
|
+
if (key.startsWith(OPERATION_PRIVATE_KEY_PREFIX)) continue;
|
|
4555
|
+
out[key] = value;
|
|
4556
|
+
}
|
|
4557
|
+
return out;
|
|
4558
|
+
}
|
|
4559
|
+
|
|
4407
4560
|
// src/utils/datetime.ts
|
|
4408
4561
|
import { nextUtcCalendarDay, utcInstantMs } from "@objectstack/spec/data";
|
|
4409
4562
|
function calendarPartsInTz(d, tz) {
|
|
@@ -6225,11 +6378,13 @@ export {
|
|
|
6225
6378
|
API_KEY_PREFIX,
|
|
6226
6379
|
CORE_FALLBACK_FACTORIES,
|
|
6227
6380
|
DependencyResolver,
|
|
6381
|
+
ENTRY_EXECUTION_CONTEXT_FIELDS,
|
|
6228
6382
|
HotReloadManager,
|
|
6229
6383
|
LiteKernel,
|
|
6230
6384
|
MigrationJournalRefusal,
|
|
6231
6385
|
MigrationPlanRegistry,
|
|
6232
6386
|
NamespaceResolver,
|
|
6387
|
+
OPERATION_PRIVATE_KEY_PREFIX,
|
|
6233
6388
|
ObjectKernel,
|
|
6234
6389
|
ObjectKernelBase,
|
|
6235
6390
|
ObjectLogger,
|
|
@@ -6251,6 +6406,8 @@ export {
|
|
|
6251
6406
|
ServiceLifecycle,
|
|
6252
6407
|
UnknownFilterTokenError,
|
|
6253
6408
|
UnresolvedFilterTokenError,
|
|
6409
|
+
assembleExecutionContext,
|
|
6410
|
+
assembleExecutionContextOrGuest,
|
|
6254
6411
|
assertInitServiceRequirements,
|
|
6255
6412
|
bucketKeyToCalendarRange,
|
|
6256
6413
|
buildPermissionsFromGrants,
|
|
@@ -6287,6 +6444,7 @@ export {
|
|
|
6287
6444
|
isGrantExpired,
|
|
6288
6445
|
isNode,
|
|
6289
6446
|
nextUtcCalendarDay,
|
|
6447
|
+
normalizeAuthGate,
|
|
6290
6448
|
parseScopes,
|
|
6291
6449
|
parseSignature,
|
|
6292
6450
|
planChunks,
|
|
@@ -6314,6 +6472,7 @@ export {
|
|
|
6314
6472
|
verifyPublisherSignature,
|
|
6315
6473
|
wireAuthoredTranslationSync,
|
|
6316
6474
|
withTransientRetry,
|
|
6475
|
+
withoutOperationPrivateKeys,
|
|
6317
6476
|
zonedDateStartToUtcMs
|
|
6318
6477
|
};
|
|
6319
6478
|
//# sourceMappingURL=index.js.map
|