@objectstack/runtime 7.9.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +522 -2211
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +114 -657
- package/dist/index.d.ts +114 -657
- package/dist/index.js +518 -2186
- package/dist/index.js.map +1 -1
- package/package.json +18 -18
package/dist/index.d.ts
CHANGED
|
@@ -6,12 +6,11 @@ import { ClusterCapabilityConfigInput, ExecutionContext } from '@objectstack/spe
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import * as Contracts from '@objectstack/spec/contracts';
|
|
8
8
|
import { ISeedLoaderService, IDataEngine, IMetadataService } from '@objectstack/spec/contracts';
|
|
9
|
-
import { SeedLoaderRequest, SeedLoaderResult, ObjectDependencyGraph,
|
|
9
|
+
import { SeedLoaderRequest, SeedLoaderResult, ObjectDependencyGraph, Seed, SeedLoaderConfigInput, ExpressionBody, ScriptBody, HookBody, Hook } from '@objectstack/spec/data';
|
|
10
10
|
import { SchemaDiffEntry } from '@objectstack/spec/shared';
|
|
11
11
|
import { MetricsRegistry, ErrorReporter } from '@objectstack/observability';
|
|
12
12
|
export { CapturedError, ErrorReporter, InMemoryErrorReporter, InMemoryMetricsRegistry, MetricSample, MetricsRegistry, NoopErrorReporter, NoopMetricsRegistry, OBSERVABILITY_ERRORS_SERVICE, OBSERVABILITY_METRICS_SERVICE, RUNTIME_METRICS } from '@objectstack/observability';
|
|
13
13
|
import { MiddlewareConfig, MiddlewareType } from '@objectstack/spec/system';
|
|
14
|
-
import { EnvironmentArtifact } from '@objectstack/spec/cloud';
|
|
15
14
|
export { RestApiPluginConfig, RestServer, RouteEntry, RouteGroupBuilder, RouteManager, createRestApiPlugin } from '@objectstack/rest';
|
|
16
15
|
export { _resetEnvDeprecationWarnings, readEnvWithDeprecation } from '@objectstack/types';
|
|
17
16
|
|
|
@@ -316,7 +315,7 @@ interface Logger {
|
|
|
316
315
|
* - Topological dependency ordering (parents before children)
|
|
317
316
|
* - Multi-pass loading for circular references
|
|
318
317
|
* - Dry-run validation mode
|
|
319
|
-
* - Upsert support honoring
|
|
318
|
+
* - Upsert support honoring SeedSchema mode
|
|
320
319
|
* - Actionable error reporting
|
|
321
320
|
*/
|
|
322
321
|
declare class SeedLoaderService implements ISeedLoaderService {
|
|
@@ -326,7 +325,7 @@ declare class SeedLoaderService implements ISeedLoaderService {
|
|
|
326
325
|
constructor(engine: IDataEngine, metadata: IMetadataService, logger: Logger);
|
|
327
326
|
load(request: SeedLoaderRequest): Promise<SeedLoaderResult>;
|
|
328
327
|
buildDependencyGraph(objectNames: string[]): Promise<ObjectDependencyGraph>;
|
|
329
|
-
validate(datasets:
|
|
328
|
+
validate(datasets: Seed[], config?: SeedLoaderConfigInput): Promise<SeedLoaderResult>;
|
|
330
329
|
private loadDataset;
|
|
331
330
|
private resolveFromDatabase;
|
|
332
331
|
private resolveDeferredUpdates;
|
|
@@ -893,97 +892,54 @@ declare class HttpServer implements IHttpServer {
|
|
|
893
892
|
}
|
|
894
893
|
|
|
895
894
|
/**
|
|
896
|
-
*
|
|
895
|
+
* Per-project driver registry contract.
|
|
896
|
+
*
|
|
897
|
+
* Resolves a project (by hostname or ID) and produces an instantiated
|
|
898
|
+
* `IDataDriver` bound to that project's physical database. Concrete
|
|
899
|
+
* implementations sit on top of either:
|
|
900
|
+
* - the ObjectStack Cloud HTTP API (see {@link ArtifactEnvironmentRegistry})
|
|
901
|
+
* - a local file artifact (see {@link FileArtifactApiClient} +
|
|
902
|
+
* {@link ArtifactEnvironmentRegistry})
|
|
897
903
|
*
|
|
898
|
-
*
|
|
899
|
-
*
|
|
900
|
-
*
|
|
901
|
-
* 3. Return a **bootstrapped** kernel ready to serve requests.
|
|
904
|
+
* The contract lives in `@objectstack/runtime` so the runtime can
|
|
905
|
+
* express "fetch artifact + boot per-project kernel" without taking a
|
|
906
|
+
* dependency on the cloud control plane.
|
|
902
907
|
*/
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
}
|
|
906
|
-
interface KernelManagerConfig {
|
|
907
|
-
factory: EnvironmentKernelFactory;
|
|
908
|
-
/** Maximum number of kernels to keep resident. Defaults to 32. */
|
|
909
|
-
maxSize?: number;
|
|
910
|
-
/**
|
|
911
|
-
* Time-to-live (ms). Kernels idle longer than this are evicted on next
|
|
912
|
-
* access. `0` disables TTL expiry. Defaults to 15 minutes.
|
|
913
|
-
*/
|
|
914
|
-
ttlMs?: number;
|
|
915
|
-
/**
|
|
916
|
-
* Optional logger (duck-typed). Falls back to `console` when omitted.
|
|
917
|
-
*/
|
|
918
|
-
logger?: {
|
|
919
|
-
info?: (...a: any[]) => void;
|
|
920
|
-
warn?: (...a: any[]) => void;
|
|
921
|
-
error?: (...a: any[]) => void;
|
|
922
|
-
};
|
|
923
|
-
/**
|
|
924
|
-
* Optional upstream-change detector. When set, every cache hit older
|
|
925
|
-
* than `staleCheckIntervalMs` triggers this probe before returning the
|
|
926
|
-
* cached kernel. Returning `true` evicts the kernel and forces a
|
|
927
|
-
* rebuild, so changes to the control-plane state that don't reach
|
|
928
|
-
* this process via push (marketplace installs, artifact republish,
|
|
929
|
-
* etc.) become visible without waiting for the LRU TTL to expire.
|
|
930
|
-
*
|
|
931
|
-
* The probe should be cheap (single small GET). Errors thrown here
|
|
932
|
-
* are caught and treated as "still fresh" so a brief upstream
|
|
933
|
-
* outage doesn't churn every cached kernel — the worst case is
|
|
934
|
-
* stale-by-`ttlMs`, which is what we had before adding the probe.
|
|
935
|
-
*
|
|
936
|
-
* `builtAtMs` is the kernel's `createdAt` time so the probe can
|
|
937
|
-
* compare against an upstream "last changed at" timestamp.
|
|
938
|
-
*/
|
|
939
|
-
freshnessProbe?: (environmentId: string, builtAtMs: number) => Promise<boolean>;
|
|
940
|
-
/**
|
|
941
|
-
* Minimum gap between successive freshness probes for the same env.
|
|
942
|
-
* Defaults to 10 seconds — enough to avoid hammering the control
|
|
943
|
-
* plane on tight render loops while still keeping the user's
|
|
944
|
-
* post-install refresh perceived as immediate.
|
|
945
|
-
*/
|
|
946
|
-
staleCheckIntervalMs?: number;
|
|
947
|
-
}
|
|
908
|
+
|
|
909
|
+
type IDataDriver = Contracts.IDataDriver;
|
|
948
910
|
/**
|
|
949
|
-
*
|
|
911
|
+
* Multi-tenant kernel router contract.
|
|
950
912
|
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
953
|
-
*
|
|
954
|
-
*
|
|
955
|
-
*
|
|
913
|
+
* The HTTP dispatcher uses this optional seam to resolve a per-environment
|
|
914
|
+
* kernel when serving a multi-tenant runtime. The framework only depends on
|
|
915
|
+
* the *interface* — the concrete LRU/TTL implementation (and everything else
|
|
916
|
+
* multi-tenant: hostname resolution, artifact fetching, per-env kernel
|
|
917
|
+
* construction) lives in the cloud distribution
|
|
918
|
+
* (`@objectstack/objectos-runtime`), not here.
|
|
956
919
|
*/
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
private readonly maxSize;
|
|
960
|
-
private readonly ttlMs;
|
|
961
|
-
private readonly logger;
|
|
962
|
-
private readonly cache;
|
|
963
|
-
private readonly pending;
|
|
964
|
-
private readonly freshnessProbe?;
|
|
965
|
-
private readonly staleCheckIntervalMs;
|
|
966
|
-
constructor(config: KernelManagerConfig);
|
|
967
|
-
/** Returns the currently cached environmentIds (ordered by insertion). */
|
|
968
|
-
keys(): string[];
|
|
969
|
-
/** Cache size for diagnostics. */
|
|
970
|
-
get size(): number;
|
|
971
|
-
/**
|
|
972
|
-
* Resolve or construct the kernel for `environmentId`.
|
|
973
|
-
*
|
|
974
|
-
* - Cache hit (fresh): bumps `lastAccess` and returns immediately.
|
|
975
|
-
* - Cache hit (TTL expired): evicts then falls through to factory.
|
|
976
|
-
* - Cache miss: dedupes concurrent callers through `pending`.
|
|
977
|
-
*/
|
|
920
|
+
interface KernelManager {
|
|
921
|
+
/** Resolve (building + caching on first use) the kernel for an environment. */
|
|
978
922
|
getOrCreate(environmentId: string): Promise<ObjectKernel>;
|
|
923
|
+
}
|
|
924
|
+
interface EnvironmentDriverRegistry {
|
|
925
|
+
/** Resolve a project by hostname. Returns `null` when unknown. */
|
|
926
|
+
resolveByHostname(host: string): Promise<{
|
|
927
|
+
environmentId: string;
|
|
928
|
+
driver: IDataDriver;
|
|
929
|
+
} | null>;
|
|
930
|
+
/** Resolve a project's driver by ID. Returns `null` when unknown. */
|
|
931
|
+
resolveById(environmentId: string): Promise<IDataDriver | null>;
|
|
979
932
|
/**
|
|
980
|
-
*
|
|
981
|
-
*
|
|
933
|
+
* Look up the cached project row + driver by ID without triggering a
|
|
934
|
+
* remote/file fetch. Returns the full cached entry when fresh.
|
|
982
935
|
*/
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
936
|
+
peekById(environmentId: string): {
|
|
937
|
+
environmentId: string;
|
|
938
|
+
driver: IDataDriver;
|
|
939
|
+
project: any;
|
|
940
|
+
} | null;
|
|
941
|
+
/** Drop cached entries for the given project. */
|
|
942
|
+
invalidate(environmentId: string): void;
|
|
987
943
|
}
|
|
988
944
|
|
|
989
945
|
/** Minimal local interface — full EnvironmentScopeManager was removed in Phase R. */
|
|
@@ -1083,6 +1039,62 @@ declare class HttpDispatcher {
|
|
|
1083
1039
|
* @param scopeId - Optional project ID for scoped service resolution (SharedProjectPlugin mode)
|
|
1084
1040
|
*/
|
|
1085
1041
|
private callData;
|
|
1042
|
+
/**
|
|
1043
|
+
* Handle an MCP request over the Streamable HTTP transport (`/mcp`).
|
|
1044
|
+
*
|
|
1045
|
+
* Gating + auth (fail-closed):
|
|
1046
|
+
* - **opt-in**: only served when `OS_MCP_SERVER_ENABLED=true` (single-env
|
|
1047
|
+
* runtime). Multi-tenant cloud overrides this gate per env. When off we
|
|
1048
|
+
* return 404 so the surface isn't advertised.
|
|
1049
|
+
* - **auth**: requires a principal already resolved by
|
|
1050
|
+
* `resolveExecutionContext` (the `sys_api_key` Bearer/header path or a
|
|
1051
|
+
* session). Anonymous → 401.
|
|
1052
|
+
*
|
|
1053
|
+
* Execution: the MCP runtime builds a stateless per-request server whose
|
|
1054
|
+
* object-CRUD tools run through {@link callData} bound to THIS request's
|
|
1055
|
+
* ExecutionContext — i.e. the exact permission + RLS path the REST API
|
|
1056
|
+
* uses. An external agent can never exceed the key's authority.
|
|
1057
|
+
*/
|
|
1058
|
+
handleMcp(body: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
|
|
1059
|
+
/** Whether the MCP HTTP surface is opted in for this single-env runtime. */
|
|
1060
|
+
private static isMcpEnabled;
|
|
1061
|
+
/**
|
|
1062
|
+
* Normalise the inbound request into a Web-standard `Request` for the MCP
|
|
1063
|
+
* transport. Accepts an already-Web `Request`, or a node/Hono-style req
|
|
1064
|
+
* (plain `headers` object, path-only `url`). Returns undefined only if the
|
|
1065
|
+
* shape is unusable. The body is carried separately via `parsedBody`, so a
|
|
1066
|
+
* GET/DELETE (no body) and a POST (JSON-RPC) both normalise cleanly.
|
|
1067
|
+
*/
|
|
1068
|
+
private toMcpWebRequest;
|
|
1069
|
+
/**
|
|
1070
|
+
* Build a principal-bound {@link McpDataBridge}: every method runs AS the
|
|
1071
|
+
* request's ExecutionContext through {@link callData} (RLS/permissions) and
|
|
1072
|
+
* the per-env metadata service. Keeps the MCP tool layer free of any direct
|
|
1073
|
+
* engine access.
|
|
1074
|
+
*/
|
|
1075
|
+
private buildMcpBridge;
|
|
1076
|
+
/**
|
|
1077
|
+
* Generate a `sys_api_key` and return the raw secret EXACTLY ONCE
|
|
1078
|
+
* (`POST /keys`). This is the only mint path — the raw key is never stored
|
|
1079
|
+
* (only its sha256 hash) and never re-displayable.
|
|
1080
|
+
*
|
|
1081
|
+
* Security (zero-tolerance):
|
|
1082
|
+
* - Requires an authenticated principal; `user_id` is PINNED to that
|
|
1083
|
+
* caller and is NEVER read from the request body (no impersonation).
|
|
1084
|
+
* - Body is whitelisted to `name` (+ optional `expires_at`); any
|
|
1085
|
+
* `key` / `id` / `user_id` / `revoked` in the body is ignored, so a
|
|
1086
|
+
* caller cannot forge a known-secret or escalate.
|
|
1087
|
+
* - `scopes` are intentionally NOT accepted from the body in v1: the
|
|
1088
|
+
* verify path ADDS scopes to the principal's permissions, so honouring
|
|
1089
|
+
* arbitrary body scopes would be an escalation vector. A generated key
|
|
1090
|
+
* therefore acts exactly AS the caller (via `user_id` resolution).
|
|
1091
|
+
* Narrowing/scoped keys need subset-enforcement — deferred.
|
|
1092
|
+
* - The raw key and its hash never enter logs or error messages.
|
|
1093
|
+
* - The row is written with an elevated `{ isSystem: true }` context
|
|
1094
|
+
* because `sys_api_key` is protection-locked; safe because the row's
|
|
1095
|
+
* contents are fully server-controlled (user_id pinned to caller).
|
|
1096
|
+
*/
|
|
1097
|
+
handleKeys(method: string, body: any, context: HttpProtocolContext): Promise<HttpDispatcherResult>;
|
|
1086
1098
|
/**
|
|
1087
1099
|
* Parse a project UUID out of a scoped URL path such as
|
|
1088
1100
|
* `/api/v1/environments/abc-123/data/task` or `/projects/abc-123/meta`.
|
|
@@ -1158,6 +1170,7 @@ declare class HttpDispatcher {
|
|
|
1158
1170
|
notifications: string | undefined;
|
|
1159
1171
|
ai: string | undefined;
|
|
1160
1172
|
i18n: string | undefined;
|
|
1173
|
+
mcp: string | undefined;
|
|
1161
1174
|
};
|
|
1162
1175
|
endpoints: {
|
|
1163
1176
|
data: string;
|
|
@@ -1174,6 +1187,7 @@ declare class HttpDispatcher {
|
|
|
1174
1187
|
notifications: string | undefined;
|
|
1175
1188
|
ai: string | undefined;
|
|
1176
1189
|
i18n: string | undefined;
|
|
1190
|
+
mcp: string | undefined;
|
|
1177
1191
|
};
|
|
1178
1192
|
features: {
|
|
1179
1193
|
graphql: boolean;
|
|
@@ -1523,6 +1537,18 @@ declare class HttpDispatcher {
|
|
|
1523
1537
|
* Physical database addressing (database_url, database_driver, etc.)
|
|
1524
1538
|
* is stored directly on the sys_environment row.
|
|
1525
1539
|
*/
|
|
1540
|
+
/**
|
|
1541
|
+
* Apply just-published `seed` metadata: load each seed's rows into its
|
|
1542
|
+
* target object so publishing a seed draft makes the data live (the runtime
|
|
1543
|
+
* counterpart to staging it). Reads each seed body via the protocol, then
|
|
1544
|
+
* runs the {@link SeedLoaderService} for the active org. Best-effort and
|
|
1545
|
+
* idempotent (upsert) — callers must never let this fail the publish.
|
|
1546
|
+
*
|
|
1547
|
+
* Lives at the runtime layer (not in the objectql publish primitive)
|
|
1548
|
+
* because the seed loader needs the data engine + metadata service, which
|
|
1549
|
+
* objectql cannot depend on without a layering cycle.
|
|
1550
|
+
*/
|
|
1551
|
+
private applyPublishedSeeds;
|
|
1526
1552
|
/**
|
|
1527
1553
|
* Resolve the calling user id from the request session, if any.
|
|
1528
1554
|
* Returns `undefined` for anonymous calls or when auth is not wired up.
|
|
@@ -1737,316 +1763,6 @@ declare function readArtifactSource(pathOrUrl: string, opts?: {
|
|
|
1737
1763
|
declare function loadArtifactBundle(absArtifactPath: string, opts?: LoadArtifactBundleOptions): Promise<any | null>;
|
|
1738
1764
|
declare function mergeRuntimeModule(bundle: any, artifactAbsPath: string, tag?: string): Promise<void>;
|
|
1739
1765
|
|
|
1740
|
-
/**
|
|
1741
|
-
* Artifact API client.
|
|
1742
|
-
*
|
|
1743
|
-
* HTTP client that talks to the ObjectStack control plane (e.g.
|
|
1744
|
-
* `apps/cloud`) to resolve hostnames to projects and to download a
|
|
1745
|
-
* project's compiled artifact.
|
|
1746
|
-
*
|
|
1747
|
-
* The control plane is expected to expose two endpoints:
|
|
1748
|
-
*
|
|
1749
|
-
* GET {controlPlaneUrl}/api/v1/cloud/resolve-hostname?host={hostname}
|
|
1750
|
-
* → { environmentId: string, organizationId?: string, runtime?: EnvironmentRuntimeConfig }
|
|
1751
|
-
*
|
|
1752
|
-
* GET {controlPlaneUrl}/api/v1/cloud/environments/:environmentId/artifact
|
|
1753
|
-
* → EnvironmentArtifactResponse (EnvironmentArtifact + optional `runtime` block)
|
|
1754
|
-
*
|
|
1755
|
-
* Both endpoints accept an optional `Authorization: Bearer <apiKey>`.
|
|
1756
|
-
*
|
|
1757
|
-
* Responses are cached in-memory with a TTL so each kernel-manager
|
|
1758
|
-
* miss does not produce an extra HTTP round trip. Concurrent callers
|
|
1759
|
-
* for the same key share a single in-flight promise (singleflight).
|
|
1760
|
-
*/
|
|
1761
|
-
|
|
1762
|
-
/**
|
|
1763
|
-
* Per-project runtime config injected by the control plane alongside
|
|
1764
|
-
* the artifact. Carries the physical database URL the runtime should
|
|
1765
|
-
* connect to (this is *not* part of the developer-authored compiled
|
|
1766
|
-
* artifact — the control plane mints it when serving the API).
|
|
1767
|
-
*/
|
|
1768
|
-
interface EnvironmentRuntimeConfig {
|
|
1769
|
-
organizationId?: string;
|
|
1770
|
-
hostname?: string;
|
|
1771
|
-
/** Driver type — e.g. `sqlite`, `postgres`, `turso`, `memory`. */
|
|
1772
|
-
databaseDriver: string;
|
|
1773
|
-
/** Driver-specific connection URL. */
|
|
1774
|
-
databaseUrl: string;
|
|
1775
|
-
/** Optional auth token (e.g. for libSQL/Turso). */
|
|
1776
|
-
databaseAuthToken?: string;
|
|
1777
|
-
/**
|
|
1778
|
-
* Project-level metadata captured by the control plane at create time
|
|
1779
|
-
* (e.g. `ownerSeed`, `orgSeed`). Forwarded to the runtime so cold-boot
|
|
1780
|
-
* seed replay can mirror the cloud org + owner into the project DB
|
|
1781
|
-
* before the user's first SSO callback arrives.
|
|
1782
|
-
*/
|
|
1783
|
-
metadata?: Record<string, unknown>;
|
|
1784
|
-
}
|
|
1785
|
-
/**
|
|
1786
|
-
* Hostname resolution response.
|
|
1787
|
-
*/
|
|
1788
|
-
interface ResolvedHostname {
|
|
1789
|
-
environmentId: string;
|
|
1790
|
-
organizationId?: string;
|
|
1791
|
-
/** Optional runtime config — when present, callers can skip the artifact fetch's runtime block. */
|
|
1792
|
-
runtime?: EnvironmentRuntimeConfig;
|
|
1793
|
-
}
|
|
1794
|
-
/**
|
|
1795
|
-
* Artifact response wrapping the spec's `EnvironmentArtifact` envelope plus
|
|
1796
|
-
* an optional `runtime` block carrying the project's database
|
|
1797
|
-
* connection details.
|
|
1798
|
-
*/
|
|
1799
|
-
interface EnvironmentArtifactResponse extends EnvironmentArtifact {
|
|
1800
|
-
runtime?: EnvironmentRuntimeConfig;
|
|
1801
|
-
}
|
|
1802
|
-
interface ArtifactApiClientConfig {
|
|
1803
|
-
/** Control-plane base URL (no trailing slash). */
|
|
1804
|
-
controlPlaneUrl: string;
|
|
1805
|
-
/** Optional bearer token. */
|
|
1806
|
-
apiKey?: string;
|
|
1807
|
-
/** Cache TTL in ms. Default: 5 min. */
|
|
1808
|
-
cacheTtlMs?: number;
|
|
1809
|
-
/** Timeout for control-plane HTTP calls in ms. Default: 10s. */
|
|
1810
|
-
requestTimeoutMs?: number;
|
|
1811
|
-
/** Optional fetch override (testing). */
|
|
1812
|
-
fetch?: typeof fetch;
|
|
1813
|
-
/** Optional logger. */
|
|
1814
|
-
logger?: {
|
|
1815
|
-
info?: (...a: any[]) => void;
|
|
1816
|
-
warn?: (...a: any[]) => void;
|
|
1817
|
-
error?: (...a: any[]) => void;
|
|
1818
|
-
};
|
|
1819
|
-
}
|
|
1820
|
-
declare class ArtifactApiClient {
|
|
1821
|
-
private readonly base;
|
|
1822
|
-
private readonly apiKey?;
|
|
1823
|
-
private readonly cacheTtlMs;
|
|
1824
|
-
private readonly requestTimeoutMs;
|
|
1825
|
-
private readonly fetchImpl;
|
|
1826
|
-
private readonly logger;
|
|
1827
|
-
private readonly hostnameCache;
|
|
1828
|
-
private readonly artifactCache;
|
|
1829
|
-
private readonly pendingHostname;
|
|
1830
|
-
private readonly pendingArtifact;
|
|
1831
|
-
constructor(config: ArtifactApiClientConfig);
|
|
1832
|
-
/**
|
|
1833
|
-
* Resolve a hostname to its project. Returns `null` on 404 or
|
|
1834
|
-
* malformed responses. Errors (network / 5xx) are thrown so
|
|
1835
|
-
* upstream callers can retry.
|
|
1836
|
-
*/
|
|
1837
|
-
resolveHostname(host: string): Promise<ResolvedHostname | null>;
|
|
1838
|
-
/**
|
|
1839
|
-
* Fetch the compiled artifact for a project.
|
|
1840
|
-
*
|
|
1841
|
-
* When `opts.commit` is set, requests that specific revision via the
|
|
1842
|
-
* existing `?commit=` query param. Different commits are cached
|
|
1843
|
-
* independently (the cache key includes the commit id) so the preview
|
|
1844
|
-
* runtime can hold multiple versions in memory simultaneously.
|
|
1845
|
-
*/
|
|
1846
|
-
fetchArtifact(environmentId: string, opts?: {
|
|
1847
|
-
commit?: string;
|
|
1848
|
-
}): Promise<EnvironmentArtifactResponse | null>;
|
|
1849
|
-
/**
|
|
1850
|
-
* Resolve an 8-hex project short id (first 8 hex chars of the UUID,
|
|
1851
|
-
* dashes stripped) to the full environmentId. Used by the preview
|
|
1852
|
-
* runtime, which encodes project ids in subdomains.
|
|
1853
|
-
*
|
|
1854
|
-
* Returns `null` on 404 or ambiguity (the control plane returns 409
|
|
1855
|
-
* if the prefix matches more than one project).
|
|
1856
|
-
*/
|
|
1857
|
-
lookupProjectByShortId(shortId: string): Promise<{
|
|
1858
|
-
environmentId: string;
|
|
1859
|
-
organizationId?: string;
|
|
1860
|
-
} | null>;
|
|
1861
|
-
/**
|
|
1862
|
-
* Fetch the head commit of a branch. Returns the commit id (and the
|
|
1863
|
-
* matching revision row's `published_at` for cache-validity checks).
|
|
1864
|
-
* Reuses the existing `GET /cloud/environments/:id/branches` endpoint.
|
|
1865
|
-
*/
|
|
1866
|
-
fetchBranchHead(environmentId: string, branchName: string): Promise<{
|
|
1867
|
-
commitId: string;
|
|
1868
|
-
publishedAt?: string | null;
|
|
1869
|
-
} | null>;
|
|
1870
|
-
/**
|
|
1871
|
-
* Cheap freshness probe — returns the env's `last_published_at`
|
|
1872
|
-
* (and best-effort current commit) without rebuilding the artifact.
|
|
1873
|
-
* Used by `KernelManager` on cache hits to detect when a per-env
|
|
1874
|
-
* kernel has been invalidated by an upstream change (marketplace
|
|
1875
|
-
* install/uninstall, artifact publish) so it can be rebuilt
|
|
1876
|
-
* without waiting for the 15-minute LRU TTL to expire.
|
|
1877
|
-
*
|
|
1878
|
-
* Returns `null` on definitive 404 / unknown env. Errors propagate
|
|
1879
|
-
* (caller decides whether to treat unreachable cloud as fresh or
|
|
1880
|
-
* stale — typically fresh, so a brief outage doesn't churn every
|
|
1881
|
-
* cached kernel).
|
|
1882
|
-
*/
|
|
1883
|
-
getFreshness(environmentId: string): Promise<{
|
|
1884
|
-
environmentId: string;
|
|
1885
|
-
lastPublishedAt: string | null;
|
|
1886
|
-
commitId: string | null;
|
|
1887
|
-
} | null>;
|
|
1888
|
-
/** Drop cached entries for a project (and any matching hostname). */
|
|
1889
|
-
invalidate(environmentId: string): void;
|
|
1890
|
-
/** Drop everything. Used on shutdown / hot-reload. */
|
|
1891
|
-
clear(): void;
|
|
1892
|
-
private request;
|
|
1893
|
-
private buildHeaders;
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
interface FileArtifactApiClientConfig {
|
|
1897
|
-
/**
|
|
1898
|
-
* Path to a compiled artifact JSON file (`dist/objectstack.json`).
|
|
1899
|
-
* Resolved against `process.cwd()` when relative. Defaults to
|
|
1900
|
-
* `<cwd>/dist/objectstack.json`.
|
|
1901
|
-
*/
|
|
1902
|
-
artifactPath?: string;
|
|
1903
|
-
/**
|
|
1904
|
-
* Project id every hostname maps to. Defaults to
|
|
1905
|
-
* `process.env.OS_ENVIRONMENT_ID` or `'proj_local'`.
|
|
1906
|
-
*/
|
|
1907
|
-
environmentId?: string;
|
|
1908
|
-
/**
|
|
1909
|
-
* Organization id surfaced alongside the project. Defaults to
|
|
1910
|
-
* `process.env.OS_ORGANIZATION_ID` or `'org_local'`.
|
|
1911
|
-
*/
|
|
1912
|
-
organizationId?: string;
|
|
1913
|
-
/**
|
|
1914
|
-
* Override runtime config. When unset, the client tries to derive
|
|
1915
|
-
* one from the artifact's `datasources` array; if that fails it
|
|
1916
|
-
* falls back to a local-file SQLite DB at
|
|
1917
|
-
* `<cwd>/.objectstack/data/<environmentId>.db`.
|
|
1918
|
-
*/
|
|
1919
|
-
runtime?: EnvironmentRuntimeConfig;
|
|
1920
|
-
/**
|
|
1921
|
-
* Reload the artifact on every fetch instead of caching the first
|
|
1922
|
-
* read. Useful when iterating on a project's metadata without
|
|
1923
|
-
* restarting objectos. Defaults to `true` for dev ergonomics.
|
|
1924
|
-
*/
|
|
1925
|
-
watch?: boolean;
|
|
1926
|
-
/** Optional logger. */
|
|
1927
|
-
logger?: {
|
|
1928
|
-
info?: (...a: any[]) => void;
|
|
1929
|
-
warn?: (...a: any[]) => void;
|
|
1930
|
-
error?: (...a: any[]) => void;
|
|
1931
|
-
};
|
|
1932
|
-
}
|
|
1933
|
-
declare class FileArtifactApiClient {
|
|
1934
|
-
private readonly artifactPath;
|
|
1935
|
-
private readonly environmentId;
|
|
1936
|
-
private readonly organizationId;
|
|
1937
|
-
private readonly overrideRuntime?;
|
|
1938
|
-
private readonly watch;
|
|
1939
|
-
private readonly logger;
|
|
1940
|
-
private cached?;
|
|
1941
|
-
constructor(config?: FileArtifactApiClientConfig);
|
|
1942
|
-
resolveHostname(_host: string): Promise<ResolvedHostname | null>;
|
|
1943
|
-
fetchArtifact(_environmentId: string, _opts?: {
|
|
1944
|
-
commit?: string;
|
|
1945
|
-
}): Promise<EnvironmentArtifactResponse | null>;
|
|
1946
|
-
lookupProjectByShortId(_shortId: string): Promise<{
|
|
1947
|
-
environmentId: string;
|
|
1948
|
-
organizationId?: string;
|
|
1949
|
-
} | null>;
|
|
1950
|
-
fetchBranchHead(_environmentId: string, _branchName: string): Promise<{
|
|
1951
|
-
commitId: string;
|
|
1952
|
-
publishedAt?: string | null;
|
|
1953
|
-
} | null>;
|
|
1954
|
-
invalidate(_environmentId: string): void;
|
|
1955
|
-
clear(): void;
|
|
1956
|
-
private loadArtifact;
|
|
1957
|
-
private readRuntimeFromArtifact;
|
|
1958
|
-
private deriveRuntimeFromMetadata;
|
|
1959
|
-
private defaultLocalSqliteRuntime;
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
/**
|
|
1963
|
-
* createObjectOSStack
|
|
1964
|
-
*
|
|
1965
|
-
* ObjectOS pure-runtime stack — no control-plane database, no auth /
|
|
1966
|
-
* security / audit / tenant plugins. The host kernel registers:
|
|
1967
|
-
*
|
|
1968
|
-
* - A minimal engine triplet (ObjectQL + in-memory DriverPlugin +
|
|
1969
|
-
* MetadataPlugin) so CLI auto-injected plugins (Setup, Studio,
|
|
1970
|
-
* Dispatcher, REST) and the runtime can boot. The host kernel itself
|
|
1971
|
-
* never reads or writes business data — every record query is routed
|
|
1972
|
-
* to a per-project kernel built from a remote artifact.
|
|
1973
|
-
* - The `env-registry` and `kernel-manager` services, so the runtime's
|
|
1974
|
-
* HTTP dispatcher can resolve hostnames and dispatch every request
|
|
1975
|
-
* to the matching project kernel.
|
|
1976
|
-
*
|
|
1977
|
-
* Invoked by `createRuntimeStack()` whenever `OS_CLOUD_URL`
|
|
1978
|
-
* (or `config.controlPlaneUrl`) is set. The same plugin shape is returned
|
|
1979
|
-
* as `createCloudStack()` so host configs can swap stacks transparently.
|
|
1980
|
-
*/
|
|
1981
|
-
|
|
1982
|
-
interface ObjectOSStackConfig {
|
|
1983
|
-
/**
|
|
1984
|
-
* Control-plane base URL (HTTP) or a sentinel of `'file'` for the
|
|
1985
|
-
* local file-backed dev mode. Required unless `client` is supplied.
|
|
1986
|
-
*
|
|
1987
|
-
* - `http(s)://…` — talk to a real ObjectStack Cloud control plane
|
|
1988
|
-
* over HTTP and resolve hostnames via its `/cloud/*` API.
|
|
1989
|
-
* - `'file'` — load a single project from a local
|
|
1990
|
-
* `dist/objectstack.json` (or `fileConfig.artifactPath`). Every
|
|
1991
|
-
* request, regardless of hostname, resolves to the same project.
|
|
1992
|
-
* Intended for `pnpm dev` / smoke tests where standing up a
|
|
1993
|
-
* separate control plane is overkill.
|
|
1994
|
-
*/
|
|
1995
|
-
controlPlaneUrl?: string;
|
|
1996
|
-
/** Optional bearer token for the control-plane API. */
|
|
1997
|
-
controlPlaneApiKey?: string;
|
|
1998
|
-
/**
|
|
1999
|
-
* Override the artifact client entirely. When supplied,
|
|
2000
|
-
* `controlPlaneUrl` is ignored — useful for tests or custom transports.
|
|
2001
|
-
*/
|
|
2002
|
-
client?: ArtifactApiClient | FileArtifactApiClient;
|
|
2003
|
-
/** Config for the file-backed mode (used when `controlPlaneUrl === 'file'`). */
|
|
2004
|
-
fileConfig?: FileArtifactApiClientConfig;
|
|
2005
|
-
/** KernelManager LRU size. Default: 32. */
|
|
2006
|
-
kernelCacheSize?: number;
|
|
2007
|
-
/** KernelManager idle TTL (ms). Default: 15 min. */
|
|
2008
|
-
kernelTtlMs?: number;
|
|
2009
|
-
/** EnvironmentDriverRegistry cache TTL (ms). Default: 5 min. */
|
|
2010
|
-
envCacheTtlMs?: number;
|
|
2011
|
-
/** Artifact / hostname response cache TTL (ms). Default: 5 min. */
|
|
2012
|
-
artifactCacheTtlMs?: number;
|
|
2013
|
-
/** API prefix (carried for parity with cloud-stack). Default: /api/v1. */
|
|
2014
|
-
apiPrefix?: string;
|
|
2015
|
-
/**
|
|
2016
|
-
* Host-supplied runtime plugins appended to the stack's default plugin
|
|
2017
|
-
* list. This is the official seam for a host (e.g. the ObjectStack Cloud
|
|
2018
|
-
* repo) to add **product/policy** plugins — marketplace install, cloud-
|
|
2019
|
-
* account binding, set-initial-password — to the otherwise-neutral
|
|
2020
|
-
* framework runtime, WITHOUT a framework release and without reaching into
|
|
2021
|
-
* the returned array by hand.
|
|
2022
|
-
*
|
|
2023
|
-
* They are appended last, so they mount their routes after the framework
|
|
2024
|
-
* plugins and can override/augment behaviour (e.g. supply a credentialled
|
|
2025
|
-
* install path that the browse-only MarketplaceProxyPlugin deliberately
|
|
2026
|
-
* does not). See docs/design/cloud-account-binding-marketplace-install.md
|
|
2027
|
-
* (ADR §5.2 — "framework exposes seams; cloud supplies metadata + policy").
|
|
2028
|
-
*/
|
|
2029
|
-
extraPlugins?: Plugin[];
|
|
2030
|
-
/**
|
|
2031
|
-
* Capability tokens force-mounted on EVERY per-environment kernel, in
|
|
2032
|
-
* addition to whatever the app artifact declares in `requires`. Merged and
|
|
2033
|
-
* de-duped with `bundle.requires` before the capability loader runs. This
|
|
2034
|
-
* is the host seam for a cloud operator to make a capability ubiquitous
|
|
2035
|
-
* across all tenants without editing each app — e.g. `['ai','aiStudio']`
|
|
2036
|
-
* so every cloud environment supports AI-driven online development.
|
|
2037
|
-
*/
|
|
2038
|
-
defaultRequires?: string[];
|
|
2039
|
-
}
|
|
2040
|
-
interface ObjectOSStackResult {
|
|
2041
|
-
plugins: any[];
|
|
2042
|
-
api: {
|
|
2043
|
-
enableProjectScoping: true;
|
|
2044
|
-
projectResolution: 'auto';
|
|
2045
|
-
requireAuth: true;
|
|
2046
|
-
};
|
|
2047
|
-
}
|
|
2048
|
-
declare function createObjectOSStack(config: ObjectOSStackConfig): Promise<ObjectOSStackResult>;
|
|
2049
|
-
|
|
2050
1766
|
/**
|
|
2051
1767
|
* MarketplaceProxyPlugin
|
|
2052
1768
|
*
|
|
@@ -2315,265 +2031,6 @@ declare const DEFAULT_CLOUD_URL = "https://cloud.objectos.ai";
|
|
|
2315
2031
|
*/
|
|
2316
2032
|
declare function resolveCloudUrl(explicit?: string | null): string;
|
|
2317
2033
|
|
|
2318
|
-
/**
|
|
2319
|
-
* Per-project driver registry contract.
|
|
2320
|
-
*
|
|
2321
|
-
* Resolves a project (by hostname or ID) and produces an instantiated
|
|
2322
|
-
* `IDataDriver` bound to that project's physical database. Concrete
|
|
2323
|
-
* implementations sit on top of either:
|
|
2324
|
-
* - the ObjectStack Cloud HTTP API (see {@link ArtifactEnvironmentRegistry})
|
|
2325
|
-
* - a local file artifact (see {@link FileArtifactApiClient} +
|
|
2326
|
-
* {@link ArtifactEnvironmentRegistry})
|
|
2327
|
-
*
|
|
2328
|
-
* The contract lives in `@objectstack/runtime` so the runtime can
|
|
2329
|
-
* express "fetch artifact + boot per-project kernel" without taking a
|
|
2330
|
-
* dependency on the cloud control plane.
|
|
2331
|
-
*/
|
|
2332
|
-
|
|
2333
|
-
type IDataDriver$1 = Contracts.IDataDriver;
|
|
2334
|
-
interface EnvironmentDriverRegistry {
|
|
2335
|
-
/** Resolve a project by hostname. Returns `null` when unknown. */
|
|
2336
|
-
resolveByHostname(host: string): Promise<{
|
|
2337
|
-
environmentId: string;
|
|
2338
|
-
driver: IDataDriver$1;
|
|
2339
|
-
} | null>;
|
|
2340
|
-
/** Resolve a project's driver by ID. Returns `null` when unknown. */
|
|
2341
|
-
resolveById(environmentId: string): Promise<IDataDriver$1 | null>;
|
|
2342
|
-
/**
|
|
2343
|
-
* Look up the cached project row + driver by ID without triggering a
|
|
2344
|
-
* remote/file fetch. Returns the full cached entry when fresh.
|
|
2345
|
-
*/
|
|
2346
|
-
peekById(environmentId: string): {
|
|
2347
|
-
environmentId: string;
|
|
2348
|
-
driver: IDataDriver$1;
|
|
2349
|
-
project: any;
|
|
2350
|
-
} | null;
|
|
2351
|
-
/** Drop cached entries for the given project. */
|
|
2352
|
-
invalidate(environmentId: string): void;
|
|
2353
|
-
}
|
|
2354
|
-
|
|
2355
|
-
/**
|
|
2356
|
-
* EnvironmentDriverRegistry implementation that talks to the control plane
|
|
2357
|
-
* over HTTP via {@link ArtifactApiClient}.
|
|
2358
|
-
*
|
|
2359
|
-
* Mirrors {@link DefaultEnvironmentDriverRegistry} from `environment-registry.ts`
|
|
2360
|
-
* but does **not** read from a local control-plane database. Hostname →
|
|
2361
|
-
* environmentId resolution and per-project runtime config (database URL /
|
|
2362
|
-
* driver) come from the control plane API.
|
|
2363
|
-
*
|
|
2364
|
-
* The cached `project` payload exposed by `peekById()` is shaped to look
|
|
2365
|
-
* like a `sys_environment` row so callers downstream (notably
|
|
2366
|
-
* `ArtifactKernelFactory`) can read `id`, `organization_id`,
|
|
2367
|
-
* `database_url` and `database_driver` without branching.
|
|
2368
|
-
*/
|
|
2369
|
-
|
|
2370
|
-
type IDataDriver = Contracts.IDataDriver;
|
|
2371
|
-
interface ArtifactEnvironmentRegistryConfig {
|
|
2372
|
-
client: ArtifactApiClient;
|
|
2373
|
-
/** Cache TTL for resolved drivers in ms. Default: 5 min. */
|
|
2374
|
-
cacheTtlMs?: number;
|
|
2375
|
-
/** Optional logger. */
|
|
2376
|
-
logger?: {
|
|
2377
|
-
info?: (...a: any[]) => void;
|
|
2378
|
-
warn?: (...a: any[]) => void;
|
|
2379
|
-
error?: (...a: any[]) => void;
|
|
2380
|
-
};
|
|
2381
|
-
}
|
|
2382
|
-
declare class ArtifactEnvironmentRegistry implements EnvironmentDriverRegistry {
|
|
2383
|
-
private readonly client;
|
|
2384
|
-
private readonly cacheTTL;
|
|
2385
|
-
private readonly logger;
|
|
2386
|
-
private readonly hostnameCache;
|
|
2387
|
-
private readonly idCache;
|
|
2388
|
-
private readonly pending;
|
|
2389
|
-
constructor(config: ArtifactEnvironmentRegistryConfig);
|
|
2390
|
-
resolveByHostname(host: string): Promise<{
|
|
2391
|
-
environmentId: string;
|
|
2392
|
-
driver: IDataDriver;
|
|
2393
|
-
} | null>;
|
|
2394
|
-
resolveById(environmentId: string): Promise<IDataDriver | null>;
|
|
2395
|
-
peekById(environmentId: string): {
|
|
2396
|
-
environmentId: string;
|
|
2397
|
-
driver: IDataDriver;
|
|
2398
|
-
project: any;
|
|
2399
|
-
} | null;
|
|
2400
|
-
invalidate(environmentId: string): void;
|
|
2401
|
-
private buildCacheEntry;
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2404
|
-
interface ArtifactKernelFactoryConfig {
|
|
2405
|
-
client: ArtifactApiClient;
|
|
2406
|
-
envRegistry: EnvironmentDriverRegistry;
|
|
2407
|
-
/** Optional logger. */
|
|
2408
|
-
logger?: {
|
|
2409
|
-
info?: (...a: any[]) => void;
|
|
2410
|
-
warn?: (...a: any[]) => void;
|
|
2411
|
-
error?: (...a: any[]) => void;
|
|
2412
|
-
};
|
|
2413
|
-
/** Optional kernel constructor config. */
|
|
2414
|
-
kernelConfig?: ConstructorParameters<typeof ObjectKernel>[0];
|
|
2415
|
-
/**
|
|
2416
|
-
* Base secret used to derive per-project AuthPlugin secrets via
|
|
2417
|
-
* HKDF-style HMAC-SHA256(baseSecret, environmentId). Falls back to
|
|
2418
|
-
* `process.env.OS_AUTH_SECRET` / `AUTH_SECRET` at construction time.
|
|
2419
|
-
*/
|
|
2420
|
-
authBaseSecret?: string;
|
|
2421
|
-
/**
|
|
2422
|
-
* Capability tokens force-mounted on every per-environment kernel, merged
|
|
2423
|
-
* (and de-duped by the loader) with the artifact's own `requires`. Lets a
|
|
2424
|
-
* host make a capability ubiquitous across tenants — e.g. `['ai','aiStudio']`.
|
|
2425
|
-
*/
|
|
2426
|
-
defaultRequires?: string[];
|
|
2427
|
-
}
|
|
2428
|
-
declare class ArtifactKernelFactory implements EnvironmentKernelFactory {
|
|
2429
|
-
private readonly client;
|
|
2430
|
-
private readonly envRegistry;
|
|
2431
|
-
private readonly logger;
|
|
2432
|
-
private readonly kernelConfig?;
|
|
2433
|
-
private readonly authBaseSecret;
|
|
2434
|
-
private readonly defaultRequires;
|
|
2435
|
-
constructor(config: ArtifactKernelFactoryConfig);
|
|
2436
|
-
create(environmentId: string): Promise<ObjectKernel>;
|
|
2437
|
-
}
|
|
2438
|
-
|
|
2439
|
-
/**
|
|
2440
|
-
* AuthProxyPlugin
|
|
2441
|
-
*
|
|
2442
|
-
* Mounts a single `/api/v1/auth/*` wildcard route on the host's Hono server
|
|
2443
|
-
* that forwards every request to the per-project `AuthManager` registered
|
|
2444
|
-
* by `ArtifactKernelFactory`.
|
|
2445
|
-
*
|
|
2446
|
-
* Why a dedicated plugin: AuthPlugin (better-auth) registers its routes by
|
|
2447
|
-
* grabbing the host's `http-server` service from its own `PluginContext`.
|
|
2448
|
-
* In objectos runtime mode AuthPlugin lives on a per-project kernel — it
|
|
2449
|
-
* has no access to the host's HTTP server, so its `kernel:ready` route
|
|
2450
|
-
* registration is a no-op. The dispatcher plugin's wildcard registration
|
|
2451
|
-
* via `IHttpServer.post('/auth/*', …)` proved unreliable in practice,
|
|
2452
|
-
* so this plugin uses Hono's raw app directly (same path AuthPlugin took
|
|
2453
|
-
* historically) which is rock solid.
|
|
2454
|
-
*
|
|
2455
|
-
* Routing:
|
|
2456
|
-
* 1. Resolve the project from the request hostname via `env-registry`.
|
|
2457
|
-
* 2. Acquire the project's kernel via `kernel-manager`.
|
|
2458
|
-
* 3. Look up the `auth` service on that kernel — this is the better-auth
|
|
2459
|
-
* handler injected by `ArtifactKernelFactory`.
|
|
2460
|
-
* 4. Build a Web `Request` using the project's canonical baseUrl and
|
|
2461
|
-
* hand it to the better-auth handler.
|
|
2462
|
-
* 5. Stream the response back through Hono.
|
|
2463
|
-
*/
|
|
2464
|
-
|
|
2465
|
-
declare class AuthProxyPlugin implements Plugin {
|
|
2466
|
-
readonly name = "com.objectstack.runtime.auth-proxy";
|
|
2467
|
-
readonly version = "1.0.0";
|
|
2468
|
-
init: (_ctx: PluginContext) => Promise<void>;
|
|
2469
|
-
start: (ctx: PluginContext) => Promise<void>;
|
|
2470
|
-
}
|
|
2471
|
-
|
|
2472
|
-
/**
|
|
2473
|
-
* Provider id used in better-auth's `genericOAuth` and as part of the
|
|
2474
|
-
* callback URL: `/api/v1/auth/oauth2/callback/<PROVIDER_ID>`. Keep stable —
|
|
2475
|
-
* changing it invalidates every registered redirect_uri.
|
|
2476
|
-
*/
|
|
2477
|
-
declare const PLATFORM_SSO_PROVIDER_ID = "objectstack-cloud";
|
|
2478
|
-
/**
|
|
2479
|
-
* Derive the per-project OAuth client_id used in `sys_oauth_application`
|
|
2480
|
-
* (cloud side) and {@link genericOAuth} config (project side).
|
|
2481
|
-
*/
|
|
2482
|
-
declare function derivePlatformSsoClientId(environmentId: string): string;
|
|
2483
|
-
/**
|
|
2484
|
-
* Derive the per-project OAuth client_secret deterministically from the
|
|
2485
|
-
* shared master secret. HMAC-SHA256(baseSecret, 'oauth-client:' + environmentId)
|
|
2486
|
-
* yields a 64-char hex string that is:
|
|
2487
|
-
* - stable across container cold-starts (no DB lookup needed)
|
|
2488
|
-
* - independent per project (compromising one does not compromise others)
|
|
2489
|
-
* - rotatable via OS_AUTH_SECRET rotation (invalidates all SSO clients)
|
|
2490
|
-
*
|
|
2491
|
-
* This is the **plaintext** value the RP must present at the token endpoint.
|
|
2492
|
-
* The cloud-side `sys_oauth_application.client_secret` column instead stores
|
|
2493
|
-
* {@link hashPlatformSsoClientSecret}(plaintext) — better-auth's oauth-provider
|
|
2494
|
-
* defaults to `storeClientSecret: 'hashed'` (SHA-256 + base64url) when the JWT
|
|
2495
|
-
* plugin is enabled, and looks up the row by hashing the presented secret.
|
|
2496
|
-
*/
|
|
2497
|
-
declare function derivePlatformSsoClientSecret(baseSecret: string, environmentId: string): string;
|
|
2498
|
-
/**
|
|
2499
|
-
* Build the redirect_uri better-auth's `genericOAuth` plugin will use
|
|
2500
|
-
* when the project kernel mounts the provider with id
|
|
2501
|
-
* {@link PLATFORM_SSO_PROVIDER_ID}. MUST be one of the URIs registered
|
|
2502
|
-
* on the cloud-side oauth client or the authorization server will reject
|
|
2503
|
-
* the callback with `invalid_request`.
|
|
2504
|
-
*/
|
|
2505
|
-
declare function buildPlatformSsoRedirectUri(hostname: string, basePath?: string): string;
|
|
2506
|
-
interface SeedPlatformSsoClientOptions {
|
|
2507
|
-
/**
|
|
2508
|
-
* Cloud control-plane ObjectQL engine. Must expose `find(object, query)`,
|
|
2509
|
-
* `insert(object, data)`, and `update(object, data, {where})`. Both the
|
|
2510
|
-
* `apps/cloud` boot kernel (via `kernel.getService('objectql')`) and the
|
|
2511
|
-
* dispatcher's local `ql` reference satisfy this shape.
|
|
2512
|
-
*/
|
|
2513
|
-
ql: {
|
|
2514
|
-
find: (object: string, query: any, opts?: any) => Promise<any>;
|
|
2515
|
-
insert: (object: string, data: any, opts?: any) => Promise<any>;
|
|
2516
|
-
update: (object: string, data: any, where: any, opts?: any) => Promise<any>;
|
|
2517
|
-
};
|
|
2518
|
-
/** Project id (also used to derive client_id + client_secret). */
|
|
2519
|
-
environmentId: string;
|
|
2520
|
-
/**
|
|
2521
|
-
* Project hostname (e.g. `acme-crm.objectos.ai`). Optional — projects
|
|
2522
|
-
* may be created before a hostname is assigned, in which case no
|
|
2523
|
-
* redirect_uri is registered yet and the row is upserted with an
|
|
2524
|
-
* empty `redirect_uris` array. Calling this function again once the
|
|
2525
|
-
* hostname is known will merge the new URI in.
|
|
2526
|
-
*/
|
|
2527
|
-
hostname?: string | null;
|
|
2528
|
-
/** Master secret shared between cloud and project containers. */
|
|
2529
|
-
baseSecret: string;
|
|
2530
|
-
/** Optional logger for diagnostics. */
|
|
2531
|
-
logger?: {
|
|
2532
|
-
info?: (...a: any[]) => void;
|
|
2533
|
-
warn?: (...a: any[]) => void;
|
|
2534
|
-
error?: (...a: any[]) => void;
|
|
2535
|
-
};
|
|
2536
|
-
/** When true, rethrow insert/update errors instead of swallowing them.
|
|
2537
|
-
* Backfill uses this to surface real failures via the admin endpoint. */
|
|
2538
|
-
throwOnError?: boolean;
|
|
2539
|
-
}
|
|
2540
|
-
/**
|
|
2541
|
-
* Idempotently upsert a `sys_oauth_application` row for the given project.
|
|
2542
|
-
* Re-running with the same `environmentId` is a no-op (the deterministic
|
|
2543
|
-
* `client_id` is uniquely indexed and the secret derivation is stable).
|
|
2544
|
-
* Re-running with a new `hostname` adds the new redirect_uri to the
|
|
2545
|
-
* existing row's JSON array.
|
|
2546
|
-
*/
|
|
2547
|
-
declare function seedPlatformSsoClient(opts: SeedPlatformSsoClientOptions): Promise<void>;
|
|
2548
|
-
interface BackfillPlatformSsoClientsOptions {
|
|
2549
|
-
ql: SeedPlatformSsoClientOptions['ql'];
|
|
2550
|
-
baseSecret: string;
|
|
2551
|
-
logger?: {
|
|
2552
|
-
info?: (...a: any[]) => void;
|
|
2553
|
-
warn?: (...a: any[]) => void;
|
|
2554
|
-
error?: (...a: any[]) => void;
|
|
2555
|
-
};
|
|
2556
|
-
/** Hard cap on rows scanned (default: 1000). */
|
|
2557
|
-
limit?: number;
|
|
2558
|
-
}
|
|
2559
|
-
/**
|
|
2560
|
-
* Scan `sys_environment` and ensure every active project has a corresponding
|
|
2561
|
-
* `sys_oauth_application` row. Intended to run once at cloud boot — the
|
|
2562
|
-
* happy path is dominated by the project-create hook
|
|
2563
|
-
* ({@link seedPlatformSsoClient}); the backfill exists so projects
|
|
2564
|
-
* created before this feature shipped also get SSO support without an
|
|
2565
|
-
* out-of-band migration.
|
|
2566
|
-
*/
|
|
2567
|
-
declare function backfillPlatformSsoClients(opts: BackfillPlatformSsoClientsOptions): Promise<{
|
|
2568
|
-
scanned: number;
|
|
2569
|
-
seeded: number;
|
|
2570
|
-
alreadyExisted: number;
|
|
2571
|
-
failures: Array<{
|
|
2572
|
-
environmentId: string;
|
|
2573
|
-
error: string;
|
|
2574
|
-
}>;
|
|
2575
|
-
}>;
|
|
2576
|
-
|
|
2577
2034
|
/**
|
|
2578
2035
|
* # Hook & Action Body Sandbox
|
|
2579
2036
|
*
|
|
@@ -2804,4 +2261,4 @@ declare function actionBodyRunnerFactory(runner: ScriptRunner, opts: FactoryOpti
|
|
|
2804
2261
|
timeoutMs?: number;
|
|
2805
2262
|
}) => ((actionCtx: any) => Promise<unknown>) | undefined;
|
|
2806
2263
|
|
|
2807
|
-
export { AppPlugin,
|
|
2264
|
+
export { AppPlugin, DEFAULT_CLOUD_URL, DEFAULT_RATE_LIMITS, type DefaultHostConfigOptions, type DefaultHostConfigResult, type DispatcherPluginConfig, DriverPlugin, type EnvironmentDriverRegistry, type ExternalSchemaDriftEvent, ExternalValidationPlugin, HttpDispatcher, type HttpDispatcherResult, type HttpProtocolContext, HttpServer, type KernelManager, type LoadArtifactBundleOptions, MarketplaceInstallLocalPlugin, type MarketplaceInstallLocalPluginConfig, MarketplaceProxyPlugin, type MarketplaceProxyPluginConfig, MiddlewareManager, ObservabilityServicePlugin, type ObservabilityServicePluginOptions, QuickJSScriptRunner, type QuickJSScriptRunnerOptions, type RateLimitBucketConfig, type RateLimitDecision, type RateLimitDefaults, type RateLimitStore, RateLimiter, Runtime, type RuntimeConfig, RuntimeConfigPlugin, type RuntimeConfigPluginConfig, SYSTEM_ENVIRONMENT_ID, SandboxError, type ScriptContext, type ScriptOrigin, type ScriptResult, type ScriptRunOptions, type ScriptRunner, type SecurityHeadersOptions, SeedLoaderService, type StandaloneStackConfig, type StandaloneStackResult, type SystemEnvironmentPluginConfig, type TraceContext, UnimplementedScriptRunner, actionBodyRunnerFactory, buildSecurityHeaders, collectBundleActions, collectBundleFunctions, collectBundleHooks, createDefaultHostConfig, createDispatcherPlugin, createExternalValidationPlugin, createStandaloneStack, createSystemEnvironmentPlugin, extractRequestId, formatTraceparent, generateRequestId, hookBodyRunnerFactory, isHttpUrl, loadArtifactBundle, mergeRuntimeModule, parseTraceparent, readArtifactSource, resolveCloudUrl, resolveDefaultArtifactPath, resolveErrorReporter, resolveMetrics, resolveObjectStackHome, resolveRequestId };
|