@objectstack/runtime 5.1.0 → 6.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.d.cts CHANGED
@@ -1,15 +1,16 @@
1
1
  import { ObjectKernel, IHttpServer, ObjectKernelConfig, Plugin, PluginContext, RouteHandler, Middleware } from '@objectstack/core';
2
2
  export * from '@objectstack/core';
3
3
  export { ObjectKernel } from '@objectstack/core';
4
+ import { ClusterServicePluginOptions } from '@objectstack/service-cluster';
5
+ import { ClusterCapabilityConfigInput, ExecutionContext } from '@objectstack/spec/kernel';
4
6
  import { z } from 'zod';
5
7
  import * as Contracts from '@objectstack/spec/contracts';
6
8
  import { ISeedLoaderService, IDataEngine, IMetadataService } from '@objectstack/spec/contracts';
7
9
  import { SeedLoaderRequest, SeedLoaderResult, ObjectDependencyGraph, Dataset, SeedLoaderConfigInput, ExpressionBody, ScriptBody, HookBody, Hook } from '@objectstack/spec/data';
8
10
  import { MetricsRegistry, ErrorReporter } from '@objectstack/observability';
9
- export { CapturedError, ErrorReporter, InMemoryErrorReporter, InMemoryMetricsRegistry, MetricSample, MetricsRegistry, NoopErrorReporter, NoopMetricsRegistry, RUNTIME_METRICS } from '@objectstack/observability';
10
- import { ExecutionContext } from '@objectstack/spec/kernel';
11
+ export { CapturedError, ErrorReporter, InMemoryErrorReporter, InMemoryMetricsRegistry, MetricSample, MetricsRegistry, NoopErrorReporter, NoopMetricsRegistry, OBSERVABILITY_ERRORS_SERVICE, OBSERVABILITY_METRICS_SERVICE, RUNTIME_METRICS } from '@objectstack/observability';
11
12
  import { MiddlewareConfig, MiddlewareType } from '@objectstack/spec/system';
12
- import { ProjectArtifact } from '@objectstack/spec/cloud';
13
+ import { EnvironmentArtifact } from '@objectstack/spec/cloud';
13
14
  export { RestApiPluginConfig, RestServer, RouteEntry, RouteGroupBuilder, RouteManager, createRestApiPlugin } from '@objectstack/rest';
14
15
 
15
16
  interface RuntimeConfig {
@@ -23,6 +24,18 @@ interface RuntimeConfig {
23
24
  * Kernel Configuration
24
25
  */
25
26
  kernel?: ObjectKernelConfig;
27
+ /**
28
+ * Cluster service configuration.
29
+ *
30
+ * - Omit (default): a single-node `memory` cluster is auto-registered.
31
+ * - `false`: skip auto-registration entirely. Register your own
32
+ * `ClusterServicePlugin` if you need it later.
33
+ * - `ClusterCapabilityConfigInput`: forwarded to `defineCluster()`.
34
+ * - `{ cluster: IClusterService }`: bring your own instance.
35
+ *
36
+ * See `content/docs/concepts/cluster-semantics.mdx` for driver options.
37
+ */
38
+ cluster?: false | ClusterCapabilityConfigInput | ClusterServicePluginOptions;
26
39
  }
27
40
  /**
28
41
  * ObjectStack Runtime
@@ -41,6 +54,7 @@ interface RuntimeConfig {
41
54
  declare class Runtime {
42
55
  readonly kernel: ObjectKernel;
43
56
  constructor(config?: RuntimeConfig);
57
+ private normalizeClusterOptions;
44
58
  /**
45
59
  * Register a plugin
46
60
  */
@@ -61,13 +75,14 @@ declare const StandaloneStackConfigSchema: z.ZodObject<{
61
75
  databaseUrl: z.ZodOptional<z.ZodString>;
62
76
  databaseAuthToken: z.ZodOptional<z.ZodString>;
63
77
  databaseDriver: z.ZodOptional<z.ZodEnum<{
64
- sqlite: "sqlite";
65
- turso: "turso";
66
78
  memory: "memory";
67
79
  postgres: "postgres";
80
+ sqlite: "sqlite";
81
+ "sqlite-wasm": "sqlite-wasm";
82
+ turso: "turso";
68
83
  mongodb: "mongodb";
69
84
  }>>;
70
- projectId: z.ZodOptional<z.ZodString>;
85
+ environmentId: z.ZodOptional<z.ZodString>;
71
86
  artifactPath: z.ZodOptional<z.ZodString>;
72
87
  }, z.core.$strip>;
73
88
  type StandaloneStackConfig = z.input<typeof StandaloneStackConfigSchema>;
@@ -171,7 +186,7 @@ declare class DriverPlugin implements Plugin {
171
186
  * usages may omit this — no catalog hooks are emitted in that case.
172
187
  */
173
188
  interface AppPluginProjectContext {
174
- projectId: string;
189
+ environmentId: string;
175
190
  organizationId: string;
176
191
  projectName?: string;
177
192
  /** When the app comes from a package installation, the source package id. */
@@ -492,6 +507,75 @@ declare function parseTraceparent(value: unknown): TraceContext | undefined;
492
507
  */
493
508
  declare function formatTraceparent(ctx: TraceContext): string;
494
509
 
510
+ /**
511
+ * Options for {@link ObservabilityServicePlugin}.
512
+ *
513
+ * Either or both backends can be omitted; the omitted one resolves to
514
+ * the corresponding no-op exporter so consumers can always rely on the
515
+ * service being present.
516
+ */
517
+ interface ObservabilityServicePluginOptions {
518
+ /** Metrics backend (e.g. `ConsoleMetricsRegistry`, `OtlpHttpMetricsRegistry`). */
519
+ metrics?: MetricsRegistry;
520
+ /** Error reporter backend (e.g. Sentry adapter). */
521
+ errors?: ErrorReporter;
522
+ }
523
+ /**
524
+ * `ObservabilityServicePlugin` — registers the host's
525
+ * {@link MetricsRegistry} and {@link ErrorReporter} in the kernel
526
+ * service registry under the canonical names so any other plugin can
527
+ * look them up without each host having to thread observability config
528
+ * through every plugin constructor.
529
+ *
530
+ * Resolution chain other plugins should follow:
531
+ *
532
+ * 1. Explicit option on the plugin's own options object (escape
533
+ * hatch for tests / explicit wiring).
534
+ * 2. `ctx.getService(OBSERVABILITY_METRICS_SERVICE)`.
535
+ * 3. `NoopMetricsRegistry()` — never null.
536
+ *
537
+ * Register this plugin **before** any plugin that wants to consume the
538
+ * services (cache, storage, dispatcher), otherwise the consumer's
539
+ * `init` will fall through to the no-op default.
540
+ *
541
+ * @example
542
+ * ```ts
543
+ * import { ObjectKernel } from '@objectstack/core';
544
+ * import {
545
+ * ObservabilityServicePlugin,
546
+ * CacheServicePlugin,
547
+ * } from '@objectstack/runtime';
548
+ * import { ConsoleMetricsRegistry } from '@objectstack/observability';
549
+ *
550
+ * const kernel = new ObjectKernel();
551
+ * kernel.use(new ObservabilityServicePlugin({
552
+ * metrics: new ConsoleMetricsRegistry(),
553
+ * }));
554
+ * kernel.use(new CacheServicePlugin()); // picks metrics up automatically
555
+ * ```
556
+ */
557
+ declare class ObservabilityServicePlugin implements Plugin {
558
+ name: string;
559
+ version: string;
560
+ type: string;
561
+ private readonly options;
562
+ constructor(options?: ObservabilityServicePluginOptions);
563
+ init(ctx: PluginContext): Promise<void>;
564
+ }
565
+ /**
566
+ * Helper used by consumer plugins to resolve a metrics backend with
567
+ * the canonical fallback chain. Never throws; always returns a usable
568
+ * `MetricsRegistry`.
569
+ *
570
+ * @param ctx the consuming plugin's `PluginContext`
571
+ * @param override explicit option set on the consuming plugin (wins)
572
+ */
573
+ declare function resolveMetrics(ctx: PluginContext, override?: MetricsRegistry): MetricsRegistry;
574
+ /**
575
+ * Sibling of {@link resolveMetrics} for {@link ErrorReporter}.
576
+ */
577
+ declare function resolveErrorReporter(ctx: PluginContext, override?: ErrorReporter): ErrorReporter;
578
+
495
579
  interface DispatcherPluginConfig {
496
580
  /**
497
581
  * API path prefix for all endpoints.
@@ -504,16 +588,16 @@ interface DispatcherPluginConfig {
504
588
  * routes stay in lockstep with /data and /meta.
505
589
  *
506
590
  * When `enableProjectScoping` is true and `projectResolution` is:
507
- * - `required` — only `/projects/:projectId/...` variants are registered.
591
+ * - `required` — only `/environments/:environmentId/...` variants are registered.
508
592
  * - `optional` / `auto` — both unscoped and scoped variants are registered
509
- * (the scoped handler forwards `req.params.projectId` into context).
593
+ * (the scoped handler forwards `req.params.environmentId` into context).
510
594
  */
511
595
  scoping?: {
512
596
  enableProjectScoping?: boolean;
513
597
  projectResolution?: 'required' | 'optional' | 'auto';
514
598
  };
515
599
  /**
516
- * Enforce per-project membership (`sys_project_member`) on scoped
600
+ * Enforce per-project membership (`sys_environment_member`) on scoped
517
601
  * data-plane routes. Returns 403 for non-members unless they are
518
602
  * staff (platform org) or the project is the well-known system
519
603
  * project.
@@ -588,10 +672,10 @@ declare function createDispatcherPlugin(config?: DispatcherPluginConfig): Plugin
588
672
 
589
673
  /**
590
674
  * The well-known UUID for the built-in system project.
591
- * Kept in lockstep with `ProjectProvisioningService.provisionSystemProject`.
675
+ * Kept in lockstep with `ProjectProvisioningService.provisionSystemEnvironment`.
592
676
  */
593
- declare const SYSTEM_PROJECT_ID = "00000000-0000-0000-0000-000000000001";
594
- interface SystemProjectPluginConfig {
677
+ declare const SYSTEM_ENVIRONMENT_ID = "00000000-0000-0000-0000-000000000001";
678
+ interface SystemEnvironmentPluginConfig {
595
679
  /**
596
680
  * Service name that resolves to a `ProjectProvisioningService`-shaped
597
681
  * object. Defaults to `tenant.provisioning` (convention used by
@@ -609,8 +693,8 @@ interface SystemProjectPluginConfig {
609
693
  * System Project Bootstrap Plugin
610
694
  *
611
695
  * Ensures the built-in system project (well-known UUID
612
- * {@link SYSTEM_PROJECT_ID}) exists on the control plane the first time the
613
- * runtime starts. Calls are idempotent — `provisionSystemProject()` returns
696
+ * {@link SYSTEM_ENVIRONMENT_ID}) exists on the control plane the first time the
697
+ * runtime starts. Calls are idempotent — `provisionSystemEnvironment()` returns
614
698
  * the existing row when the project has already been created.
615
699
  *
616
700
  * Register AFTER the tenant service is available so the provisioning service
@@ -619,10 +703,10 @@ interface SystemProjectPluginConfig {
619
703
  * @example
620
704
  * ```ts
621
705
  * kernel.use(tenantPlugin);
622
- * kernel.use(createSystemProjectPlugin());
706
+ * kernel.use(createSystemEnvironmentPlugin());
623
707
  * ```
624
708
  */
625
- declare function createSystemProjectPlugin(config?: SystemProjectPluginConfig): Plugin;
709
+ declare function createSystemEnvironmentPlugin(config?: SystemEnvironmentPluginConfig): Plugin;
626
710
 
627
711
  /**
628
712
  * HttpServer - Unified HTTP Server Abstraction
@@ -711,16 +795,16 @@ declare class HttpServer implements IHttpServer {
711
795
  /**
712
796
  * Factory contract for instantiating a per-project {@link ObjectKernel}.
713
797
  *
714
- * Given a `projectId`, the factory is expected to:
715
- * 1. Read control-plane metadata (`sys_project` + credentials + subscribed packages).
798
+ * Given a `environmentId`, the factory is expected to:
799
+ * 1. Read control-plane metadata (`sys_environment` + credentials + subscribed packages).
716
800
  * 2. Construct a fresh `ObjectKernel` with project-scoped driver + plugins + Apps.
717
801
  * 3. Return a **bootstrapped** kernel ready to serve requests.
718
802
  */
719
- interface ProjectKernelFactory {
720
- create(projectId: string): Promise<ObjectKernel>;
803
+ interface EnvironmentKernelFactory {
804
+ create(environmentId: string): Promise<ObjectKernel>;
721
805
  }
722
806
  interface KernelManagerConfig {
723
- factory: ProjectKernelFactory;
807
+ factory: EnvironmentKernelFactory;
724
808
  /** Maximum number of kernels to keep resident. Defaults to 32. */
725
809
  maxSize?: number;
726
810
  /**
@@ -743,7 +827,7 @@ interface KernelManagerConfig {
743
827
  * Implements ADR-0003 multi-kernel scheduling: each project gets an
744
828
  * isolated kernel (App/plugin/metadata namespaces) that is lazily built
745
829
  * on first request and evicted under memory / idle pressure. Concurrent
746
- * `getOrCreate()` calls for the same projectId share a single in-flight
830
+ * `getOrCreate()` calls for the same environmentId share a single in-flight
747
831
  * factory invocation (singleflight).
748
832
  */
749
833
  declare class KernelManager {
@@ -754,36 +838,36 @@ declare class KernelManager {
754
838
  private readonly cache;
755
839
  private readonly pending;
756
840
  constructor(config: KernelManagerConfig);
757
- /** Returns the currently cached projectIds (ordered by insertion). */
841
+ /** Returns the currently cached environmentIds (ordered by insertion). */
758
842
  keys(): string[];
759
843
  /** Cache size for diagnostics. */
760
844
  get size(): number;
761
845
  /**
762
- * Resolve or construct the kernel for `projectId`.
846
+ * Resolve or construct the kernel for `environmentId`.
763
847
  *
764
848
  * - Cache hit (fresh): bumps `lastAccess` and returns immediately.
765
849
  * - Cache hit (TTL expired): evicts then falls through to factory.
766
850
  * - Cache miss: dedupes concurrent callers through `pending`.
767
851
  */
768
- getOrCreate(projectId: string): Promise<ObjectKernel>;
852
+ getOrCreate(environmentId: string): Promise<ObjectKernel>;
769
853
  /**
770
- * Evict the kernel for `projectId` and invoke `kernel.shutdown()`.
854
+ * Evict the kernel for `environmentId` and invoke `kernel.shutdown()`.
771
855
  * No-op when the entry is absent.
772
856
  */
773
- evict(projectId: string): Promise<void>;
857
+ evict(environmentId: string): Promise<void>;
774
858
  /** Evict all resident kernels. Used on runtime shutdown. */
775
859
  evictAll(): Promise<void>;
776
860
  private enforceMaxSize;
777
861
  }
778
862
 
779
- /** Minimal local interface — full ProjectScopeManager was removed in Phase R. */
780
- interface ProjectScopeManager {
781
- touch(projectId: string): void;
863
+ /** Minimal local interface — full EnvironmentScopeManager was removed in Phase R. */
864
+ interface EnvironmentScopeManager {
865
+ touch(environmentId: string): void;
782
866
  }
783
867
  interface HttpProtocolContext {
784
868
  request: any;
785
869
  response?: any;
786
- projectId?: string;
870
+ environmentId?: string;
787
871
  dataDriver?: any;
788
872
  /**
789
873
  * Identity envelope resolved by `resolveExecutionContext` and threaded
@@ -810,17 +894,17 @@ interface HttpDispatcherOptions {
810
894
  enforceProjectMembership?: boolean;
811
895
  /**
812
896
  * Optional {@link KernelManager}. When present, the dispatcher resolves
813
- * `context.projectId` first and then routes the request against the
814
- * project's dedicated kernel via `kernelManager.getOrCreate(projectId)`.
815
- * Requests that fail to resolve a projectId fall through to the
897
+ * `context.environmentId` first and then routes the request against the
898
+ * project's dedicated kernel via `kernelManager.getOrCreate(environmentId)`.
899
+ * Requests that fail to resolve a environmentId fall through to the
816
900
  * constructor-supplied kernel (self-hosted / legacy behavior).
817
901
  */
818
902
  kernelManager?: KernelManager;
819
903
  /**
820
- * Optional {@link ProjectScopeManager}. When present, `touch(projectId)` is
904
+ * Optional {@link EnvironmentScopeManager}. When present, `touch(environmentId)` is
821
905
  * called on every scoped request so idle projects are evicted after TTL.
822
906
  */
823
- scopeManager?: ProjectScopeManager;
907
+ scopeManager?: EnvironmentScopeManager;
824
908
  }
825
909
  /**
826
910
  * @deprecated Use `createDispatcherPlugin()` from `@objectstack/runtime` instead.
@@ -839,22 +923,22 @@ declare class HttpDispatcher {
839
923
  private scopeManager?;
840
924
  /**
841
925
  * When `true`, scoped data-plane routes enforce a
842
- * `sys_project_member` lookup and return 403 for non-members.
843
- * Defaults to `true` when a projectId is resolvable — legacy callers
926
+ * `sys_environment_member` lookup and return 403 for non-members.
927
+ * Defaults to `true` when a environmentId is resolvable — legacy callers
844
928
  * can opt out via the third constructor argument (see
845
929
  * `DispatcherConfig.enforceProjectMembership`).
846
930
  */
847
931
  private enforceMembership;
848
932
  /**
849
933
  * In-memory cache of positive membership checks, keyed by
850
- * `${projectId}:${userId}`. Entries expire 60 seconds after insertion
934
+ * `${environmentId}:${userId}`. Entries expire 60 seconds after insertion
851
935
  * — a short TTL is acceptable because a user whose access was just
852
936
  * revoked sees stale access for at most one minute.
853
937
  */
854
938
  private membershipCache;
855
939
  private static readonly MEMBERSHIP_CACHE_TTL_MS;
856
940
  /** Well-known system project id — bypassed for any authenticated user. */
857
- private static readonly SYSTEM_PROJECT_ID;
941
+ private static readonly SYSTEM_ENVIRONMENT_ID;
858
942
  /** Well-known platform org id — members bypass project membership. */
859
943
  private static readonly PLATFORM_ORG_ID;
860
944
  constructor(kernel: ObjectKernel, envRegistry?: any, options?: HttpDispatcherOptions);
@@ -875,22 +959,27 @@ declare class HttpDispatcher {
875
959
  private callData;
876
960
  /**
877
961
  * Parse a project UUID out of a scoped URL path such as
878
- * `/api/v1/projects/abc-123/data/task` or `/projects/abc-123/meta`.
962
+ * `/api/v1/environments/abc-123/data/task` or `/projects/abc-123/meta`.
963
+ * Returns `undefined` when the path does not match the scoped pattern.
964
+ */
965
+ /**
966
+ * Parse an environment UUID out of a scoped URL path such as
967
+ * `/api/v1/environments/abc-123/data/task` or `/environments/abc-123/meta`.
879
968
  * Returns `undefined` when the path does not match the scoped pattern.
880
969
  */
881
- private extractProjectIdFromPath;
970
+ private extractEnvironmentIdFromPath;
882
971
  /**
883
972
  * Resolve environment context for incoming request.
884
973
  *
885
974
  * Precedence:
886
- * 0. URL path matches `/projects/:projectId/...` OR request.params.projectId set by router
975
+ * 0. URL path matches `/environments/:environmentId/...` OR request.params.environmentId set by router
887
976
  * → envRegistry.resolveById(id)
888
977
  * 1. request.headers.host → envRegistry.resolveByHostname(host)
889
- * 2. request.headers['x-project-id'] → envRegistry.resolveById(id)
978
+ * 2. request.headers['x-environment-id'] → envRegistry.resolveById(id)
890
979
  * 3. session.activeEnvironmentId → envRegistry.resolveById(id)
891
980
  * 4. session.activeOrganizationId → find default project → envRegistry.resolveById(id)
892
- * 5. single-project default (registered by `createSingleProjectPlugin`)
893
- * → envRegistry.resolveById(defaultProject.projectId). Lets bare
981
+ * 5. single-environment default (registered by `createSingleEnvironmentPlugin`)
982
+ * → envRegistry.resolveById(defaultProject.environmentId). Lets bare
894
983
  * `/api/v1/data/...` URLs resolve to the lone project in
895
984
  * `cloudUrl: 'local'` deployments.
896
985
  *
@@ -900,13 +989,13 @@ declare class HttpDispatcher {
900
989
  private resolveEnvironmentContext;
901
990
  /**
902
991
  * Check whether the authenticated user is a member of
903
- * `context.projectId`. Runs after {@link resolveEnvironmentContext}
992
+ * `context.environmentId`. Runs after {@link resolveEnvironmentContext}
904
993
  * and is a no-op when:
905
994
  *
906
995
  * - Membership enforcement is disabled via the constructor.
907
996
  * - The route is control-plane (`/auth/*`, `/cloud/*`, `/health`,
908
997
  * `/discovery`) — already skipped upstream.
909
- * - No `projectId` was resolved (e.g. unscoped legacy routes).
998
+ * - No `environmentId` was resolved (e.g. unscoped legacy routes).
910
999
  * - The project is the well-known system project (bypassed so any
911
1000
  * authenticated user can read platform metadata).
912
1001
  * - The user's active organization is the platform org (staff).
@@ -1240,23 +1329,23 @@ declare class HttpDispatcher {
1240
1329
  * Cloud / Environment Control-Plane routes.
1241
1330
  *
1242
1331
  * - GET /cloud/drivers → list registered ObjectQL drivers (for env provisioning)
1243
- * - GET /cloud/projects → list
1244
- * - POST /cloud/projects → provision (driver: memory | turso | <any registered driver>)
1245
- * - GET /cloud/projects/:id → detail (+ db, credential, membership)
1246
- * - PATCH /cloud/projects/:id → update displayName / plan / status / isDefault / metadata
1247
- * - DELETE /cloud/projects/:id[?force=1] → cascade-delete the project (cred/member/package install rows + physical DB)
1332
+ * - GET /cloud/environments → list
1333
+ * - POST /cloud/environments → provision (driver: memory | turso | <any registered driver>)
1334
+ * - GET /cloud/environments/:id → detail (+ db, credential, membership)
1335
+ * - PATCH /cloud/environments/:id → update displayName / plan / status / isDefault / metadata
1336
+ * - DELETE /cloud/environments/:id[?force=1] → cascade-delete the project (cred/member/package install rows + physical DB)
1248
1337
  * - DELETE /cloud/organizations/:id → cascade-delete every project (and its DB) for the org, then drop the org
1249
- * - POST /cloud/projects/:id/retry → re-run provisioning for a failed environment
1250
- * - POST /cloud/projects/:id/activate → mark as active for session (stub)
1251
- * - POST /cloud/projects/:id/credentials/rotate → rotate credential
1252
- * - GET /cloud/projects/:id/members → list members
1253
- * - GET /cloud/projects/:id/packages → list installed packages
1254
- * - POST /cloud/projects/:id/packages → install package into env
1255
- * - GET /cloud/projects/:id/packages/:pkgId → get installation detail
1256
- * - PATCH /cloud/projects/:id/packages/:pkgId/enable → enable package
1257
- * - PATCH /cloud/projects/:id/packages/:pkgId/disable → disable package
1258
- * - DELETE /cloud/projects/:id/packages/:pkgId → uninstall (scope=platform forbidden)
1259
- * - POST /cloud/projects/:id/packages/:pkgId/upgrade → upgrade to newer version
1338
+ * - POST /cloud/environments/:id/retry → re-run provisioning for a failed environment
1339
+ * - POST /cloud/environments/:id/activate → mark as active for session (stub)
1340
+ * - POST /cloud/environments/:id/credentials/rotate → rotate credential
1341
+ * - GET /cloud/environments/:id/members → list members
1342
+ * - GET /cloud/environments/:id/packages → list installed packages
1343
+ * - POST /cloud/environments/:id/packages → install package into env
1344
+ * - GET /cloud/environments/:id/packages/:pkgId → get installation detail
1345
+ * - PATCH /cloud/environments/:id/packages/:pkgId/enable → enable package
1346
+ * - PATCH /cloud/environments/:id/packages/:pkgId/disable → disable package
1347
+ * - DELETE /cloud/environments/:id/packages/:pkgId → uninstall (scope=platform forbidden)
1348
+ * - POST /cloud/environments/:id/packages/:pkgId/upgrade → upgrade to newer version
1260
1349
  *
1261
1350
  * Driver binding
1262
1351
  * --------------
@@ -1268,11 +1357,11 @@ declare class HttpDispatcher {
1268
1357
  * If `driver` is omitted, the dispatcher auto-selects the first available
1269
1358
  * in preference order: turso → memory → any other registered driver.
1270
1359
  *
1271
- * Backed by ObjectQL sys_project / sys_project_credential /
1272
- * sys_project_member tables (registered by
1360
+ * Backed by ObjectQL sys_environment / sys_environment_credential /
1361
+ * sys_environment_member tables (registered by
1273
1362
  * `@objectstack/service-tenant`'s `createTenantPlugin`).
1274
1363
  * Physical database addressing (database_url, database_driver, etc.)
1275
- * is stored directly on the sys_project row.
1364
+ * is stored directly on the sys_environment row.
1276
1365
  */
1277
1366
  /**
1278
1367
  * Resolve the calling user id from the request session, if any.
@@ -1284,7 +1373,7 @@ declare class HttpDispatcher {
1284
1373
  /**
1285
1374
  * Cascade-delete a project: cred / member / package_installation rows,
1286
1375
  * then the physical database via the provisioning adapter, then the
1287
- * `sys_project` row itself. Used by both `DELETE /cloud/projects/:id`
1376
+ * `sys_environment` row itself. Used by both `DELETE /cloud/environments/:id`
1288
1377
  * and the org-cascade in `DELETE /cloud/organizations/:id`.
1289
1378
  *
1290
1379
  * Idempotent and best-effort: missing rows / unreachable adapters
@@ -1507,10 +1596,10 @@ declare function mergeRuntimeModule(bundle: any, artifactAbsPath: string, tag?:
1507
1596
  * The control plane is expected to expose two endpoints:
1508
1597
  *
1509
1598
  * GET {controlPlaneUrl}/api/v1/cloud/resolve-hostname?host={hostname}
1510
- * → { projectId: string, organizationId?: string, runtime?: ProjectRuntimeConfig }
1599
+ * → { environmentId: string, organizationId?: string, runtime?: EnvironmentRuntimeConfig }
1511
1600
  *
1512
- * GET {controlPlaneUrl}/api/v1/cloud/projects/:projectId/artifact
1513
- * → ProjectArtifactResponse (ProjectArtifact + optional `runtime` block)
1601
+ * GET {controlPlaneUrl}/api/v1/cloud/environments/:environmentId/artifact
1602
+ * → EnvironmentArtifactResponse (EnvironmentArtifact + optional `runtime` block)
1514
1603
  *
1515
1604
  * Both endpoints accept an optional `Authorization: Bearer <apiKey>`.
1516
1605
  *
@@ -1525,7 +1614,7 @@ declare function mergeRuntimeModule(bundle: any, artifactAbsPath: string, tag?:
1525
1614
  * connect to (this is *not* part of the developer-authored compiled
1526
1615
  * artifact — the control plane mints it when serving the API).
1527
1616
  */
1528
- interface ProjectRuntimeConfig {
1617
+ interface EnvironmentRuntimeConfig {
1529
1618
  organizationId?: string;
1530
1619
  hostname?: string;
1531
1620
  /** Driver type — e.g. `sqlite`, `postgres`, `turso`, `memory`. */
@@ -1546,18 +1635,18 @@ interface ProjectRuntimeConfig {
1546
1635
  * Hostname resolution response.
1547
1636
  */
1548
1637
  interface ResolvedHostname {
1549
- projectId: string;
1638
+ environmentId: string;
1550
1639
  organizationId?: string;
1551
1640
  /** Optional runtime config — when present, callers can skip the artifact fetch's runtime block. */
1552
- runtime?: ProjectRuntimeConfig;
1641
+ runtime?: EnvironmentRuntimeConfig;
1553
1642
  }
1554
1643
  /**
1555
- * Artifact response wrapping the spec's `ProjectArtifact` envelope plus
1644
+ * Artifact response wrapping the spec's `EnvironmentArtifact` envelope plus
1556
1645
  * an optional `runtime` block carrying the project's database
1557
1646
  * connection details.
1558
1647
  */
1559
- interface ProjectArtifactResponse extends ProjectArtifact {
1560
- runtime?: ProjectRuntimeConfig;
1648
+ interface EnvironmentArtifactResponse extends EnvironmentArtifact {
1649
+ runtime?: EnvironmentRuntimeConfig;
1561
1650
  }
1562
1651
  interface ArtifactApiClientConfig {
1563
1652
  /** Control-plane base URL (no trailing slash). */
@@ -1603,32 +1692,32 @@ declare class ArtifactApiClient {
1603
1692
  * independently (the cache key includes the commit id) so the preview
1604
1693
  * runtime can hold multiple versions in memory simultaneously.
1605
1694
  */
1606
- fetchArtifact(projectId: string, opts?: {
1695
+ fetchArtifact(environmentId: string, opts?: {
1607
1696
  commit?: string;
1608
- }): Promise<ProjectArtifactResponse | null>;
1697
+ }): Promise<EnvironmentArtifactResponse | null>;
1609
1698
  /**
1610
1699
  * Resolve an 8-hex project short id (first 8 hex chars of the UUID,
1611
- * dashes stripped) to the full projectId. Used by the preview
1700
+ * dashes stripped) to the full environmentId. Used by the preview
1612
1701
  * runtime, which encodes project ids in subdomains.
1613
1702
  *
1614
1703
  * Returns `null` on 404 or ambiguity (the control plane returns 409
1615
1704
  * if the prefix matches more than one project).
1616
1705
  */
1617
1706
  lookupProjectByShortId(shortId: string): Promise<{
1618
- projectId: string;
1707
+ environmentId: string;
1619
1708
  organizationId?: string;
1620
1709
  } | null>;
1621
1710
  /**
1622
1711
  * Fetch the head commit of a branch. Returns the commit id (and the
1623
1712
  * matching revision row's `published_at` for cache-validity checks).
1624
- * Reuses the existing `GET /cloud/projects/:id/branches` endpoint.
1713
+ * Reuses the existing `GET /cloud/environments/:id/branches` endpoint.
1625
1714
  */
1626
- fetchBranchHead(projectId: string, branchName: string): Promise<{
1715
+ fetchBranchHead(environmentId: string, branchName: string): Promise<{
1627
1716
  commitId: string;
1628
1717
  publishedAt?: string | null;
1629
1718
  } | null>;
1630
1719
  /** Drop cached entries for a project (and any matching hostname). */
1631
- invalidate(projectId: string): void;
1720
+ invalidate(environmentId: string): void;
1632
1721
  /** Drop everything. Used on shutdown / hot-reload. */
1633
1722
  clear(): void;
1634
1723
  private request;
@@ -1644,9 +1733,9 @@ interface FileArtifactApiClientConfig {
1644
1733
  artifactPath?: string;
1645
1734
  /**
1646
1735
  * Project id every hostname maps to. Defaults to
1647
- * `process.env.OS_PROJECT_ID` or `'proj_local'`.
1736
+ * `process.env.OS_ENVIRONMENT_ID` or `'proj_local'`.
1648
1737
  */
1649
- projectId?: string;
1738
+ environmentId?: string;
1650
1739
  /**
1651
1740
  * Organization id surfaced alongside the project. Defaults to
1652
1741
  * `process.env.OS_ORGANIZATION_ID` or `'org_local'`.
@@ -1656,9 +1745,9 @@ interface FileArtifactApiClientConfig {
1656
1745
  * Override runtime config. When unset, the client tries to derive
1657
1746
  * one from the artifact's `datasources` array; if that fails it
1658
1747
  * falls back to a local-file SQLite DB at
1659
- * `<cwd>/.objectstack/data/<projectId>.db`.
1748
+ * `<cwd>/.objectstack/data/<environmentId>.db`.
1660
1749
  */
1661
- runtime?: ProjectRuntimeConfig;
1750
+ runtime?: EnvironmentRuntimeConfig;
1662
1751
  /**
1663
1752
  * Reload the artifact on every fetch instead of caching the first
1664
1753
  * read. Useful when iterating on a project's metadata without
@@ -1674,7 +1763,7 @@ interface FileArtifactApiClientConfig {
1674
1763
  }
1675
1764
  declare class FileArtifactApiClient {
1676
1765
  private readonly artifactPath;
1677
- private readonly projectId;
1766
+ private readonly environmentId;
1678
1767
  private readonly organizationId;
1679
1768
  private readonly overrideRuntime?;
1680
1769
  private readonly watch;
@@ -1682,18 +1771,18 @@ declare class FileArtifactApiClient {
1682
1771
  private cached?;
1683
1772
  constructor(config?: FileArtifactApiClientConfig);
1684
1773
  resolveHostname(_host: string): Promise<ResolvedHostname | null>;
1685
- fetchArtifact(_projectId: string, _opts?: {
1774
+ fetchArtifact(_environmentId: string, _opts?: {
1686
1775
  commit?: string;
1687
- }): Promise<ProjectArtifactResponse | null>;
1776
+ }): Promise<EnvironmentArtifactResponse | null>;
1688
1777
  lookupProjectByShortId(_shortId: string): Promise<{
1689
- projectId: string;
1778
+ environmentId: string;
1690
1779
  organizationId?: string;
1691
1780
  } | null>;
1692
- fetchBranchHead(_projectId: string, _branchName: string): Promise<{
1781
+ fetchBranchHead(_environmentId: string, _branchName: string): Promise<{
1693
1782
  commitId: string;
1694
1783
  publishedAt?: string | null;
1695
1784
  } | null>;
1696
- invalidate(_projectId: string): void;
1785
+ invalidate(_environmentId: string): void;
1697
1786
  clear(): void;
1698
1787
  private loadArtifact;
1699
1788
  private readRuntimeFromArtifact;
@@ -1745,6 +1834,155 @@ interface ObjectOSStackResult {
1745
1834
  }
1746
1835
  declare function createObjectOSStack(config: ObjectOSStackConfig): Promise<ObjectOSStackResult>;
1747
1836
 
1837
+ /**
1838
+ * MarketplaceProxyPlugin
1839
+ *
1840
+ * Forwards `GET /api/v1/marketplace/*` from a tenant ObjectOS runtime to
1841
+ * the configured ObjectStack Cloud control-plane URL. The cloud endpoint
1842
+ * (`packages/service-cloud/src/routes/marketplace.ts`) is unauthenticated
1843
+ * and only exposes packages whose owner has opted in to the public catalog
1844
+ * (`sys_package.marketplace_listed = true`) — so the proxy passes through
1845
+ * without any credentials.
1846
+ *
1847
+ * Why proxy instead of direct browser → cloud:
1848
+ * - The Console SPA stays on the tenant origin, so no CORS configuration
1849
+ * is required on the cloud side.
1850
+ * - Local-dev `os serve` works regardless of whether the developer's
1851
+ * browser has cookies for cloud.objectos.app.
1852
+ * - Adds a single, easily auditable network seam between tenant and
1853
+ * control plane.
1854
+ *
1855
+ * Install is NOT proxied here. Installing a package mutates control-plane
1856
+ * state and requires a cloud session + active organization context — the
1857
+ * Console SPA performs install by opening the cloud's install dialog in a
1858
+ * new tab so the user authenticates against cloud directly. A future
1859
+ * iteration may introduce a delegated install token; until then, browse
1860
+ * here and install on cloud.
1861
+ */
1862
+
1863
+ interface MarketplaceProxyPluginConfig {
1864
+ /**
1865
+ * Control-plane base URL (e.g. https://cloud.objectos.app). When the
1866
+ * caller passes nothing AND the runtime has no OS_CLOUD_URL set, the
1867
+ * plugin falls back to the public ObjectStack-operated cloud so that
1868
+ * `objectstack dev` can browse the marketplace out of the box. Set
1869
+ * OS_CLOUD_URL=off (or `local`) to opt out — the plugin then mounts
1870
+ * a stub that responds 503 and the SPA renders an empty-state
1871
+ * explaining marketplace is unavailable in this runtime.
1872
+ */
1873
+ controlPlaneUrl?: string;
1874
+ }
1875
+ declare class MarketplaceProxyPlugin implements Plugin {
1876
+ readonly name = "com.objectstack.runtime.marketplace-proxy";
1877
+ readonly version = "1.0.0";
1878
+ private readonly cloudUrl;
1879
+ constructor(config?: MarketplaceProxyPluginConfig);
1880
+ init: (_ctx: PluginContext) => Promise<void>;
1881
+ start: (ctx: PluginContext) => Promise<void>;
1882
+ }
1883
+
1884
+ interface MarketplaceInstallLocalPluginConfig {
1885
+ /** Cloud control-plane base URL. When unset, falls back to OS_CLOUD_URL
1886
+ * and then to the public ObjectStack cloud so a fresh `objectstack dev`
1887
+ * can install from the marketplace without configuration. Set
1888
+ * OS_CLOUD_URL=off to disable (the install endpoint then returns 503). */
1889
+ controlPlaneUrl?: string;
1890
+ /** Override the on-disk cache directory. Defaults to
1891
+ * `<cwd>/.objectstack/installed-packages`. */
1892
+ storageDir?: string;
1893
+ }
1894
+ declare class MarketplaceInstallLocalPlugin implements Plugin {
1895
+ readonly name = "com.objectstack.runtime.marketplace-install-local";
1896
+ readonly version = "1.0.0";
1897
+ private readonly cloudUrl;
1898
+ private readonly storageDir;
1899
+ constructor(config?: MarketplaceInstallLocalPluginConfig);
1900
+ init: (_ctx: PluginContext) => Promise<void>;
1901
+ start: (ctx: PluginContext) => Promise<void>;
1902
+ /**
1903
+ * Re-register every cached manifest with the kernel's manifest service.
1904
+ * Safe to call on a kernel that already has the same manifest_id (the
1905
+ * underlying ObjectQL registry overwrites by id, but we still warn so
1906
+ * a developer can spot the dev-time clash between their config.ts and
1907
+ * a marketplace package).
1908
+ */
1909
+ private rehydrate;
1910
+ private handleInstall;
1911
+ private handleList;
1912
+ private handleUninstall;
1913
+ /**
1914
+ * Detect whether `manifestId` is already known to the kernel and classify
1915
+ * the source so we can refuse vs upgrade gracefully.
1916
+ *
1917
+ * 'none' — fresh install
1918
+ * 'marketplace' — previously installed by this plugin (allow upgrade)
1919
+ * 'user-code' — defined by AppPlugin from objectstack.config.ts
1920
+ * (refuse to avoid silently overwriting authored code)
1921
+ */
1922
+ private findConflict;
1923
+ /**
1924
+ * Pull a userId out of the request's better-auth session, if any.
1925
+ * Returns null when there is no signed-in user. v1 does not check
1926
+ * admin role — UI gating + the auth requirement is sufficient for
1927
+ * dev / single-tenant runtimes. Stricter checks can be layered on
1928
+ * via a middleware in cloud-hosted multi-tenant deployments.
1929
+ */
1930
+ /**
1931
+ * Replicate the start-time side-effects that AppPlugin runs for
1932
+ * statically-declared apps but the `manifest` service does NOT:
1933
+ *
1934
+ * 1. Load `manifest.translations` (array of `Record<locale, data>`)
1935
+ * into the i18n service — auto-creating an in-memory fallback if
1936
+ * none is registered, matching AppPlugin's behaviour.
1937
+ *
1938
+ * 2. Merge `manifest.data` (an array of seed datasets) into the
1939
+ * kernel's `seed-datasets` service so SecurityPlugin's per-org
1940
+ * replay middleware picks them up on every future
1941
+ * sys_organization insert.
1942
+ *
1943
+ * 3. When `seedNow=true`, also run the seed immediately so the user
1944
+ * sees demo data without having to create a new org:
1945
+ * • single-tenant: run SeedLoaderService inline (mirrors
1946
+ * AppPlugin single-tenant branch)
1947
+ * • multi-tenant: invoke `seed-replayer` for the caller's
1948
+ * active org (resolved from the request session)
1949
+ *
1950
+ * Errors are logged but never thrown — install succeeds even if
1951
+ * post-register side-effects partially fail (the manifest itself is
1952
+ * already registered + cached). Returns a small summary for the
1953
+ * response envelope.
1954
+ */
1955
+ private applySideEffects;
1956
+ /**
1957
+ * Best-effort active-org resolution. Reads the better-auth session
1958
+ * (same path as requireAuthenticatedUser) and returns
1959
+ * `session.activeOrganizationId`, falling back to the user's first
1960
+ * org membership.
1961
+ */
1962
+ private resolveActiveOrgId;
1963
+ private requireAuthenticatedUser;
1964
+ private readAll;
1965
+ }
1966
+
1967
+ /**
1968
+ * Shared marketplace / cloud control-plane defaults.
1969
+ *
1970
+ * Centralised so every plugin + the CLI auto-inject path agree on
1971
+ * "what cloud URL do we mean when the user didn't set OS_CLOUD_URL?".
1972
+ * Until we have a competing public hosted cloud, this points at the
1973
+ * ObjectStack-operated control plane so a vanilla `objectstack dev` can
1974
+ * browse the marketplace out of the box.
1975
+ */
1976
+ declare const DEFAULT_CLOUD_URL = "https://cloud.objectos.app";
1977
+ /**
1978
+ * Resolve the effective control-plane URL from an explicit constructor
1979
+ * value, the OS_CLOUD_URL env var, or the default. Returns an empty
1980
+ * string when the caller explicitly disabled cloud with
1981
+ * `OS_CLOUD_URL=off` / `local` — callers should treat that as
1982
+ * "marketplace unavailable on this runtime".
1983
+ */
1984
+ declare function resolveCloudUrl(explicit?: string | null): string;
1985
+
1748
1986
  /**
1749
1987
  * Per-project driver registry contract.
1750
1988
  *
@@ -1764,22 +2002,22 @@ type IDataDriver$1 = Contracts.IDataDriver;
1764
2002
  interface EnvironmentDriverRegistry {
1765
2003
  /** Resolve a project by hostname. Returns `null` when unknown. */
1766
2004
  resolveByHostname(host: string): Promise<{
1767
- projectId: string;
2005
+ environmentId: string;
1768
2006
  driver: IDataDriver$1;
1769
2007
  } | null>;
1770
2008
  /** Resolve a project's driver by ID. Returns `null` when unknown. */
1771
- resolveById(projectId: string): Promise<IDataDriver$1 | null>;
2009
+ resolveById(environmentId: string): Promise<IDataDriver$1 | null>;
1772
2010
  /**
1773
2011
  * Look up the cached project row + driver by ID without triggering a
1774
2012
  * remote/file fetch. Returns the full cached entry when fresh.
1775
2013
  */
1776
- peekById(projectId: string): {
1777
- projectId: string;
2014
+ peekById(environmentId: string): {
2015
+ environmentId: string;
1778
2016
  driver: IDataDriver$1;
1779
2017
  project: any;
1780
2018
  } | null;
1781
2019
  /** Drop cached entries for the given project. */
1782
- invalidate(projectId: string): void;
2020
+ invalidate(environmentId: string): void;
1783
2021
  }
1784
2022
 
1785
2023
  /**
@@ -1788,11 +2026,11 @@ interface EnvironmentDriverRegistry {
1788
2026
  *
1789
2027
  * Mirrors {@link DefaultEnvironmentDriverRegistry} from `environment-registry.ts`
1790
2028
  * but does **not** read from a local control-plane database. Hostname →
1791
- * projectId resolution and per-project runtime config (database URL /
2029
+ * environmentId resolution and per-project runtime config (database URL /
1792
2030
  * driver) come from the control plane API.
1793
2031
  *
1794
2032
  * The cached `project` payload exposed by `peekById()` is shaped to look
1795
- * like a `sys_project` row so callers downstream (notably
2033
+ * like a `sys_environment` row so callers downstream (notably
1796
2034
  * `ArtifactKernelFactory`) can read `id`, `organization_id`,
1797
2035
  * `database_url` and `database_driver` without branching.
1798
2036
  */
@@ -1818,16 +2056,16 @@ declare class ArtifactEnvironmentRegistry implements EnvironmentDriverRegistry {
1818
2056
  private readonly pending;
1819
2057
  constructor(config: ArtifactEnvironmentRegistryConfig);
1820
2058
  resolveByHostname(host: string): Promise<{
1821
- projectId: string;
2059
+ environmentId: string;
1822
2060
  driver: IDataDriver;
1823
2061
  } | null>;
1824
- resolveById(projectId: string): Promise<IDataDriver | null>;
1825
- peekById(projectId: string): {
1826
- projectId: string;
2062
+ resolveById(environmentId: string): Promise<IDataDriver | null>;
2063
+ peekById(environmentId: string): {
2064
+ environmentId: string;
1827
2065
  driver: IDataDriver;
1828
2066
  project: any;
1829
2067
  } | null;
1830
- invalidate(projectId: string): void;
2068
+ invalidate(environmentId: string): void;
1831
2069
  private buildCacheEntry;
1832
2070
  }
1833
2071
 
@@ -1844,19 +2082,19 @@ interface ArtifactKernelFactoryConfig {
1844
2082
  kernelConfig?: ConstructorParameters<typeof ObjectKernel>[0];
1845
2083
  /**
1846
2084
  * Base secret used to derive per-project AuthPlugin secrets via
1847
- * HKDF-style HMAC-SHA256(baseSecret, projectId). Falls back to
2085
+ * HKDF-style HMAC-SHA256(baseSecret, environmentId). Falls back to
1848
2086
  * `process.env.OS_AUTH_SECRET` / `AUTH_SECRET` at construction time.
1849
2087
  */
1850
2088
  authBaseSecret?: string;
1851
2089
  }
1852
- declare class ArtifactKernelFactory implements ProjectKernelFactory {
2090
+ declare class ArtifactKernelFactory implements EnvironmentKernelFactory {
1853
2091
  private readonly client;
1854
2092
  private readonly envRegistry;
1855
2093
  private readonly logger;
1856
2094
  private readonly kernelConfig?;
1857
2095
  private readonly authBaseSecret;
1858
2096
  constructor(config: ArtifactKernelFactoryConfig);
1859
- create(projectId: string): Promise<ObjectKernel>;
2097
+ create(environmentId: string): Promise<ObjectKernel>;
1860
2098
  }
1861
2099
 
1862
2100
  /**
@@ -1902,10 +2140,10 @@ declare const PLATFORM_SSO_PROVIDER_ID = "objectstack-cloud";
1902
2140
  * Derive the per-project OAuth client_id used in `sys_oauth_application`
1903
2141
  * (cloud side) and {@link genericOAuth} config (project side).
1904
2142
  */
1905
- declare function derivePlatformSsoClientId(projectId: string): string;
2143
+ declare function derivePlatformSsoClientId(environmentId: string): string;
1906
2144
  /**
1907
2145
  * Derive the per-project OAuth client_secret deterministically from the
1908
- * shared master secret. HMAC-SHA256(baseSecret, 'oauth-client:' + projectId)
2146
+ * shared master secret. HMAC-SHA256(baseSecret, 'oauth-client:' + environmentId)
1909
2147
  * yields a 64-char hex string that is:
1910
2148
  * - stable across container cold-starts (no DB lookup needed)
1911
2149
  * - independent per project (compromising one does not compromise others)
@@ -1917,7 +2155,7 @@ declare function derivePlatformSsoClientId(projectId: string): string;
1917
2155
  * defaults to `storeClientSecret: 'hashed'` (SHA-256 + base64url) when the JWT
1918
2156
  * plugin is enabled, and looks up the row by hashing the presented secret.
1919
2157
  */
1920
- declare function derivePlatformSsoClientSecret(baseSecret: string, projectId: string): string;
2158
+ declare function derivePlatformSsoClientSecret(baseSecret: string, environmentId: string): string;
1921
2159
  /**
1922
2160
  * Build the redirect_uri better-auth's `genericOAuth` plugin will use
1923
2161
  * when the project kernel mounts the provider with id
@@ -1939,7 +2177,7 @@ interface SeedPlatformSsoClientOptions {
1939
2177
  update: (object: string, data: any, where: any, opts?: any) => Promise<any>;
1940
2178
  };
1941
2179
  /** Project id (also used to derive client_id + client_secret). */
1942
- projectId: string;
2180
+ environmentId: string;
1943
2181
  /**
1944
2182
  * Project hostname (e.g. `acme-crm.objectos.app`). Optional — projects
1945
2183
  * may be created before a hostname is assigned, in which case no
@@ -1962,7 +2200,7 @@ interface SeedPlatformSsoClientOptions {
1962
2200
  }
1963
2201
  /**
1964
2202
  * Idempotently upsert a `sys_oauth_application` row for the given project.
1965
- * Re-running with the same `projectId` is a no-op (the deterministic
2203
+ * Re-running with the same `environmentId` is a no-op (the deterministic
1966
2204
  * `client_id` is uniquely indexed and the secret derivation is stable).
1967
2205
  * Re-running with a new `hostname` adds the new redirect_uri to the
1968
2206
  * existing row's JSON array.
@@ -1980,7 +2218,7 @@ interface BackfillPlatformSsoClientsOptions {
1980
2218
  limit?: number;
1981
2219
  }
1982
2220
  /**
1983
- * Scan `sys_project` and ensure every active project has a corresponding
2221
+ * Scan `sys_environment` and ensure every active project has a corresponding
1984
2222
  * `sys_oauth_application` row. Intended to run once at cloud boot — the
1985
2223
  * happy path is dominated by the project-create hook
1986
2224
  * ({@link seedPlatformSsoClient}); the backfill exists so projects
@@ -1992,7 +2230,7 @@ declare function backfillPlatformSsoClients(opts: BackfillPlatformSsoClientsOpti
1992
2230
  seeded: number;
1993
2231
  alreadyExisted: number;
1994
2232
  failures: Array<{
1995
- projectId: string;
2233
+ environmentId: string;
1996
2234
  error: string;
1997
2235
  }>;
1998
2236
  }>;
@@ -2227,4 +2465,4 @@ declare function actionBodyRunnerFactory(runner: ScriptRunner, opts: FactoryOpti
2227
2465
  timeoutMs?: number;
2228
2466
  }) => ((actionCtx: any) => Promise<unknown>) | undefined;
2229
2467
 
2230
- export { AppPlugin, ArtifactApiClient, type ArtifactApiClientConfig, ArtifactEnvironmentRegistry, type ArtifactEnvironmentRegistryConfig, ArtifactKernelFactory, type ArtifactKernelFactoryConfig, AuthProxyPlugin, type BackfillPlatformSsoClientsOptions, DEFAULT_RATE_LIMITS, type DefaultHostConfigOptions, type DefaultHostConfigResult, type DispatcherPluginConfig, DriverPlugin, type EnvironmentDriverRegistry, FileArtifactApiClient, type FileArtifactApiClientConfig, HttpDispatcher, type HttpDispatcherResult, type HttpProtocolContext, HttpServer, KernelManager, type KernelManagerConfig, type LoadArtifactBundleOptions, MiddlewareManager, type ObjectOSStackConfig, type ObjectOSStackResult, PLATFORM_SSO_PROVIDER_ID, type ProjectArtifactResponse, type ProjectKernelFactory, type ProjectRuntimeConfig, QuickJSScriptRunner, type QuickJSScriptRunnerOptions, type RateLimitBucketConfig, type RateLimitDecision, type RateLimitDefaults, type RateLimitStore, RateLimiter, type ResolvedHostname, Runtime, type RuntimeConfig, SYSTEM_PROJECT_ID, SandboxError, type ScriptContext, type ScriptOrigin, type ScriptResult, type ScriptRunOptions, type ScriptRunner, type SecurityHeadersOptions, SeedLoaderService, type SeedPlatformSsoClientOptions, type StandaloneStackConfig, type StandaloneStackResult, type SystemProjectPluginConfig, type TraceContext, UnimplementedScriptRunner, actionBodyRunnerFactory, backfillPlatformSsoClients, buildPlatformSsoRedirectUri, buildSecurityHeaders, collectBundleActions, collectBundleFunctions, collectBundleHooks, createDefaultHostConfig, createDispatcherPlugin, createObjectOSStack, createStandaloneStack, createSystemProjectPlugin, derivePlatformSsoClientId, derivePlatformSsoClientSecret, extractRequestId, formatTraceparent, generateRequestId, hookBodyRunnerFactory, isHttpUrl, loadArtifactBundle, mergeRuntimeModule, parseTraceparent, readArtifactSource, resolveDefaultArtifactPath, resolveRequestId, seedPlatformSsoClient };
2468
+ export { AppPlugin, ArtifactApiClient, type ArtifactApiClientConfig, ArtifactEnvironmentRegistry, type ArtifactEnvironmentRegistryConfig, ArtifactKernelFactory, type ArtifactKernelFactoryConfig, AuthProxyPlugin, type BackfillPlatformSsoClientsOptions, DEFAULT_CLOUD_URL, DEFAULT_RATE_LIMITS, type DefaultHostConfigOptions, type DefaultHostConfigResult, type DispatcherPluginConfig, DriverPlugin, type EnvironmentArtifactResponse, type EnvironmentDriverRegistry, type EnvironmentKernelFactory, type EnvironmentRuntimeConfig, FileArtifactApiClient, type FileArtifactApiClientConfig, HttpDispatcher, type HttpDispatcherResult, type HttpProtocolContext, HttpServer, KernelManager, type KernelManagerConfig, type LoadArtifactBundleOptions, MarketplaceInstallLocalPlugin, type MarketplaceInstallLocalPluginConfig, MarketplaceProxyPlugin, type MarketplaceProxyPluginConfig, MiddlewareManager, type ObjectOSStackConfig, type ObjectOSStackResult, ObservabilityServicePlugin, type ObservabilityServicePluginOptions, PLATFORM_SSO_PROVIDER_ID, QuickJSScriptRunner, type QuickJSScriptRunnerOptions, type RateLimitBucketConfig, type RateLimitDecision, type RateLimitDefaults, type RateLimitStore, RateLimiter, type ResolvedHostname, Runtime, type RuntimeConfig, SYSTEM_ENVIRONMENT_ID, SandboxError, type ScriptContext, type ScriptOrigin, type ScriptResult, type ScriptRunOptions, type ScriptRunner, type SecurityHeadersOptions, SeedLoaderService, type SeedPlatformSsoClientOptions, type StandaloneStackConfig, type StandaloneStackResult, type SystemEnvironmentPluginConfig, type TraceContext, UnimplementedScriptRunner, actionBodyRunnerFactory, backfillPlatformSsoClients, buildPlatformSsoRedirectUri, buildSecurityHeaders, collectBundleActions, collectBundleFunctions, collectBundleHooks, createDefaultHostConfig, createDispatcherPlugin, createObjectOSStack, createStandaloneStack, createSystemEnvironmentPlugin, derivePlatformSsoClientId, derivePlatformSsoClientSecret, extractRequestId, formatTraceparent, generateRequestId, hookBodyRunnerFactory, isHttpUrl, loadArtifactBundle, mergeRuntimeModule, parseTraceparent, readArtifactSource, resolveCloudUrl, resolveDefaultArtifactPath, resolveErrorReporter, resolveMetrics, resolveRequestId, seedPlatformSsoClient };