@objectstack/core 17.3.0 → 17.4.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 +649 -0
- package/dist/index.cjs +251 -246
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +264 -132
- package/dist/index.d.ts +264 -132
- package/dist/index.js +247 -245
- package/dist/index.js.map +1 -1
- package/dist/logger.cjs.map +1 -1
- package/dist/logger.js.map +1 -1
- package/package.json +7 -6
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Logger, LifecycleEventName, IServiceRegistry, AudienceBindingSuggestionFilter, IObjectQLEngine } from '@objectstack/spec/contracts';
|
|
2
2
|
export { EngineSchemaRegistryView, EngineTransactionInfo, EngineTransactionOptions, HttpResponseObservation, HttpResponseObserver, IDataDriver, IDataEngine, IHttpRequest, IHttpResponse, IHttpServer, IObjectQLEngine, Logger, Middleware, RouteHandler, UNMATCHED_ROUTE_PATTERN } from '@objectstack/spec/contracts';
|
|
3
3
|
import { LoggerConfig, MigrationOnCrashPolicy, MigrationJournalEvent } from '@objectstack/spec/system';
|
|
4
|
-
import { CORE_PLUGIN_TYPES, PluginCapability, PluginPermissions as PluginPermissions$1, PluginPermissionSet, ResourceType, PermissionAction, PluginPermission, SandboxConfig,
|
|
4
|
+
import { PluginDefinition, CORE_PLUGIN_TYPES, PluginCapability, PluginPermissions as PluginPermissions$1, PluginPermissionSet, ResourceType, PermissionAction, PluginPermission, SandboxConfig, ExecutionContext, PluginHealthCheckParsed, PluginHealthStatus as PluginHealthStatus$1, PluginHealthReport, HotReloadConfigParsed, VersionConstraint, DependencyConflict, SemanticVersion, CompatibilityLevel } from '@objectstack/spec/kernel';
|
|
5
5
|
import { ObjectLogger } from './logger.cjs';
|
|
6
6
|
export { createLogger } from './logger.cjs';
|
|
7
7
|
import * as QA from '@objectstack/spec/qa';
|
|
@@ -72,6 +72,27 @@ interface PluginLoadResult {
|
|
|
72
72
|
interface PluginStartupResult {
|
|
73
73
|
success: boolean;
|
|
74
74
|
pluginName: string;
|
|
75
|
+
/**
|
|
76
|
+
* Elapsed milliseconds the plugin's `start()` took.
|
|
77
|
+
*
|
|
78
|
+
* Named for the member `packages/spec` declares for the same measure --
|
|
79
|
+
* `PluginStartupResultSchema.durationMs` in
|
|
80
|
+
* `packages/spec/src/kernel/startup-orchestrator.zod.ts` ("Time taken to
|
|
81
|
+
* start the plugin in milliseconds"), where the bare `duration` spelling is
|
|
82
|
+
* retired: a duration-shaped number carries its unit in its key name. Like
|
|
83
|
+
* `PluginLoadResult.loadTime` above, it is the same `Date.now() - startTime`
|
|
84
|
+
* computation under a name that does not lie.
|
|
85
|
+
*/
|
|
86
|
+
durationMs?: number;
|
|
87
|
+
/**
|
|
88
|
+
* The same elapsed milliseconds as {@link PluginStartupResult.durationMs}.
|
|
89
|
+
*
|
|
90
|
+
* @deprecated Misnamed: this has never held an instant, so a reader who
|
|
91
|
+
* correctly takes `startTime` for one and writes `Date.now() - result.startTime`
|
|
92
|
+
* gets an age near the epoch instead of a wait. Read `durationMs` instead.
|
|
93
|
+
* Still populated so nothing has to change on this release (ADR-0087 L1 --
|
|
94
|
+
* the old shape keeps working while the fleet moves); slated for removal.
|
|
95
|
+
*/
|
|
75
96
|
startTime?: number;
|
|
76
97
|
error?: Error;
|
|
77
98
|
timedOut?: boolean;
|
|
@@ -152,6 +173,25 @@ declare class PluginLoader {
|
|
|
152
173
|
getLoadedPlugins(): Map<string, PluginMetadata>;
|
|
153
174
|
private toPluginMetadata;
|
|
154
175
|
private validatePluginStructure;
|
|
176
|
+
/**
|
|
177
|
+
* Refuse a plugin object the DECLARED plugin contract refuses (#16049,
|
|
178
|
+
* maintainer ruling 2026-09-06: "the protocol is the baseline; the runtime
|
|
179
|
+
* aligns to it").
|
|
180
|
+
*
|
|
181
|
+
* The check itself — `PluginSchema.safeParse` for validation only, the
|
|
182
|
+
* eight keys it reaches, the `version` exclusion and the
|
|
183
|
+
* `PLUGIN_CONTRACT_VIOLATION` envelope — lives in `plugin-contract.ts`,
|
|
184
|
+
* because since #16721 it is ONE statement run by BOTH kernels:
|
|
185
|
+
* `LiteKernel.use()` calls it directly, and `ObjectKernel.use()` reaches
|
|
186
|
+
* it here, through `loadPlugin`. That module's comment is the authority on
|
|
187
|
+
* what is refused; this method adds nothing to it and subtracts nothing.
|
|
188
|
+
*
|
|
189
|
+
* What stays THIS loader's own, and is deliberately not shared: the
|
|
190
|
+
* structural checks one call up ({@link validatePluginStructure} —
|
|
191
|
+
* `name`, `init`, semver) and the version-compatibility check below.
|
|
192
|
+
* The convergence is on the schema, not on the loader.
|
|
193
|
+
*/
|
|
194
|
+
private validatePluginContract;
|
|
155
195
|
private checkVersionCompatibility;
|
|
156
196
|
private isValidSemanticVersion;
|
|
157
197
|
private verifyPluginSignature;
|
|
@@ -204,7 +244,12 @@ declare class ObjectKernel {
|
|
|
204
244
|
private pluginLoader;
|
|
205
245
|
private config;
|
|
206
246
|
private startedPlugins;
|
|
207
|
-
|
|
247
|
+
/**
|
|
248
|
+
* Plugin name -> elapsed milliseconds that plugin's `start()` took. These
|
|
249
|
+
* are DURATIONS, never start instants; the old spelling `pluginStartTimes`
|
|
250
|
+
* said the opposite of what it held.
|
|
251
|
+
*/
|
|
252
|
+
private pluginStartupDurations;
|
|
208
253
|
private shutdownHandlers;
|
|
209
254
|
/**
|
|
210
255
|
* Name of the plugin whose init() is currently executing (Phase 1 is
|
|
@@ -244,6 +289,25 @@ declare class ObjectKernel {
|
|
|
244
289
|
* Validate Critical System Requirements
|
|
245
290
|
*/
|
|
246
291
|
private validateSystemRequirements;
|
|
292
|
+
/**
|
|
293
|
+
* Publish this boot's degraded-capabilities conclusion on
|
|
294
|
+
* {@link DEGRADED_CAPABILITIES_SERVICE} — the data half of the warning
|
|
295
|
+
* `validateSystemRequirements()` just logged (#16630).
|
|
296
|
+
*
|
|
297
|
+
* ⛔ Best-effort, and silent on failure BY DESIGN: this is a diagnostic
|
|
298
|
+
* readout, and a readout must never be able to fail a boot that the kernel
|
|
299
|
+
* has just decided is good enough to run. The one way `registerService`
|
|
300
|
+
* can throw here is a name collision, which the guard above already
|
|
301
|
+
* forecloses; the `catch` is there so that stays true if either ever
|
|
302
|
+
* changes. (`recordSeedOutcome` in `@objectstack/runtime` states the same
|
|
303
|
+
* rule for the same reason.)
|
|
304
|
+
*
|
|
305
|
+
* The value is FROZEN and holds a COPY. `getService` hands out the stored
|
|
306
|
+
* reference, so an unfrozen live array would let any reader edit the
|
|
307
|
+
* kernel's own record of what was missing — and this record exists
|
|
308
|
+
* precisely so that two packages cannot disagree about it.
|
|
309
|
+
*/
|
|
310
|
+
private publishDegradedCapabilities;
|
|
247
311
|
/**
|
|
248
312
|
* Bootstrap the kernel with enhanced features
|
|
249
313
|
*/
|
|
@@ -260,8 +324,18 @@ declare class ObjectKernel {
|
|
|
260
324
|
* Check health of all plugins
|
|
261
325
|
*/
|
|
262
326
|
checkAllPluginsHealth(): Promise<Map<string, any>>;
|
|
327
|
+
/**
|
|
328
|
+
* Per-plugin startup durations: plugin name -> elapsed milliseconds that
|
|
329
|
+
* plugin's `start()` took. Not start instants -- see
|
|
330
|
+
* {@link PluginStartupResult.durationMs}.
|
|
331
|
+
*/
|
|
332
|
+
getPluginStartupDurations(): Map<string, number>;
|
|
263
333
|
/**
|
|
264
334
|
* Get plugin startup metrics
|
|
335
|
+
*
|
|
336
|
+
* @deprecated Renamed to {@link ObjectKernel.getPluginStartupDurations},
|
|
337
|
+
* which states what the values are. Retained as a delegating alias so
|
|
338
|
+
* nothing has to change on this release; slated for removal.
|
|
265
339
|
*/
|
|
266
340
|
getPluginMetrics(): Map<string, number>;
|
|
267
341
|
/**
|
|
@@ -474,24 +548,55 @@ type PluginType = 'standard' | (typeof CORE_PLUGIN_TYPES)[number];
|
|
|
474
548
|
* Plugin Interface
|
|
475
549
|
*
|
|
476
550
|
* All ObjectStack plugins must implement this interface.
|
|
477
|
-
|
|
478
|
-
|
|
551
|
+
*
|
|
552
|
+
* ## Two halves, one contract (#16334)
|
|
553
|
+
*
|
|
554
|
+
* **The metadata half is inherited, not restated.** Every key `PluginSchema`
|
|
555
|
+
* declares (`@objectstack/spec`, `kernel/plugin.zod.ts`) — `id`, `type`,
|
|
556
|
+
* `staticPath`, `slug`, `default`, `version`, `description`, `author`,
|
|
557
|
+
* `homepage` — arrives here through `PluginDefinition`
|
|
558
|
+
* (`z.input<typeof PluginSchema>`), so the keys the compiler accepts on a
|
|
559
|
+
* plugin object and the keys `kernel.use()` validates
|
|
560
|
+
* (`PluginLoader.validatePluginContract`, #16049) are ONE declaration. Before
|
|
561
|
+
* this the interface spelled `type` and `version` itself and declared neither
|
|
562
|
+
* `staticPath` nor `slug`, so an in-repo `ui` plugin could not carry the two
|
|
563
|
+
* keys the schema requires of it without widening its own type — two shapes
|
|
564
|
+
* for one contract, free to drift.
|
|
565
|
+
*
|
|
566
|
+
* **The runtime half is declared here and only here**: `name`, the ADR-0116
|
|
567
|
+
* ordering declarations, and the `init` / `start` / `destroy` lifecycle. The
|
|
568
|
+
* spec's schema describes what a plugin OBJECT may say about itself, never
|
|
569
|
+
* what it does.
|
|
570
|
+
*
|
|
571
|
+
* ### `type`
|
|
572
|
+
*
|
|
573
|
+
* The inherited `type` is a {@link PluginType} — the closed set the spec
|
|
574
|
+
* declares (`'standard'` plus `CORE_PLUGIN_TYPES`); `packages/rest`'s
|
|
575
|
+
* `plugin-type-closed-set.pin.test.ts` pins that the inherited key and the
|
|
576
|
+
* exported alias are the same union. Absent means `'standard'` at the schema
|
|
577
|
+
* (`.default('standard')`), and the loader never writes that default back
|
|
578
|
+
* onto the object. A value outside the set no longer type-checks, and since
|
|
579
|
+
* #16049 `kernel.use()` REFUSES it at boot — `assertPluginContract`
|
|
580
|
+
* (`plugin-contract.ts`, run by BOTH `ObjectKernel.use()` and `LiteKernel.use()`
|
|
581
|
+
* since #16721) runs `PluginSchema` over every plugin object and raises
|
|
582
|
+
* `PLUGIN_CONTRACT_VIOLATION` naming the plugin and the first violated key.
|
|
583
|
+
* `type: 'ui'` additionally owes `staticPath` and `slug` (#16334,
|
|
584
|
+
* `PLUGIN_UI_REQUIRED_KEY_MISSING`), refused on the same path.
|
|
585
|
+
*
|
|
586
|
+
* ⚠️ This comment used to say a bad `type` was refused "at parse". It was
|
|
587
|
+
* measured false (#16049, from #15638): `PluginSchema` had no runtime caller,
|
|
588
|
+
* kernel plugin objects were never parsed, and a `type` outside the set was
|
|
589
|
+
* accepted and stored verbatim. The refusal described here is the one that
|
|
590
|
+
* now exists, on the boot path, and the compiler's arm is the second half
|
|
591
|
+
* rather than the only one — `kernel.use(plugin as any)` is a shipped
|
|
592
|
+
* in-repo pattern, and externally authored plugins never meet this compiler
|
|
593
|
+
* at all.
|
|
594
|
+
*/
|
|
595
|
+
interface Plugin extends PluginDefinition {
|
|
479
596
|
/**
|
|
480
597
|
* Unique plugin name (e.g., 'com.objectstack.engine.objectql')
|
|
481
598
|
*/
|
|
482
599
|
name: string;
|
|
483
|
-
/**
|
|
484
|
-
* Plugin version
|
|
485
|
-
*/
|
|
486
|
-
version?: string;
|
|
487
|
-
/**
|
|
488
|
-
* Plugin type categorisation for runtime behaviour — a {@link PluginType},
|
|
489
|
-
* the closed set the spec declares. The enumeration lives on that type
|
|
490
|
-
* (derived from `CORE_PLUGIN_TYPES`), not in this comment: a value outside
|
|
491
|
-
* it no longer type-checks, and `PluginSchema.type` refuses it at parse.
|
|
492
|
-
* @default 'standard'
|
|
493
|
-
*/
|
|
494
|
-
type?: PluginType;
|
|
495
600
|
/**
|
|
496
601
|
* List of other plugin names that this plugin depends on.
|
|
497
602
|
* The kernel ensures these plugins are initialized before this one.
|
|
@@ -864,6 +969,26 @@ declare class LiteKernel extends ObjectKernelBase {
|
|
|
864
969
|
* Register a plugin
|
|
865
970
|
* @param plugin - Plugin instance
|
|
866
971
|
*
|
|
972
|
+
* A plugin object the DECLARED plugin contract refuses is refused here,
|
|
973
|
+
* with `PLUGIN_CONTRACT_VIOLATION` — the same check, the same envelope,
|
|
974
|
+
* that `ObjectKernel.use()` runs through `PluginLoader` (`plugin-contract.ts`
|
|
975
|
+
* is the one statement both kernels call; #16721, maintainer ruling
|
|
976
|
+
* 2026-09-08, option A under #9864's precedent that the kernels converge).
|
|
977
|
+
*
|
|
978
|
+
* This method used to write the object straight into the registry, so the
|
|
979
|
+
* same plugin was accepted by this kernel and refused by `ObjectKernel` —
|
|
980
|
+
* and `AGENTS.md` names THIS kernel for tests, so a plugin could be green
|
|
981
|
+
* in vitest and refused at production boot. Measured before converging
|
|
982
|
+
* (#16721 step 1): of 813 `LiteKernel.use()` calls reachable in this
|
|
983
|
+
* repository's suites, 807 were accepted by the schema unchanged and the
|
|
984
|
+
* six refusals came from three test-local fixture objects, none of them
|
|
985
|
+
* product code.
|
|
986
|
+
*
|
|
987
|
+
* Ordering, and why it is pinned: state first (`validateIdle`), then the
|
|
988
|
+
* contract, then registration — a refused plugin never reaches the
|
|
989
|
+
* registry, so it can neither be booted nor supersede an earlier
|
|
990
|
+
* registration under its name.
|
|
991
|
+
*
|
|
867
992
|
* Duplicate names OVERWRITE, with one `warn` naming both versions — the
|
|
868
993
|
* declared contract in `plugin-registration.ts`, applied identically by
|
|
869
994
|
* `ObjectKernel.use()` (#9864, maintainer ruling 2026-08-19).
|
|
@@ -1755,96 +1880,6 @@ declare class PluginSandboxRuntime {
|
|
|
1755
1880
|
shutdown(): void;
|
|
1756
1881
|
}
|
|
1757
1882
|
|
|
1758
|
-
/**
|
|
1759
|
-
* Scan Target
|
|
1760
|
-
*/
|
|
1761
|
-
interface ScanTarget {
|
|
1762
|
-
pluginId: string;
|
|
1763
|
-
version: string;
|
|
1764
|
-
files?: string[];
|
|
1765
|
-
dependencies?: Record<string, string>;
|
|
1766
|
-
}
|
|
1767
|
-
/**
|
|
1768
|
-
* Security Issue
|
|
1769
|
-
*/
|
|
1770
|
-
interface SecurityIssue {
|
|
1771
|
-
id: string;
|
|
1772
|
-
severity: 'critical' | 'high' | 'medium' | 'low' | 'info';
|
|
1773
|
-
category: 'vulnerability' | 'malware' | 'license' | 'code-quality' | 'configuration';
|
|
1774
|
-
title: string;
|
|
1775
|
-
description: string;
|
|
1776
|
-
location?: {
|
|
1777
|
-
file?: string;
|
|
1778
|
-
line?: number;
|
|
1779
|
-
column?: number;
|
|
1780
|
-
};
|
|
1781
|
-
remediation?: string;
|
|
1782
|
-
cve?: string;
|
|
1783
|
-
cvss?: number;
|
|
1784
|
-
}
|
|
1785
|
-
/**
|
|
1786
|
-
* Plugin Security Scanner
|
|
1787
|
-
*
|
|
1788
|
-
* Scans plugins for security vulnerabilities, malware, and license issues
|
|
1789
|
-
*/
|
|
1790
|
-
declare class PluginSecurityScanner {
|
|
1791
|
-
private logger;
|
|
1792
|
-
private vulnerabilityDb;
|
|
1793
|
-
private scanResults;
|
|
1794
|
-
private passThreshold;
|
|
1795
|
-
constructor(logger: ObjectLogger, config?: {
|
|
1796
|
-
passThreshold?: number;
|
|
1797
|
-
});
|
|
1798
|
-
/**
|
|
1799
|
-
* Perform a comprehensive security scan on a plugin
|
|
1800
|
-
*/
|
|
1801
|
-
scan(target: ScanTarget): Promise<KernelSecurityScanResult>;
|
|
1802
|
-
/**
|
|
1803
|
-
* Scan code for vulnerabilities
|
|
1804
|
-
*/
|
|
1805
|
-
private scanCode;
|
|
1806
|
-
/**
|
|
1807
|
-
* Scan dependencies for known vulnerabilities
|
|
1808
|
-
*/
|
|
1809
|
-
private scanDependencies;
|
|
1810
|
-
/**
|
|
1811
|
-
* Scan for malware patterns
|
|
1812
|
-
*/
|
|
1813
|
-
private scanMalware;
|
|
1814
|
-
/**
|
|
1815
|
-
* Check license compliance
|
|
1816
|
-
*/
|
|
1817
|
-
private scanLicenses;
|
|
1818
|
-
/**
|
|
1819
|
-
* Check configuration security
|
|
1820
|
-
*/
|
|
1821
|
-
private scanConfiguration;
|
|
1822
|
-
/**
|
|
1823
|
-
* Calculate security score based on issues
|
|
1824
|
-
*/
|
|
1825
|
-
private calculateSecurityScore;
|
|
1826
|
-
/**
|
|
1827
|
-
* Add a vulnerability to the database
|
|
1828
|
-
*/
|
|
1829
|
-
addVulnerability(packageName: string, version: string, vulnerability: KernelSecurityVulnerability): void;
|
|
1830
|
-
/**
|
|
1831
|
-
* Get scan result from cache
|
|
1832
|
-
*/
|
|
1833
|
-
getScanResult(pluginId: string, version: string): KernelSecurityScanResult | undefined;
|
|
1834
|
-
/**
|
|
1835
|
-
* Clear scan results cache
|
|
1836
|
-
*/
|
|
1837
|
-
clearCache(): void;
|
|
1838
|
-
/**
|
|
1839
|
-
* Update vulnerability database from external source
|
|
1840
|
-
*/
|
|
1841
|
-
updateVulnerabilityDatabase(): Promise<void>;
|
|
1842
|
-
/**
|
|
1843
|
-
* Shutdown security scanner
|
|
1844
|
-
*/
|
|
1845
|
-
shutdown(): void;
|
|
1846
|
-
}
|
|
1847
|
-
|
|
1848
1883
|
/** Default visible prefix for generated keys (helps users identify a key). */
|
|
1849
1884
|
declare const API_KEY_PREFIX = "osk_";
|
|
1850
1885
|
/**
|
|
@@ -1888,6 +1923,21 @@ declare function isExpired(value: unknown, nowMs: number): boolean;
|
|
|
1888
1923
|
/** The principal resolved from a valid `sys_api_key`. */
|
|
1889
1924
|
interface ApiKeyPrincipal {
|
|
1890
1925
|
userId: string;
|
|
1926
|
+
/**
|
|
1927
|
+
* [#15256 / 2A] The `sys_api_key` ROW id — a non-secret handle an operator
|
|
1928
|
+
* can look the credential up by. Carried so the posture-conditional refusal
|
|
1929
|
+
* log in `resolve-authz-context.ts` can name WHICH key was refused without
|
|
1930
|
+
* naming the credential.
|
|
1931
|
+
*
|
|
1932
|
+
* ⛔ Never the raw key and never its hash: the raw key is returned exactly
|
|
1933
|
+
* once by {@link generateApiKey} and only `sha256(raw)` is ever stored, and
|
|
1934
|
+
* neither may enter a log line (see this module's SECURITY header). The row
|
|
1935
|
+
* id is not derived from either.
|
|
1936
|
+
*
|
|
1937
|
+
* Optional because a row is only required to identify its owner; a store
|
|
1938
|
+
* that answers without an `id` still yields a usable principal.
|
|
1939
|
+
*/
|
|
1940
|
+
keyId?: string;
|
|
1891
1941
|
/**
|
|
1892
1942
|
* The organization this key authenticates INTO — read from the row's
|
|
1893
1943
|
* `active_organization_id` and adopted by `resolveAuthzContext` as the
|
|
@@ -1926,6 +1976,19 @@ type ApiKeyAdmission = {
|
|
|
1926
1976
|
outcome: 'refused';
|
|
1927
1977
|
reason: ApiKeyRefusalReason;
|
|
1928
1978
|
message: string;
|
|
1979
|
+
/**
|
|
1980
|
+
* [#15256 / 2A] The refused key's `sys_api_key` row id — same non-secret
|
|
1981
|
+
* handle as {@link ApiKeyPrincipal.keyId}, carried on this arm too so the
|
|
1982
|
+
* refusal log can name the credential the operator must go look at. ⛔
|
|
1983
|
+
* Never the raw key or its hash. The WIRE answer is unchanged (a generic
|
|
1984
|
+
* `401 UNAUTHENTICATED`, no reason and no id), so nothing here reaches a
|
|
1985
|
+
* caller holding someone else's key.
|
|
1986
|
+
*/
|
|
1987
|
+
keyId?: string;
|
|
1988
|
+
/** The owner this refused key authenticates as — for the same log line. */
|
|
1989
|
+
userId?: string;
|
|
1990
|
+
/** The organization the refusal is about, when the key names one. */
|
|
1991
|
+
organizationId?: string;
|
|
1929
1992
|
};
|
|
1930
1993
|
/**
|
|
1931
1994
|
* The shape of the kernel's `tenancy` service this module reads a posture from.
|
|
@@ -2029,13 +2092,13 @@ declare function resolveApiKeyAdmission(ql: any, headers: any, nowMs?: number, t
|
|
|
2029
2092
|
* ## Why a THROW, and not a field on the envelope
|
|
2030
2093
|
*
|
|
2031
2094
|
* The alternative was a discriminator field on `ResolvedAuthzContext` — the
|
|
2032
|
-
* shape `authRefusal`
|
|
2033
|
-
* preference:
|
|
2034
|
-
*
|
|
2035
|
-
*
|
|
2036
|
-
*
|
|
2037
|
-
*
|
|
2038
|
-
*
|
|
2095
|
+
* shape `authRefusal` had (#8287). That was rejected on a MEASUREMENT, not a
|
|
2096
|
+
* preference: from #8287 until #14273 removed it, `authRefusal` had **zero**
|
|
2097
|
+
* consumers anywhere in the repo outside this module and test assertions — a
|
|
2098
|
+
* reading #14273 acted on by deleting the field. Every transport reads `userId`
|
|
2099
|
+
* and `systemPermissions`; a new sibling field would have to be taught to eight
|
|
2100
|
+
* separate call sites before it made a single door louder, and would answer
|
|
2101
|
+
* the old quiet 403 at every site that was missed.
|
|
2039
2102
|
*
|
|
2040
2103
|
* A field is quiet by default and must be deliberately made loud. A throw is
|
|
2041
2104
|
* loud by default and must be deliberately silenced. On a security surface
|
|
@@ -2168,6 +2231,15 @@ declare function rethrowAuthzStoreUnavailable(err: unknown): undefined;
|
|
|
2168
2231
|
/** The transport-agnostic authorization envelope produced from a request. */
|
|
2169
2232
|
interface ResolvedAuthzContext {
|
|
2170
2233
|
userId?: string;
|
|
2234
|
+
/**
|
|
2235
|
+
* The ACTIVE organization this request operates in.
|
|
2236
|
+
*
|
|
2237
|
+
* ⚠️ [#15409] For a session principal under a wall-enforcing posture this is
|
|
2238
|
+
* a VETTED value, never the stored `activeOrganizationId` as read: a claim
|
|
2239
|
+
* that is not in {@link accessible_org_ids} is dropped and the context
|
|
2240
|
+
* resolves with no active organization at all. Absent here is the fail-closed
|
|
2241
|
+
* state, not a missing lookup — Layer 0 denies on it.
|
|
2242
|
+
*/
|
|
2171
2243
|
tenantId?: string;
|
|
2172
2244
|
email?: string;
|
|
2173
2245
|
accessToken?: string;
|
|
@@ -2197,24 +2269,6 @@ interface ResolvedAuthzContext {
|
|
|
2197
2269
|
* anonymous requests carry no rung.
|
|
2198
2270
|
*/
|
|
2199
2271
|
posture?: AuthzPosture;
|
|
2200
|
-
/**
|
|
2201
|
-
* [#8287] Set when an inbound API key was REFUSED — a real, intact
|
|
2202
|
-
* credential this deployment's tenancy posture cannot admit. The context is
|
|
2203
|
-
* otherwise EMPTY (no `userId`), so every transport already fails it closed
|
|
2204
|
-
* to 401 with no change; this field only lets a transport that wants to say
|
|
2205
|
-
* WHY do so, instead of answering the operator with a bare "unauthenticated"
|
|
2206
|
-
* for a key they can see is neither revoked nor expired.
|
|
2207
|
-
*
|
|
2208
|
-
* ⚠️ `reason` is NOT an `error.code`. The wire vocabulary is closed
|
|
2209
|
-
* (ADR-0112: `StandardErrorCode ∪ ERROR_CODE_LEDGER`, both in `packages/spec`)
|
|
2210
|
-
* and a refused credential's standard member is `UNAUTHENTICATED`. This is a
|
|
2211
|
-
* diagnostic discriminator for the message, deliberately lowercase so it can
|
|
2212
|
-
* never be mistaken for one.
|
|
2213
|
-
*/
|
|
2214
|
-
authRefusal?: {
|
|
2215
|
-
reason: ApiKeyRefusalReason;
|
|
2216
|
-
message: string;
|
|
2217
|
-
};
|
|
2218
2272
|
}
|
|
2219
2273
|
interface ResolveAuthzInput {
|
|
2220
2274
|
/** Data engine (ObjectQL) exposing `find(object, { where, limit, context })`. */
|
|
@@ -4108,6 +4162,71 @@ declare function runMigrationJournal(engine: IObjectQLEngine, plan: MigrationPla
|
|
|
4108
4162
|
/** Resume a run the journal says was interrupted. Thin alias for intent at call sites. */
|
|
4109
4163
|
declare function resumeMigrationJournal(engine: IObjectQLEngine, plan: MigrationPlan, runId: string, options?: Omit<RunMigrationJournalOptions, 'runId'>): Promise<MigrationRunResult>;
|
|
4110
4164
|
|
|
4165
|
+
/** Example row references a group carries, so the summary can point at real rows. */
|
|
4166
|
+
declare const ADVISORY_SAMPLE_ROWS = 5;
|
|
4167
|
+
/** One advisory rule hit, as the evaluator reports it. */
|
|
4168
|
+
interface AdvisoryHit {
|
|
4169
|
+
/** Object the row belongs to. */
|
|
4170
|
+
object: string;
|
|
4171
|
+
/** The declared rule's `name`. */
|
|
4172
|
+
rule: string;
|
|
4173
|
+
/** The rule's declared severity — `'warning'` or `'info'`; never `'error'`. */
|
|
4174
|
+
severity: string;
|
|
4175
|
+
/** The rule's author-written message, in the caller's locale. */
|
|
4176
|
+
message: string;
|
|
4177
|
+
/**
|
|
4178
|
+
* A reference to the row, when the write carries one.
|
|
4179
|
+
*
|
|
4180
|
+
* NOT necessarily an id: on the path this exists for — a seed INSERT — the
|
|
4181
|
+
* driver has not issued an id yet at validation time, so an id-only reference
|
|
4182
|
+
* would be empty for exactly the case the aggregation was built for. The
|
|
4183
|
+
* producer sends the best stable handle it has (`id`, else `name=<value>`,
|
|
4184
|
+
* the same way the seed loader names a row in its own errors).
|
|
4185
|
+
*/
|
|
4186
|
+
recordRef?: string;
|
|
4187
|
+
}
|
|
4188
|
+
/** Every hit for one `(object, rule)` pair, folded. */
|
|
4189
|
+
interface AdvisoryGroup {
|
|
4190
|
+
object: string;
|
|
4191
|
+
rule: string;
|
|
4192
|
+
severity: string;
|
|
4193
|
+
/** The first message seen for this group (they differ only by interpolation). */
|
|
4194
|
+
message: string;
|
|
4195
|
+
/** How many ROWS tripped this rule during the scope. */
|
|
4196
|
+
rows: number;
|
|
4197
|
+
/** Up to {@link ADVISORY_SAMPLE_ROWS} example row references. */
|
|
4198
|
+
sampleRows: string[];
|
|
4199
|
+
}
|
|
4200
|
+
/**
|
|
4201
|
+
* Offer one advisory hit to the active aggregation scope.
|
|
4202
|
+
*
|
|
4203
|
+
* @returns `true` when a scope captured it — the caller must then NOT log its
|
|
4204
|
+
* own per-row line, because the scope owner reports the whole group. `false`
|
|
4205
|
+
* when no scope is active, which is the ordinary interactive case: the caller
|
|
4206
|
+
* logs exactly as it always did. A caller that ignores the return value
|
|
4207
|
+
* degrades to today's behaviour rather than losing the report.
|
|
4208
|
+
*/
|
|
4209
|
+
declare function recordAdvisoryHit(hit: AdvisoryHit): boolean;
|
|
4210
|
+
/**
|
|
4211
|
+
* Whether an advisory aggregation scope is active on this async context.
|
|
4212
|
+
*
|
|
4213
|
+
* Exported for tests and for a caller that wants to skip building a message it
|
|
4214
|
+
* is about to discard; {@link recordAdvisoryHit}'s return value is the one that
|
|
4215
|
+
* decides.
|
|
4216
|
+
*/
|
|
4217
|
+
declare function isAggregatingAdvisories(): boolean;
|
|
4218
|
+
/**
|
|
4219
|
+
* Run `fn` with advisory hits aggregated, then hand the folded groups to
|
|
4220
|
+
* `report`.
|
|
4221
|
+
*
|
|
4222
|
+
* `report` runs in a `finally`, so a load that throws still reports what it
|
|
4223
|
+
* tripped before failing — the diagnostics of a half-finished seed are the ones
|
|
4224
|
+
* most worth having. It is called only when there is something to report, and
|
|
4225
|
+
* its own failure is never allowed to replace the caller's outcome: a reporting
|
|
4226
|
+
* bug must not turn a successful seed load into a failed one.
|
|
4227
|
+
*/
|
|
4228
|
+
declare function runWithAdvisoryAggregation<T>(fn: () => Promise<T>, report: (groups: AdvisoryGroup[]) => void): Promise<T>;
|
|
4229
|
+
|
|
4111
4230
|
/**
|
|
4112
4231
|
* The slice of an execution context the resolver reads. Structural on purpose —
|
|
4113
4232
|
* see {@link filterTokenContextFrom}.
|
|
@@ -4633,6 +4752,19 @@ declare function createMemoryI18n(): {
|
|
|
4633
4752
|
setSupportedLocales(locales: readonly string[] | undefined): void;
|
|
4634
4753
|
getDefaultLocale(): string;
|
|
4635
4754
|
setDefaultLocale(locale: string): void;
|
|
4755
|
+
/**
|
|
4756
|
+
* @see II18nService.setFallbackLocale — [#15694]
|
|
4757
|
+
*
|
|
4758
|
+
* ⛔ There is deliberately NO `getFallbackLocale()` beside this. The two
|
|
4759
|
+
* are different questions: this one is what the provider was TOLD, the
|
|
4760
|
+
* accessor is what the serving layer ASKS it in order to build the
|
|
4761
|
+
* metadata-document translators' fallback chain (#14882). Answering the
|
|
4762
|
+
* second from `defaultLocale` — the only value that was always available
|
|
4763
|
+
* here — would settle the default-locale contract question #14882 leaves
|
|
4764
|
+
* deliberately open, from a degraded provider. Without the accessor those
|
|
4765
|
+
* reads keep the resolvers' own default, which is known and intentional.
|
|
4766
|
+
*/
|
|
4767
|
+
setFallbackLocale(locale: string): void;
|
|
4636
4768
|
};
|
|
4637
4769
|
|
|
4638
4770
|
/**
|
|
@@ -5133,4 +5265,4 @@ declare class NamespaceResolver {
|
|
|
5133
5265
|
private suggestAlternative;
|
|
5134
5266
|
}
|
|
5135
5267
|
|
|
5136
|
-
export { ADMIN_STANDING_NON_TABLE_INPUTS, ADMIN_STANDING_SURFACE, ANONYMOUS_DENY_BODY, ANONYMOUS_DENY_CODE, ANONYMOUS_DENY_MESSAGE, ANONYMOUS_DENY_STATUS, API_KEY_PREFIX, AUDIENCE_BINDING_SUGGESTION_STATUSES, AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES, AUTHZ_GRANTS_CACHE_TTL_ENV, AUTHZ_INVALIDATED_CHANNEL, AUTHZ_STORE_UNAVAILABLE_CODE, AUTHZ_STORE_UNAVAILABLE_MESSAGE, AUTHZ_STORE_UNAVAILABLE_STATUS, type ActivatableRow, type AdminStandingNonTableInput, type AdminStandingTable, type AnonymousDenyInput, type ApiKeyAdmission, type ApiKeyPrincipal, type ApiKeyRefusalReason, type ArtifactPackageError, type AudienceBindingSuggestionStatus, type AuthGate, type AuthzCachePosture, type AuthzCachePostureInput, type AuthzCachePostureStatement, type AuthzGrantsCacheTtlReading, type AuthzInvalidatedPayload, type AuthzInvalidationBusState, type AuthzInvalidationReason, type AuthzPostureSink, AuthzStoreUnavailableError, type BucketGranularity, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, ENTRY_EXECUTION_CONTEXT_FIELDS, type EngineWithTransaction, type EntryExecutionContextField, type EntryLocalization, type ExecutionContextAssemblyInput, type ExecutionContextEntryFields, type ExecutionContextLike, type FilterTokenResolutionContext, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, InMemoryMetadataActivationStore, type IntegrityFile, type IntegrityViolation, type IntegrityViolationKind, type InterruptedRun, type KernelState, type KeyInput, type LadderPrincipal, type LadderRow, LiteKernel, METADATA_ACTIVATION_TABLE, type MetadataActivationRow, type MetadataActivationStore, type MetadataActivationStoreEngine, type MigrationChunk, type MigrationChunkContext, MigrationJournalRefusal, type MigrationPlan, type MigrationPlanProvider, MigrationPlanRegistry, type MigrationPlanStep, type MigrationRunResult, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, type OAuthTokenProvenance, OPERATION_PRIVATE_KEY_PREFIX, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, ObjectStoreMetadataActivationStore, type OrderablePlugin, PLATFORM_ADMIN_EMAIL_SEPARATOR, POSTURE_INJECTION_RULE, POSTURE_LADDER, POSTURE_RANK, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type PlatformAdminConfigSink, type PlatformAdminEmailConfig, type Plugin, type PluginArtifactVerifyResult, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime,
|
|
5268
|
+
export { ADMIN_STANDING_NON_TABLE_INPUTS, ADMIN_STANDING_SURFACE, ADVISORY_SAMPLE_ROWS, ANONYMOUS_DENY_BODY, ANONYMOUS_DENY_CODE, ANONYMOUS_DENY_MESSAGE, ANONYMOUS_DENY_STATUS, API_KEY_PREFIX, AUDIENCE_BINDING_SUGGESTION_STATUSES, AUDIENCE_BINDING_SUGGESTION_STATUS_VALUES, AUTHZ_GRANTS_CACHE_TTL_ENV, AUTHZ_INVALIDATED_CHANNEL, AUTHZ_STORE_UNAVAILABLE_CODE, AUTHZ_STORE_UNAVAILABLE_MESSAGE, AUTHZ_STORE_UNAVAILABLE_STATUS, type ActivatableRow, type AdminStandingNonTableInput, type AdminStandingTable, type AdvisoryGroup, type AdvisoryHit, type AnonymousDenyInput, type ApiKeyAdmission, type ApiKeyPrincipal, type ApiKeyRefusalReason, type ArtifactPackageError, type AudienceBindingSuggestionStatus, type AuthGate, type AuthzCachePosture, type AuthzCachePostureInput, type AuthzCachePostureStatement, type AuthzGrantsCacheTtlReading, type AuthzInvalidatedPayload, type AuthzInvalidationBusState, type AuthzInvalidationReason, type AuthzPostureSink, AuthzStoreUnavailableError, type BucketGranularity, type BulkWriteOptions, type BulkWriteRowResult, CORE_FALLBACK_FACTORIES, type CalendarParts, DependencyResolver, ENTRY_EXECUTION_CONTEXT_FIELDS, type EngineWithTransaction, type EntryExecutionContextField, type EntryLocalization, type ExecutionContextAssemblyInput, type ExecutionContextEntryFields, type ExecutionContextLike, type FilterTokenResolutionContext, type GeneratedApiKey, type GrantValidityWindow, HotReloadManager, InMemoryMetadataActivationStore, type IntegrityFile, type IntegrityViolation, type IntegrityViolationKind, type InterruptedRun, type KernelState, type KeyInput, type LadderPrincipal, type LadderRow, LiteKernel, METADATA_ACTIVATION_TABLE, type MetadataActivationRow, type MetadataActivationStore, type MetadataActivationStoreEngine, type MigrationChunk, type MigrationChunkContext, MigrationJournalRefusal, type MigrationPlan, type MigrationPlanProvider, MigrationPlanRegistry, type MigrationPlanStep, type MigrationRunResult, type NamespaceCheckResult, type NamespaceConflict, type NamespaceEntry, NamespaceResolver, type OAuthTokenProvenance, OPERATION_PRIVATE_KEY_PREFIX, ObjectKernel, ObjectKernelBase, type ObjectKernelConfig, ObjectLogger, ObjectStoreMetadataActivationStore, type OrderablePlugin, PLATFORM_ADMIN_EMAIL_SEPARATOR, POSTURE_INJECTION_RULE, POSTURE_LADDER, POSTURE_RANK, type ParsedSignature, type PermissionCheckResult$1 as PermissionCheckResult, type PermissionGrant, type PlatformAdminConfigSink, type PlatformAdminEmailConfig, type Plugin, type PluginArtifactVerifyResult, type PluginContext, PluginHealthMonitor, type PluginHealthStatus, type PluginLoadResult, PluginLoader, type PluginMetadata, type PermissionCheckResult as PluginPermissionCheckResult, PluginPermissionEnforcer, PluginPermissionManager, type PluginPermissions, PluginSandboxRuntime, type PluginSignatureConfig, PluginSignatureVerifier, type PluginStartupResult, type PluginType, type PostureEvidence, type PublisherVerifyResult, index as QA, type ResolveAuthzInput, type ResolveLocalizationInput, type ResolveUserAuthzGrantsOptions, type ResolvedAuthzContext, type ResourceUsage, type RetryOptions, type RunMigrationJournalOptions, SERVICE_NOT_REGISTERED_CODE, SIGNATURE_ALG, type SandboxContext, SecurePluginContext, SemanticVersionManager, type ServiceFactory, ServiceLifecycle, type ServiceRegistration, type SignatureVerificationResult, type TemporalComparandKind, type TenancyPostureSource, UnknownFilterTokenError, UnresolvedFilterTokenError, type UserAuthzGrants, type VerifyIntegrityResult, type VersionCompatibility, type WallClockParts, adminStandingColumns, adminStandingTables, artifactPackageId, assembleExecutionContext, assembleExecutionContextOrGuest, assertInitServiceRequirements, assertMetadataRegisterContract, bucketKeyToCalendarRange, buildPermissionsFromGrants, bulkWrite, calendarPartsInTz, calendarPartsInTzOrUtc, canonicalMetadataServiceType, collectInternalWriteResponseFields, counterSignPayload, createMemoryCache, createMemoryI18n, createMemoryJob, createMemoryMetadata, createMemoryQueue, createPluginPermissionEnforcer, deepMerge, defaultIsTransientError, derivePosture, describeInitOrderFault, effectiveTenancyPosture, engineCanRollBack, evaluateAuthGate, extractApiKey, filterTokenContextFrom, findInterruptedRuns, formatIntegrityViolation, generateApiKey, generateEd25519KeyPair, getEnv, getMemoryUsage, hasPlatformAdminStanding, hashApiKey, hashMigrationPlan, isAggregatingAdvisories, isAudienceBindingSuggestionStatus, isAuthGateAllowlisted, isAuthzStoreUnavailableError, isConfiguredPlatformAdminEmail, isExpired, isGrantActive, isGrantExpired, isNode, isRowActive, isServiceNotRegisteredError, isUninterpretableTemporalComparand, matchesConfiguredPlatformAdmin, normalizeAuthGate, normalizePlatformAdminEmail, omitInternalFieldsFromWriteResponse, parsePlatformAdminEmails, parseScopes, parseSignature, planChunks, postureVisibleRows, readAuthoredTranslationLayer, readAuthzGrantsCacheTtlMs, readRunJournal, recordAdvisoryHit, recordNotFoundError, reportAuthzCachePosture, reportLegacyPlatformAdminGrant, resetLegacyPlatformAdminGrantReport, resetPlatformAdminEmailMemo, resolveApiKeyAdmission, resolveApiKeyPrincipal, resolveArtifactPackageOrder, resolveAuthzCachePosture, resolveAuthzContext, resolveFilterToken, resolveFilterTokens, resolveLocale, resolveLocalizationContext, resolvePlatformAdminEmails, resolvePluginOrder, resolveUserAuthzGrants, resumeMigrationJournal, rethrowAuthzStoreUnavailable, runMigrationJournal, runWithAdvisoryAggregation, safeExit, setPlatformAdminConfigSink, shouldDenyAnonymous, signPayload, temporalComparandKind, unknownAudienceBindingSuggestionStatusMessage, validateInitServiceContract, verifyIntegrity, verifyPayload, verifyPlatformSignature, verifyPluginArtifact, verifyPublisherSignature, wireAuthoredTranslationSync, withTransientRetry, withoutOperationPrivateKeys, zonedDateStartToUtcMs, zonedWallClockToUtcMs };
|