@objectstack/core 17.0.0 → 17.1.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 +538 -0
- package/dist/index.cjs +383 -50
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +402 -13
- package/dist/index.d.ts +402 -13
- package/dist/index.js +372 -49
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
ADMIN_STANDING_SURFACE: () => ADMIN_STANDING_SURFACE,
|
|
33
34
|
ANONYMOUS_DENY_BODY: () => ANONYMOUS_DENY_BODY,
|
|
34
35
|
ANONYMOUS_DENY_CODE: () => ANONYMOUS_DENY_CODE,
|
|
35
36
|
ANONYMOUS_DENY_MESSAGE: () => ANONYMOUS_DENY_MESSAGE,
|
|
@@ -65,8 +66,11 @@ __export(index_exports, {
|
|
|
65
66
|
SecurePluginContext: () => SecurePluginContext,
|
|
66
67
|
SemanticVersionManager: () => SemanticVersionManager,
|
|
67
68
|
ServiceLifecycle: () => ServiceLifecycle,
|
|
69
|
+
UNMATCHED_ROUTE_PATTERN: () => import_contracts.UNMATCHED_ROUTE_PATTERN,
|
|
68
70
|
UnknownFilterTokenError: () => UnknownFilterTokenError,
|
|
69
71
|
UnresolvedFilterTokenError: () => UnresolvedFilterTokenError,
|
|
72
|
+
adminStandingColumns: () => adminStandingColumns,
|
|
73
|
+
adminStandingTables: () => adminStandingTables,
|
|
70
74
|
assembleExecutionContext: () => assembleExecutionContext,
|
|
71
75
|
assembleExecutionContextOrGuest: () => assembleExecutionContextOrGuest,
|
|
72
76
|
assertInitServiceRequirements: () => assertInitServiceRequirements,
|
|
@@ -91,6 +95,7 @@ __export(index_exports, {
|
|
|
91
95
|
defaultIsTransientError: () => defaultIsTransientError,
|
|
92
96
|
derivePosture: () => derivePosture,
|
|
93
97
|
describeInitOrderFault: () => describeInitOrderFault,
|
|
98
|
+
effectiveTenancyPosture: () => effectiveTenancyPosture,
|
|
94
99
|
engineCanRollBack: () => engineCanRollBack,
|
|
95
100
|
evaluateAuthGate: () => evaluateAuthGate,
|
|
96
101
|
extractApiKey: () => extractApiKey,
|
|
@@ -108,6 +113,8 @@ __export(index_exports, {
|
|
|
108
113
|
isGrantActive: () => isGrantActive,
|
|
109
114
|
isGrantExpired: () => isGrantExpired,
|
|
110
115
|
isNode: () => isNode,
|
|
116
|
+
isRowActive: () => isRowActive,
|
|
117
|
+
isUninterpretableTemporalComparand: () => isUninterpretableTemporalComparand,
|
|
111
118
|
nextUtcCalendarDay: () => import_data.nextUtcCalendarDay,
|
|
112
119
|
normalizeAuthGate: () => normalizeAuthGate,
|
|
113
120
|
omitInternalFieldsFromWriteResponse: () => omitInternalFieldsFromWriteResponse,
|
|
@@ -118,6 +125,7 @@ __export(index_exports, {
|
|
|
118
125
|
readAuthoredTranslationLayer: () => readAuthoredTranslationLayer,
|
|
119
126
|
readRunJournal: () => readRunJournal,
|
|
120
127
|
recordNotFoundError: () => recordNotFoundError,
|
|
128
|
+
resolveApiKeyAdmission: () => resolveApiKeyAdmission,
|
|
121
129
|
resolveApiKeyPrincipal: () => resolveApiKeyPrincipal,
|
|
122
130
|
resolveAuthzContext: () => resolveAuthzContext,
|
|
123
131
|
resolveFilterToken: () => resolveFilterToken,
|
|
@@ -131,6 +139,7 @@ __export(index_exports, {
|
|
|
131
139
|
safeExit: () => safeExit,
|
|
132
140
|
shouldDenyAnonymous: () => shouldDenyAnonymous,
|
|
133
141
|
signPayload: () => signPayload,
|
|
142
|
+
temporalComparandKind: () => temporalComparandKind,
|
|
134
143
|
unknownAudienceBindingSuggestionStatusMessage: () => unknownAudienceBindingSuggestionStatusMessage,
|
|
135
144
|
utcInstantMs: () => import_data.utcInstantMs,
|
|
136
145
|
validateInitServiceContract: () => validateInitServiceContract,
|
|
@@ -141,7 +150,8 @@ __export(index_exports, {
|
|
|
141
150
|
wireAuthoredTranslationSync: () => wireAuthoredTranslationSync,
|
|
142
151
|
withTransientRetry: () => withTransientRetry,
|
|
143
152
|
withoutOperationPrivateKeys: () => withoutOperationPrivateKeys,
|
|
144
|
-
zonedDateStartToUtcMs: () => zonedDateStartToUtcMs
|
|
153
|
+
zonedDateStartToUtcMs: () => zonedDateStartToUtcMs,
|
|
154
|
+
zonedWallClockToUtcMs: () => zonedWallClockToUtcMs
|
|
145
155
|
});
|
|
146
156
|
module.exports = __toCommonJS(index_exports);
|
|
147
157
|
|
|
@@ -1876,6 +1886,26 @@ var CORE_FALLBACK_FACTORIES = {
|
|
|
1876
1886
|
i18n: createMemoryI18n
|
|
1877
1887
|
};
|
|
1878
1888
|
|
|
1889
|
+
// src/plugin-registration.ts
|
|
1890
|
+
function versionLabel(plugin) {
|
|
1891
|
+
return plugin.version ? `v${plugin.version}` : "unversioned";
|
|
1892
|
+
}
|
|
1893
|
+
function describeSupersededRegistration(previous, next) {
|
|
1894
|
+
return `Plugin superseded: '${next.name}' \u2014 the later registration (${versionLabel(next)}) REPLACED the earlier one (${versionLabel(previous)}). Only the later instance is initialized and started; the earlier one is discarded without ever running init(). Duplicate registration by name is last-one-wins on both kernels by declared contract (#9864) \u2014 register the plugin once if that is not what you meant.`;
|
|
1895
|
+
}
|
|
1896
|
+
function registerPluginByName(registry, plugin, logger) {
|
|
1897
|
+
const previous = registry.get(plugin.name);
|
|
1898
|
+
if (previous !== void 0) {
|
|
1899
|
+
logger.warn(describeSupersededRegistration(previous, plugin), {
|
|
1900
|
+
plugin: plugin.name,
|
|
1901
|
+
supersededVersion: previous.version,
|
|
1902
|
+
supersedingVersion: plugin.version
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
registry.set(plugin.name, plugin);
|
|
1906
|
+
return previous;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1879
1909
|
// src/kernel.ts
|
|
1880
1910
|
var ObjectKernel = class {
|
|
1881
1911
|
constructor(config = {}) {
|
|
@@ -1960,6 +1990,14 @@ var ObjectKernel = class {
|
|
|
1960
1990
|
}
|
|
1961
1991
|
/**
|
|
1962
1992
|
* Register a plugin with enhanced validation
|
|
1993
|
+
*
|
|
1994
|
+
* Duplicate names OVERWRITE, with one `warn` naming both versions — the
|
|
1995
|
+
* declared contract in `plugin-registration.ts`, applied identically by
|
|
1996
|
+
* `LiteKernel.use()` (#9864, maintainer ruling 2026-08-19). The overwrite
|
|
1997
|
+
* itself is unchanged: it is what lets an app config's `plugins` entry
|
|
1998
|
+
* supersede a plugin the CLI auto-registered earlier in the same boot
|
|
1999
|
+
* (#9863). What changes is that it is no longer silent, and no longer
|
|
2000
|
+
* disagrees with the other kernel.
|
|
1963
2001
|
*/
|
|
1964
2002
|
async use(plugin) {
|
|
1965
2003
|
if (this.state !== "idle") {
|
|
@@ -1970,11 +2008,13 @@ var ObjectKernel = class {
|
|
|
1970
2008
|
throw new Error(`Failed to load plugin: ${plugin.name} - ${result.error?.message}`);
|
|
1971
2009
|
}
|
|
1972
2010
|
const pluginMeta = result.plugin;
|
|
1973
|
-
this.plugins
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
2011
|
+
const superseded = registerPluginByName(this.plugins, pluginMeta, this.logger);
|
|
2012
|
+
if (superseded === void 0) {
|
|
2013
|
+
this.logger.info(`Plugin registered: ${pluginMeta.name}@${pluginMeta.version}`, {
|
|
2014
|
+
plugin: pluginMeta.name,
|
|
2015
|
+
version: pluginMeta.version
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
1978
2018
|
return this;
|
|
1979
2019
|
}
|
|
1980
2020
|
/**
|
|
@@ -2452,14 +2492,21 @@ var LiteKernel = class extends ObjectKernelBase {
|
|
|
2452
2492
|
/**
|
|
2453
2493
|
* Register a plugin
|
|
2454
2494
|
* @param plugin - Plugin instance
|
|
2495
|
+
*
|
|
2496
|
+
* Duplicate names OVERWRITE, with one `warn` naming both versions — the
|
|
2497
|
+
* declared contract in `plugin-registration.ts`, applied identically by
|
|
2498
|
+
* `ObjectKernel.use()` (#9864, maintainer ruling 2026-08-19).
|
|
2499
|
+
*
|
|
2500
|
+
* This method used to `throw` `[Kernel] Plugin '<name>' already
|
|
2501
|
+
* registered` here while `ObjectKernel` overwrote silently, so one input
|
|
2502
|
+
* had two meanings depending on which kernel was running — and the kernel
|
|
2503
|
+
* that runs in production was the silent one. The ruling converged them on
|
|
2504
|
+
* the behaviour that already works (an app config superseding a plugin the
|
|
2505
|
+
* CLI auto-registered, #9863) and made it audible rather than removing it.
|
|
2455
2506
|
*/
|
|
2456
2507
|
use(plugin) {
|
|
2457
2508
|
this.validateIdle();
|
|
2458
|
-
|
|
2459
|
-
if (this.plugins.has(pluginName)) {
|
|
2460
|
-
throw new Error(`[Kernel] Plugin '${pluginName}' already registered`);
|
|
2461
|
-
}
|
|
2462
|
-
this.plugins.set(pluginName, plugin);
|
|
2509
|
+
registerPluginByName(this.plugins, plugin, this.logger);
|
|
2463
2510
|
return this;
|
|
2464
2511
|
}
|
|
2465
2512
|
/**
|
|
@@ -2709,27 +2756,117 @@ var TestRunner = class {
|
|
|
2709
2756
|
|
|
2710
2757
|
// src/qa/http-adapter.ts
|
|
2711
2758
|
var import_api = require("@objectstack/spec/api");
|
|
2712
|
-
var
|
|
2713
|
-
function
|
|
2714
|
-
if (
|
|
2759
|
+
var conventionCache;
|
|
2760
|
+
function conventionMounts() {
|
|
2761
|
+
if (conventionCache === void 0) {
|
|
2715
2762
|
const api = import_api.RestApiConfigSchema.parse({});
|
|
2716
2763
|
const crud = import_api.CrudEndpointsConfigSchema.parse({});
|
|
2717
|
-
|
|
2764
|
+
const apiBase = api.apiPath ?? `${api.basePath}/${api.version}`;
|
|
2765
|
+
conventionCache = { apiBase, dataPath: `${apiBase}${crud.dataPrefix}` };
|
|
2718
2766
|
}
|
|
2719
|
-
return
|
|
2767
|
+
return conventionCache;
|
|
2720
2768
|
}
|
|
2721
2769
|
var HttpTestAdapter = class {
|
|
2722
2770
|
constructor(baseUrl, authToken) {
|
|
2723
2771
|
this.baseUrl = baseUrl;
|
|
2724
2772
|
this.authToken = authToken;
|
|
2725
2773
|
}
|
|
2726
|
-
/**
|
|
2727
|
-
|
|
2728
|
-
|
|
2774
|
+
/** The resolved data mount; probes at most once per adapter. */
|
|
2775
|
+
dataMount() {
|
|
2776
|
+
if (this.mountPromise === void 0) {
|
|
2777
|
+
this.mountPromise = this.resolveDataMount();
|
|
2778
|
+
}
|
|
2779
|
+
return this.mountPromise;
|
|
2780
|
+
}
|
|
2781
|
+
/**
|
|
2782
|
+
* Ask the server where it serves the Data Protocol, and fall back to the
|
|
2783
|
+
* convention — loudly — when it cannot say.
|
|
2784
|
+
*
|
|
2785
|
+
* ## [#7983] What the probe recovers, measured rather than assumed
|
|
2786
|
+
*
|
|
2787
|
+
* `@objectstack/client` answers the same question through discovery
|
|
2788
|
+
* (`getRoute`, `packages/client/src/index.ts`), and this follows it: prefer
|
|
2789
|
+
* the server's own `routes.data`, fall back to the convention. Measured on a
|
|
2790
|
+
* booted stack (REST generator + dispatcher bridge, three configs):
|
|
2791
|
+
*
|
|
2792
|
+
* | deployment | `{apiBase}/discovery` | serves |
|
|
2793
|
+
* |--------------------------------|-----------------------|---------------|
|
|
2794
|
+
* | stock | 200 `/api/v1/data` | `/api/v1/data`|
|
|
2795
|
+
* | `crud.dataPrefix: '/objects'` | 200 `/api/v1/objects` | `/api/v1/objects` |
|
|
2796
|
+
* | `api.apiPath: '/api/2026-01'` | **404** | `/api/2026-01/data` |
|
|
2797
|
+
*
|
|
2798
|
+
* So the probe closes the `dataPrefix` row exactly: `RestServer`'s discovery
|
|
2799
|
+
* handler substitutes the configured prefix into `routes.data`, and reading
|
|
2800
|
+
* it is strictly better than recomputing it here. The `apiPath` row it cannot
|
|
2801
|
+
* close, and the reason is structural rather than an oversight — `apiPath`
|
|
2802
|
+
* moves the base that discovery itself is mounted under, so the document that
|
|
2803
|
+
* would name the new mount is behind the very prefix we are missing.
|
|
2804
|
+
*
|
|
2805
|
+
* ⛔ And the one discovery document at a FIXED path does not rescue it:
|
|
2806
|
+
* `/.well-known/objectstack` is mounted at the site root by the dispatcher
|
|
2807
|
+
* bridge, but its `routes.data` is the DISPATCHER's own `${prefix}/data` —
|
|
2808
|
+
* measured as `/api/v1/data` under all three configs above, including the two
|
|
2809
|
+
* where the server serves elsewhere. Falling back to it would turn "we could
|
|
2810
|
+
* not resolve the mount" into "discovery told us `/api/v1/data`": the same
|
|
2811
|
+
* 404, now with a false provenance attached. Not probed, deliberately.
|
|
2812
|
+
*
|
|
2813
|
+
* Hence: one probe, then a diagnostic that NAMES the mount, the evidence and
|
|
2814
|
+
* the remedy. `api_call` takes the path it is given and is unaffected either
|
|
2815
|
+
* way — it stays the escape hatch for a host this cannot reach.
|
|
2816
|
+
*/
|
|
2817
|
+
async resolveDataMount() {
|
|
2818
|
+
const { apiBase, dataPath } = conventionMounts();
|
|
2819
|
+
const probeUrl = `${this.baseUrl}${apiBase}/discovery`;
|
|
2820
|
+
let why;
|
|
2821
|
+
try {
|
|
2822
|
+
const headers = {};
|
|
2823
|
+
if (this.authToken) {
|
|
2824
|
+
headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
2825
|
+
}
|
|
2826
|
+
const response = await fetch(probeUrl, { method: "GET", headers });
|
|
2827
|
+
if (response.ok) {
|
|
2828
|
+
const body = await response.json();
|
|
2829
|
+
const doc = body && typeof body === "object" && "routes" in body ? body : body?.data;
|
|
2830
|
+
const advertised = doc?.routes?.data;
|
|
2831
|
+
if (typeof advertised === "string" && advertised.length > 0) {
|
|
2832
|
+
return {
|
|
2833
|
+
path: advertised,
|
|
2834
|
+
source: "discovery",
|
|
2835
|
+
why: `GET ${probeUrl} advertised routes.data`
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
why = `GET ${probeUrl} answered ${response.status} but carried no routes.data`;
|
|
2839
|
+
} else {
|
|
2840
|
+
why = `GET ${probeUrl} answered ${response.status}`;
|
|
2841
|
+
}
|
|
2842
|
+
} catch (error) {
|
|
2843
|
+
why = `GET ${probeUrl} could not be reached (${error.message})`;
|
|
2844
|
+
}
|
|
2845
|
+
const mount = { path: dataPath, source: "convention", why };
|
|
2846
|
+
console.warn(
|
|
2847
|
+
`[HttpTestAdapter] Data Protocol mount NOT resolved from discovery. Record actions (create_record, read_record, update_record, delete_record, query_records) will address ${this.baseUrl}${dataPath}, the convention declared by RestApiConfigSchema (apiPath ?? basePath/version) + CrudEndpointsConfigSchema.dataPrefix. Evidence: ${why}. A deployment that sets crud.dataPrefix is normally recovered by this probe; one that sets api.apiPath moves discovery itself out from under it, and no fixed-path document reports the REST mount \u2014 write those steps as api_call, which takes the path you give it.`
|
|
2848
|
+
);
|
|
2849
|
+
return mount;
|
|
2850
|
+
}
|
|
2851
|
+
/** `{baseUrl}{dataMount}/{object}` — the collection URL. */
|
|
2852
|
+
collectionUrl(mount, objectName) {
|
|
2853
|
+
return `${this.baseUrl}${mount.path}/${encodeURIComponent(objectName)}`;
|
|
2729
2854
|
}
|
|
2730
2855
|
/** `{collection}/{id}` — the single-record URL. */
|
|
2731
|
-
recordUrl(objectName, id) {
|
|
2732
|
-
return `${this.collectionUrl(objectName)}/${encodeURIComponent(String(id))}`;
|
|
2856
|
+
recordUrl(mount, objectName, id) {
|
|
2857
|
+
return `${this.collectionUrl(mount, objectName)}/${encodeURIComponent(String(id))}`;
|
|
2858
|
+
}
|
|
2859
|
+
/**
|
|
2860
|
+
* The provenance clause appended to a failed record action's error.
|
|
2861
|
+
*
|
|
2862
|
+
* The card this closes is about a 404 that reads like the author's own URL
|
|
2863
|
+
* mistake; the mount is the one fact that distinguishes the two, so it rides
|
|
2864
|
+
* on the failure itself rather than only on a warning printed earlier in the
|
|
2865
|
+
* transcript.
|
|
2866
|
+
*/
|
|
2867
|
+
mountNote(mount) {
|
|
2868
|
+
const how = mount.source === "discovery" ? "resolved from discovery" : "assumed by convention \u2014 the server was not able to state it";
|
|
2869
|
+
return `record actions addressed ${this.baseUrl}${mount.path} (data mount ${how}: ${mount.why})`;
|
|
2733
2870
|
}
|
|
2734
2871
|
async execute(action, _context) {
|
|
2735
2872
|
const headers = {
|
|
@@ -2762,48 +2899,53 @@ var HttpTestAdapter = class {
|
|
|
2762
2899
|
}
|
|
2763
2900
|
}
|
|
2764
2901
|
async createRecord(objectName, data, headers) {
|
|
2765
|
-
const
|
|
2902
|
+
const mount = await this.dataMount();
|
|
2903
|
+
const response = await fetch(this.collectionUrl(mount, objectName), {
|
|
2766
2904
|
method: "POST",
|
|
2767
2905
|
headers,
|
|
2768
2906
|
body: JSON.stringify(data)
|
|
2769
2907
|
});
|
|
2770
|
-
return this.handleResponse(response);
|
|
2908
|
+
return this.handleResponse(response, this.mountNote(mount));
|
|
2771
2909
|
}
|
|
2772
2910
|
async updateRecord(objectName, data, headers) {
|
|
2773
2911
|
const { id, ...fields } = data;
|
|
2774
2912
|
if (!id) throw new Error("Update record requires id in payload");
|
|
2775
|
-
const
|
|
2913
|
+
const mount = await this.dataMount();
|
|
2914
|
+
const response = await fetch(this.recordUrl(mount, objectName, id), {
|
|
2776
2915
|
method: "PATCH",
|
|
2777
2916
|
headers,
|
|
2778
2917
|
body: JSON.stringify(fields)
|
|
2779
2918
|
});
|
|
2780
|
-
return this.handleResponse(response);
|
|
2919
|
+
return this.handleResponse(response, this.mountNote(mount));
|
|
2781
2920
|
}
|
|
2782
2921
|
async deleteRecord(objectName, data, headers) {
|
|
2783
2922
|
const id = data.id;
|
|
2784
2923
|
if (!id) throw new Error("Delete record requires id in payload");
|
|
2785
|
-
const
|
|
2924
|
+
const mount = await this.dataMount();
|
|
2925
|
+
const response = await fetch(this.recordUrl(mount, objectName, id), {
|
|
2786
2926
|
method: "DELETE",
|
|
2787
2927
|
headers
|
|
2788
2928
|
});
|
|
2789
|
-
return this.handleResponse(response);
|
|
2929
|
+
return this.handleResponse(response, this.mountNote(mount));
|
|
2790
2930
|
}
|
|
2791
2931
|
async readRecord(objectName, data, headers) {
|
|
2792
2932
|
const id = data.id;
|
|
2793
2933
|
if (!id) throw new Error("Read record requires id in payload");
|
|
2794
|
-
const
|
|
2934
|
+
const mount = await this.dataMount();
|
|
2935
|
+
const response = await fetch(this.recordUrl(mount, objectName, id), {
|
|
2795
2936
|
method: "GET",
|
|
2796
2937
|
headers
|
|
2797
2938
|
});
|
|
2798
|
-
return this.handleResponse(response);
|
|
2939
|
+
return this.handleResponse(response, this.mountNote(mount));
|
|
2799
2940
|
}
|
|
2800
2941
|
async queryRecords(objectName, data, headers) {
|
|
2801
|
-
const
|
|
2942
|
+
const mount = await this.dataMount();
|
|
2943
|
+
const response = await fetch(`${this.collectionUrl(mount, objectName)}/query`, {
|
|
2802
2944
|
method: "POST",
|
|
2803
2945
|
headers,
|
|
2804
2946
|
body: JSON.stringify(data)
|
|
2805
2947
|
});
|
|
2806
|
-
return this.handleResponse(response);
|
|
2948
|
+
return this.handleResponse(response, this.mountNote(mount));
|
|
2807
2949
|
}
|
|
2808
2950
|
async rawApiCall(endpoint, data, headers) {
|
|
2809
2951
|
const method = data.method || "GET";
|
|
@@ -2816,10 +2958,13 @@ var HttpTestAdapter = class {
|
|
|
2816
2958
|
});
|
|
2817
2959
|
return this.handleResponse(response);
|
|
2818
2960
|
}
|
|
2819
|
-
async handleResponse(response) {
|
|
2961
|
+
async handleResponse(response, mountNote) {
|
|
2820
2962
|
if (!response.ok) {
|
|
2821
2963
|
const text = await response.text();
|
|
2822
|
-
|
|
2964
|
+
const wrongUrlShaped = response.status === 404 || response.status === 405;
|
|
2965
|
+
throw new Error(
|
|
2966
|
+
`HTTP Error ${response.status}: ${text}${wrongUrlShaped && mountNote ? ` \u2014 ${mountNote}` : ""}`
|
|
2967
|
+
);
|
|
2823
2968
|
}
|
|
2824
2969
|
const contentType = response.headers.get("content-type");
|
|
2825
2970
|
if (contentType && contentType.includes("application/json")) {
|
|
@@ -4161,6 +4306,7 @@ var PluginSecurityScanner = class {
|
|
|
4161
4306
|
|
|
4162
4307
|
// src/security/api-key.ts
|
|
4163
4308
|
var import_node_crypto2 = require("crypto");
|
|
4309
|
+
var import_security = require("@objectstack/spec/security");
|
|
4164
4310
|
var API_KEY_PREFIX = "osk_";
|
|
4165
4311
|
var API_KEY_ENTROPY_BYTES = 32;
|
|
4166
4312
|
var VISIBLE_PREFIX_LEN = 12;
|
|
@@ -4214,10 +4360,18 @@ function isExpired(value, nowMs) {
|
|
|
4214
4360
|
if (Number.isNaN(ms)) return false;
|
|
4215
4361
|
return ms <= nowMs;
|
|
4216
4362
|
}
|
|
4217
|
-
|
|
4363
|
+
function effectiveTenancyPosture(tenancy) {
|
|
4364
|
+
if (!tenancy) return void 0;
|
|
4365
|
+
return (0, import_security.normalizeTenancyPosture)(tenancy.posture) ?? (tenancy.isolationActive ? "isolated" : "single");
|
|
4366
|
+
}
|
|
4367
|
+
async function resolveApiKeyPrincipal(ql, headers, nowMs = Date.now(), tenancyPosture) {
|
|
4368
|
+
const admission = await resolveApiKeyAdmission(ql, headers, nowMs, tenancyPosture);
|
|
4369
|
+
return admission.outcome === "admitted" ? admission.principal : void 0;
|
|
4370
|
+
}
|
|
4371
|
+
async function resolveApiKeyAdmission(ql, headers, nowMs = Date.now(), tenancyPosture) {
|
|
4218
4372
|
const apiKey = extractApiKey(headers);
|
|
4219
|
-
if (!apiKey) return
|
|
4220
|
-
if (!ql || typeof ql.find !== "function") return
|
|
4373
|
+
if (!apiKey) return { outcome: "none" };
|
|
4374
|
+
if (!ql || typeof ql.find !== "function") return { outcome: "none" };
|
|
4221
4375
|
let rows;
|
|
4222
4376
|
try {
|
|
4223
4377
|
rows = await ql.find("sys_api_key", {
|
|
@@ -4226,19 +4380,29 @@ async function resolveApiKeyPrincipal(ql, headers, nowMs = Date.now()) {
|
|
|
4226
4380
|
context: { isSystem: true }
|
|
4227
4381
|
});
|
|
4228
4382
|
} catch {
|
|
4229
|
-
return
|
|
4383
|
+
return { outcome: "none" };
|
|
4230
4384
|
}
|
|
4231
4385
|
if (rows && rows.value) rows = rows.value;
|
|
4232
4386
|
const row = Array.isArray(rows) ? rows[0] : void 0;
|
|
4233
|
-
if (!row || row.revoked === true) return
|
|
4387
|
+
if (!row || row.revoked === true) return { outcome: "none" };
|
|
4234
4388
|
const expiresAt = row.expires_at ?? row.expiresAt;
|
|
4235
|
-
if (isExpired(expiresAt, nowMs)) return
|
|
4389
|
+
if (isExpired(expiresAt, nowMs)) return { outcome: "none" };
|
|
4236
4390
|
const userId = row.user_id ?? row.userId;
|
|
4237
|
-
if (!userId || typeof userId !== "string") return
|
|
4391
|
+
if (!userId || typeof userId !== "string") return { outcome: "none" };
|
|
4392
|
+
const tenantId = typeof row.active_organization_id === "string" && row.active_organization_id ? row.active_organization_id : void 0;
|
|
4393
|
+
if (!tenantId && tenancyPosture) {
|
|
4394
|
+
const posture = tenancyPosture;
|
|
4395
|
+
if ((0, import_security.postureEnforcesWall)(posture) && !(0, import_security.postureUsesUnionScope)(posture)) {
|
|
4396
|
+
return {
|
|
4397
|
+
outcome: "refused",
|
|
4398
|
+
reason: "organization_required",
|
|
4399
|
+
message: "This API key carries no organization and cannot be used under the `isolated` tenancy posture, where every organization-scoped read is walled to an active organization. Mint a replacement key \u2014 new keys inherit the minter\u2019s active organization."
|
|
4400
|
+
};
|
|
4401
|
+
}
|
|
4402
|
+
}
|
|
4238
4403
|
return {
|
|
4239
|
-
|
|
4240
|
-
|
|
4241
|
-
scopes: parseScopes(row.scopes)
|
|
4404
|
+
outcome: "admitted",
|
|
4405
|
+
principal: { userId, tenantId, scopes: parseScopes(row.scopes) }
|
|
4242
4406
|
};
|
|
4243
4407
|
}
|
|
4244
4408
|
function readHeader(headers, name) {
|
|
@@ -4266,6 +4430,7 @@ function safeJsonParse(s, fallback) {
|
|
|
4266
4430
|
|
|
4267
4431
|
// src/security/resolve-authz-context.ts
|
|
4268
4432
|
var import_spec = require("@objectstack/spec");
|
|
4433
|
+
var import_security2 = require("@objectstack/spec/security");
|
|
4269
4434
|
|
|
4270
4435
|
// src/security/grant-validity.ts
|
|
4271
4436
|
function toEpochMs(value) {
|
|
@@ -4348,6 +4513,15 @@ function postureVisibleRows(posture, rows, principal) {
|
|
|
4348
4513
|
}
|
|
4349
4514
|
}
|
|
4350
4515
|
|
|
4516
|
+
// src/security/row-active.ts
|
|
4517
|
+
var DEACTIVATED_VALUES = [false, 0, "0", "false"];
|
|
4518
|
+
function isRowActive(row) {
|
|
4519
|
+
if (!row) return false;
|
|
4520
|
+
const value = row.active;
|
|
4521
|
+
if (value === void 0 || value === null) return true;
|
|
4522
|
+
return !DEACTIVATED_VALUES.includes(value);
|
|
4523
|
+
}
|
|
4524
|
+
|
|
4351
4525
|
// src/security/resolve-authz-context.ts
|
|
4352
4526
|
function safeJsonParse2(s, fallback) {
|
|
4353
4527
|
try {
|
|
@@ -4377,7 +4551,12 @@ async function resolveAuthzContext(input) {
|
|
|
4377
4551
|
};
|
|
4378
4552
|
let userId;
|
|
4379
4553
|
let tenantId;
|
|
4380
|
-
const
|
|
4554
|
+
const admission = await resolveApiKeyAdmission(ql, headers, input.nowMs, input.tenancyPosture);
|
|
4555
|
+
if (admission.outcome === "refused") {
|
|
4556
|
+
ctx.authRefusal = { reason: admission.reason, message: admission.message };
|
|
4557
|
+
return ctx;
|
|
4558
|
+
}
|
|
4559
|
+
const keyPrincipal = admission.outcome === "admitted" ? admission.principal : void 0;
|
|
4381
4560
|
if (keyPrincipal) {
|
|
4382
4561
|
userId = keyPrincipal.userId;
|
|
4383
4562
|
tenantId = keyPrincipal.tenantId;
|
|
@@ -4405,6 +4584,22 @@ async function resolveAuthzContext(input) {
|
|
|
4405
4584
|
seedPermissions: ctx.permissions,
|
|
4406
4585
|
seedEmail: ctx.email
|
|
4407
4586
|
});
|
|
4587
|
+
if (keyPrincipal?.tenantId && input.tenancyPosture) {
|
|
4588
|
+
const posture = input.tenancyPosture;
|
|
4589
|
+
if ((0, import_security2.postureEnforcesWall)(posture) && !grants.accessible_org_ids.includes(keyPrincipal.tenantId)) {
|
|
4590
|
+
return {
|
|
4591
|
+
positions: [],
|
|
4592
|
+
permissions: [],
|
|
4593
|
+
systemPermissions: [],
|
|
4594
|
+
org_user_ids: [],
|
|
4595
|
+
accessible_org_ids: [],
|
|
4596
|
+
authRefusal: {
|
|
4597
|
+
reason: "organization_membership_ended",
|
|
4598
|
+
message: "This API key authenticates into an organization its owner is no longer a member of. The key was not revoked \u2014 the membership that backed it ended."
|
|
4599
|
+
}
|
|
4600
|
+
};
|
|
4601
|
+
}
|
|
4602
|
+
}
|
|
4408
4603
|
ctx.positions = grants.positions;
|
|
4409
4604
|
ctx.permissions = grants.permissions;
|
|
4410
4605
|
ctx.systemPermissions = grants.systemPermissions;
|
|
@@ -4489,7 +4684,13 @@ async function resolveUserAuthzGrants(ql, userId, opts = {}) {
|
|
|
4489
4684
|
if (!grants.positions.includes("everyone")) grants.positions.push("everyone");
|
|
4490
4685
|
if (grants.positions.length > 0) {
|
|
4491
4686
|
const positionRows = await tryFind(ql, "sys_position", { name: { $in: grants.positions } }, 100);
|
|
4492
|
-
const
|
|
4687
|
+
const deactivatedNames = new Set(
|
|
4688
|
+
positionRows.filter((r) => !isRowActive(r)).map((r) => r.name).filter(Boolean)
|
|
4689
|
+
);
|
|
4690
|
+
if (deactivatedNames.size > 0) {
|
|
4691
|
+
grants.positions = grants.positions.filter((n) => !deactivatedNames.has(n));
|
|
4692
|
+
}
|
|
4693
|
+
const positionIds = positionRows.filter((r) => isRowActive(r)).map((r) => r.id).filter(Boolean);
|
|
4493
4694
|
if (positionIds.length > 0) {
|
|
4494
4695
|
const rpsRows = await tryFind(ql, "sys_position_permission_set", { position_id: { $in: positionIds } }, 500);
|
|
4495
4696
|
for (const r of rpsRows) {
|
|
@@ -4499,7 +4700,8 @@ async function resolveUserAuthzGrants(ql, userId, opts = {}) {
|
|
|
4499
4700
|
}
|
|
4500
4701
|
}
|
|
4501
4702
|
if (psIds.size > 0) {
|
|
4502
|
-
const
|
|
4703
|
+
const psRowsAll = await tryFind(ql, "sys_permission_set", { id: { $in: Array.from(psIds) } }, 500);
|
|
4704
|
+
const psRows = psRowsAll.filter((r) => isRowActive(r));
|
|
4503
4705
|
const tabRank = { hidden: 0, default_off: 1, default_on: 2, visible: 3 };
|
|
4504
4706
|
const mergedTabs = {};
|
|
4505
4707
|
for (const ps of psRows) {
|
|
@@ -4730,6 +4932,7 @@ var ANONYMOUS_DENY_CODE = "UNAUTHENTICATED";
|
|
|
4730
4932
|
var ANONYMOUS_DENY_MESSAGE = "Authentication is required to access this endpoint.";
|
|
4731
4933
|
var ANONYMOUS_DENY_BODY = {
|
|
4732
4934
|
error: ANONYMOUS_DENY_CODE,
|
|
4935
|
+
code: ANONYMOUS_DENY_CODE,
|
|
4733
4936
|
message: ANONYMOUS_DENY_MESSAGE
|
|
4734
4937
|
};
|
|
4735
4938
|
function shouldDenyAnonymous(input) {
|
|
@@ -4743,6 +4946,76 @@ function shouldDenyAnonymous(input) {
|
|
|
4743
4946
|
return true;
|
|
4744
4947
|
}
|
|
4745
4948
|
|
|
4949
|
+
// src/security/admin-standing-surface.ts
|
|
4950
|
+
var ADMIN_STANDING_SURFACE = {
|
|
4951
|
+
sys_permission_set: {
|
|
4952
|
+
role: "derives",
|
|
4953
|
+
reason: "The row `platform_admin` is resolved BY NAME from (\xA76b). Renaming it, deleting it or switching it off (ADR-0049 `active`, read here since #8613) un-makes every platform admin at once, with no identity table touched.",
|
|
4954
|
+
columns: [
|
|
4955
|
+
"id",
|
|
4956
|
+
"name",
|
|
4957
|
+
"active",
|
|
4958
|
+
"system_permissions",
|
|
4959
|
+
"systemPermissions",
|
|
4960
|
+
"tab_permissions",
|
|
4961
|
+
"tabPermissions"
|
|
4962
|
+
]
|
|
4963
|
+
},
|
|
4964
|
+
sys_user_permission_set: {
|
|
4965
|
+
role: "derives",
|
|
4966
|
+
reason: "The grant that makes a user a platform admin: an UNSCOPED, in-window (ADR-0091) grant of `admin_full_access` (\xA76). Re-pointing it, scoping it to an organization or moving it out of its window revokes the standing while leaving the row in place.",
|
|
4967
|
+
columns: [
|
|
4968
|
+
"user_id",
|
|
4969
|
+
"permission_set_id",
|
|
4970
|
+
"permissionSetId",
|
|
4971
|
+
"organization_id",
|
|
4972
|
+
"organizationId",
|
|
4973
|
+
"valid_from",
|
|
4974
|
+
"validFrom",
|
|
4975
|
+
"valid_until",
|
|
4976
|
+
"validUntil"
|
|
4977
|
+
]
|
|
4978
|
+
},
|
|
4979
|
+
sys_member: {
|
|
4980
|
+
role: "derives",
|
|
4981
|
+
reason: "Organization owner/admin standing (\xA73). The graded `role` is projected into `positions` here and separately drives the `organization_admin` capability grant, which is what the posture ladder reads; the break-glass guard counts the same rows one step earlier, by grade (ADR-0108). Either way a downgrade of the last graded membership is a write that can empty the administrator population.",
|
|
4982
|
+
columns: [
|
|
4983
|
+
"user_id",
|
|
4984
|
+
"userId",
|
|
4985
|
+
"organization_id",
|
|
4986
|
+
"organizationId",
|
|
4987
|
+
"role",
|
|
4988
|
+
"valid_from",
|
|
4989
|
+
"validFrom",
|
|
4990
|
+
"valid_until",
|
|
4991
|
+
"validUntil"
|
|
4992
|
+
]
|
|
4993
|
+
},
|
|
4994
|
+
sys_user: {
|
|
4995
|
+
role: "reads-only",
|
|
4996
|
+
reason: "Read for the `current_user.email` RLS fallback and the ADR-0024 `ai_seat` synthesis (\xA77). Neither confers administrator standing. The guard does watch this table, but for the ban/delete WRITE SHAPES \u2014 `banned` is never read here, so it is not a derivation column and carries no standing-key list."
|
|
4997
|
+
},
|
|
4998
|
+
sys_user_position: {
|
|
4999
|
+
role: "reads-only",
|
|
5000
|
+
reason: "ADR-0057 D4 platform-RBAC position assignments (\xA74). A position can carry permission sets (see `sys_position_permission_set`) but never platform-admin standing \u2014 \xA76b requires the set to be reached through an unscoped USER grant (`unscopedUserPsIds`), so a position-bound `admin_full_access` resolves the set name into `permissions` and leaves `hasPlatformAdminGrant` false."
|
|
5001
|
+
},
|
|
5002
|
+
sys_position: {
|
|
5003
|
+
role: "reads-only",
|
|
5004
|
+
reason: "Read to drop DEACTIVATED positions (ADR-0049, \xA76a). Same reason as `sys_user_position`: the position path cannot reach `hasPlatformAdminGrant`."
|
|
5005
|
+
},
|
|
5006
|
+
sys_position_permission_set: {
|
|
5007
|
+
role: "reads-only",
|
|
5008
|
+
reason: "Position-bound permission sets (\xA76a). Contributes ids to `psIds` \u2014 and therefore names to `permissions` \u2014 but not to `unscopedUserPsIds`, which is the set \xA76b tests for platform-admin standing."
|
|
5009
|
+
}
|
|
5010
|
+
};
|
|
5011
|
+
function adminStandingTables() {
|
|
5012
|
+
return Object.entries(ADMIN_STANDING_SURFACE).filter(([, t]) => t.role === "derives").map(([name]) => name).sort();
|
|
5013
|
+
}
|
|
5014
|
+
function adminStandingColumns(table) {
|
|
5015
|
+
const entry = ADMIN_STANDING_SURFACE[table];
|
|
5016
|
+
return entry?.role === "derives" ? entry.columns : void 0;
|
|
5017
|
+
}
|
|
5018
|
+
|
|
4746
5019
|
// src/security/audience-binding-suggestion-status.ts
|
|
4747
5020
|
var AUDIENCE_BINDING_SUGGESTION_STATUSES = {
|
|
4748
5021
|
pending: true,
|
|
@@ -4793,10 +5066,26 @@ function calendarPartsInTzOrUtc(d, tz) {
|
|
|
4793
5066
|
}
|
|
4794
5067
|
function zonedDateStartToUtcMs(ymd2, tz) {
|
|
4795
5068
|
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(ymd2);
|
|
4796
|
-
|
|
5069
|
+
if (!m) return NaN;
|
|
5070
|
+
return zonedWallClockToUtcMs(
|
|
5071
|
+
{ year: Number(m[1]), month: Number(m[2]), day: Number(m[3]) },
|
|
5072
|
+
tz
|
|
5073
|
+
);
|
|
5074
|
+
}
|
|
5075
|
+
function zonedWallClockToUtcMs(parts, tz) {
|
|
5076
|
+
const wallAsUtc = Date.UTC(
|
|
5077
|
+
parts.year,
|
|
5078
|
+
parts.month - 1,
|
|
5079
|
+
parts.day,
|
|
5080
|
+
parts.hour ?? 0,
|
|
5081
|
+
parts.minute ?? 0,
|
|
5082
|
+
parts.second ?? 0,
|
|
5083
|
+
parts.millisecond ?? 0
|
|
5084
|
+
);
|
|
4797
5085
|
if (!tz || tz === "UTC" || Number.isNaN(wallAsUtc)) return wallAsUtc;
|
|
4798
5086
|
try {
|
|
4799
5087
|
const offsetAt = (t) => {
|
|
5088
|
+
const whole = Math.floor(t / 1e3) * 1e3;
|
|
4800
5089
|
const p = new Intl.DateTimeFormat("en-US", {
|
|
4801
5090
|
timeZone: tz,
|
|
4802
5091
|
hourCycle: "h23",
|
|
@@ -4806,9 +5095,9 @@ function zonedDateStartToUtcMs(ymd2, tz) {
|
|
|
4806
5095
|
hour: "2-digit",
|
|
4807
5096
|
minute: "2-digit",
|
|
4808
5097
|
second: "2-digit"
|
|
4809
|
-
}).formatToParts(new Date(
|
|
5098
|
+
}).formatToParts(new Date(whole));
|
|
4810
5099
|
const g = (k) => Number(p.find((x) => x.type === k)?.value);
|
|
4811
|
-
return Date.UTC(g("year"), g("month") - 1, g("day"), g("hour"), g("minute"), g("second")) -
|
|
5100
|
+
return Date.UTC(g("year"), g("month") - 1, g("day"), g("hour"), g("minute"), g("second")) - whole;
|
|
4812
5101
|
};
|
|
4813
5102
|
const off1 = offsetAt(wallAsUtc - offsetAt(wallAsUtc));
|
|
4814
5103
|
return wallAsUtc - off1;
|
|
@@ -5619,6 +5908,37 @@ function filterTokenContextFrom(execCtx, now) {
|
|
|
5619
5908
|
};
|
|
5620
5909
|
}
|
|
5621
5910
|
|
|
5911
|
+
// src/utils/temporal-comparand.ts
|
|
5912
|
+
var import_data3 = require("@objectstack/spec/data");
|
|
5913
|
+
function temporalComparandKind(fieldType) {
|
|
5914
|
+
if (fieldType === "datetime") return "datetime";
|
|
5915
|
+
if (fieldType === "date") return "date";
|
|
5916
|
+
if (fieldType === "time") return "time";
|
|
5917
|
+
return null;
|
|
5918
|
+
}
|
|
5919
|
+
function readsAsInstant(s) {
|
|
5920
|
+
if (/^-?\d+$/.test(s)) return Number.isFinite(new Date(Number(s)).getTime());
|
|
5921
|
+
const iso = /^\d{4}-\d{2}-\d{2}$/.test(s) ? `${s}T00:00:00.000Z` : /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2}(\.\d+)?)?$/.test(s) ? `${s.replace(" ", "T")}Z` : s;
|
|
5922
|
+
return Number.isFinite(Date.parse(iso));
|
|
5923
|
+
}
|
|
5924
|
+
function readsAsCalendarDay(s) {
|
|
5925
|
+
return /^\d{4}-\d{2}-\d{2}/.test(s);
|
|
5926
|
+
}
|
|
5927
|
+
function readsAsWallClock(s) {
|
|
5928
|
+
const m = /^(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d+))?)?$/.exec(s);
|
|
5929
|
+
if (!m) return false;
|
|
5930
|
+
return Number(m[1]) <= 23 && Number(m[2]) <= 59 && Number(m[3] ?? "0") <= 59;
|
|
5931
|
+
}
|
|
5932
|
+
function isUninterpretableTemporalComparand(kind, value) {
|
|
5933
|
+
if (typeof value !== "string") return false;
|
|
5934
|
+
const s = value.trim();
|
|
5935
|
+
if (s === "") return false;
|
|
5936
|
+
if ((0, import_data3.classifyFilterToken)(value) !== null) return false;
|
|
5937
|
+
if (kind === "datetime") return !readsAsInstant(s);
|
|
5938
|
+
if (kind === "date") return !readsAsCalendarDay(s);
|
|
5939
|
+
return !(readsAsWallClock(s) || readsAsInstant(s));
|
|
5940
|
+
}
|
|
5941
|
+
|
|
5622
5942
|
// src/utils/record-not-found.ts
|
|
5623
5943
|
function recordNotFoundError(object, id) {
|
|
5624
5944
|
const err = new Error(`Record ${id} not found in ${object}`);
|
|
@@ -6604,8 +6924,12 @@ var NamespaceResolver = class {
|
|
|
6604
6924
|
return `${shortName}_${ns}`;
|
|
6605
6925
|
}
|
|
6606
6926
|
};
|
|
6927
|
+
|
|
6928
|
+
// src/index.ts
|
|
6929
|
+
var import_contracts = require("@objectstack/spec/contracts");
|
|
6607
6930
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6608
6931
|
0 && (module.exports = {
|
|
6932
|
+
ADMIN_STANDING_SURFACE,
|
|
6609
6933
|
ANONYMOUS_DENY_BODY,
|
|
6610
6934
|
ANONYMOUS_DENY_CODE,
|
|
6611
6935
|
ANONYMOUS_DENY_MESSAGE,
|
|
@@ -6641,8 +6965,11 @@ var NamespaceResolver = class {
|
|
|
6641
6965
|
SecurePluginContext,
|
|
6642
6966
|
SemanticVersionManager,
|
|
6643
6967
|
ServiceLifecycle,
|
|
6968
|
+
UNMATCHED_ROUTE_PATTERN,
|
|
6644
6969
|
UnknownFilterTokenError,
|
|
6645
6970
|
UnresolvedFilterTokenError,
|
|
6971
|
+
adminStandingColumns,
|
|
6972
|
+
adminStandingTables,
|
|
6646
6973
|
assembleExecutionContext,
|
|
6647
6974
|
assembleExecutionContextOrGuest,
|
|
6648
6975
|
assertInitServiceRequirements,
|
|
@@ -6667,6 +6994,7 @@ var NamespaceResolver = class {
|
|
|
6667
6994
|
defaultIsTransientError,
|
|
6668
6995
|
derivePosture,
|
|
6669
6996
|
describeInitOrderFault,
|
|
6997
|
+
effectiveTenancyPosture,
|
|
6670
6998
|
engineCanRollBack,
|
|
6671
6999
|
evaluateAuthGate,
|
|
6672
7000
|
extractApiKey,
|
|
@@ -6684,6 +7012,8 @@ var NamespaceResolver = class {
|
|
|
6684
7012
|
isGrantActive,
|
|
6685
7013
|
isGrantExpired,
|
|
6686
7014
|
isNode,
|
|
7015
|
+
isRowActive,
|
|
7016
|
+
isUninterpretableTemporalComparand,
|
|
6687
7017
|
nextUtcCalendarDay,
|
|
6688
7018
|
normalizeAuthGate,
|
|
6689
7019
|
omitInternalFieldsFromWriteResponse,
|
|
@@ -6694,6 +7024,7 @@ var NamespaceResolver = class {
|
|
|
6694
7024
|
readAuthoredTranslationLayer,
|
|
6695
7025
|
readRunJournal,
|
|
6696
7026
|
recordNotFoundError,
|
|
7027
|
+
resolveApiKeyAdmission,
|
|
6697
7028
|
resolveApiKeyPrincipal,
|
|
6698
7029
|
resolveAuthzContext,
|
|
6699
7030
|
resolveFilterToken,
|
|
@@ -6707,6 +7038,7 @@ var NamespaceResolver = class {
|
|
|
6707
7038
|
safeExit,
|
|
6708
7039
|
shouldDenyAnonymous,
|
|
6709
7040
|
signPayload,
|
|
7041
|
+
temporalComparandKind,
|
|
6710
7042
|
unknownAudienceBindingSuggestionStatusMessage,
|
|
6711
7043
|
utcInstantMs,
|
|
6712
7044
|
validateInitServiceContract,
|
|
@@ -6717,6 +7049,7 @@ var NamespaceResolver = class {
|
|
|
6717
7049
|
wireAuthoredTranslationSync,
|
|
6718
7050
|
withTransientRetry,
|
|
6719
7051
|
withoutOperationPrivateKeys,
|
|
6720
|
-
zonedDateStartToUtcMs
|
|
7052
|
+
zonedDateStartToUtcMs,
|
|
7053
|
+
zonedWallClockToUtcMs
|
|
6721
7054
|
});
|
|
6722
7055
|
//# sourceMappingURL=index.cjs.map
|