@objectstack/runtime 5.0.0 → 5.2.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,13 +1,14 @@
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
13
  import { ProjectArtifact } from '@objectstack/spec/cloud';
13
14
  export { RestApiPluginConfig, RestServer, RouteEntry, RouteGroupBuilder, RouteManager, createRestApiPlugin } from '@objectstack/rest';
@@ -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,10 +75,10 @@ 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
+ turso: "turso";
68
82
  mongodb: "mongodb";
69
83
  }>>;
70
84
  projectId: z.ZodOptional<z.ZodString>;
@@ -492,6 +506,75 @@ declare function parseTraceparent(value: unknown): TraceContext | undefined;
492
506
  */
493
507
  declare function formatTraceparent(ctx: TraceContext): string;
494
508
 
509
+ /**
510
+ * Options for {@link ObservabilityServicePlugin}.
511
+ *
512
+ * Either or both backends can be omitted; the omitted one resolves to
513
+ * the corresponding no-op exporter so consumers can always rely on the
514
+ * service being present.
515
+ */
516
+ interface ObservabilityServicePluginOptions {
517
+ /** Metrics backend (e.g. `ConsoleMetricsRegistry`, `OtlpHttpMetricsRegistry`). */
518
+ metrics?: MetricsRegistry;
519
+ /** Error reporter backend (e.g. Sentry adapter). */
520
+ errors?: ErrorReporter;
521
+ }
522
+ /**
523
+ * `ObservabilityServicePlugin` — registers the host's
524
+ * {@link MetricsRegistry} and {@link ErrorReporter} in the kernel
525
+ * service registry under the canonical names so any other plugin can
526
+ * look them up without each host having to thread observability config
527
+ * through every plugin constructor.
528
+ *
529
+ * Resolution chain other plugins should follow:
530
+ *
531
+ * 1. Explicit option on the plugin's own options object (escape
532
+ * hatch for tests / explicit wiring).
533
+ * 2. `ctx.getService(OBSERVABILITY_METRICS_SERVICE)`.
534
+ * 3. `NoopMetricsRegistry()` — never null.
535
+ *
536
+ * Register this plugin **before** any plugin that wants to consume the
537
+ * services (cache, storage, dispatcher), otherwise the consumer's
538
+ * `init` will fall through to the no-op default.
539
+ *
540
+ * @example
541
+ * ```ts
542
+ * import { ObjectKernel } from '@objectstack/core';
543
+ * import {
544
+ * ObservabilityServicePlugin,
545
+ * CacheServicePlugin,
546
+ * } from '@objectstack/runtime';
547
+ * import { ConsoleMetricsRegistry } from '@objectstack/observability';
548
+ *
549
+ * const kernel = new ObjectKernel();
550
+ * kernel.use(new ObservabilityServicePlugin({
551
+ * metrics: new ConsoleMetricsRegistry(),
552
+ * }));
553
+ * kernel.use(new CacheServicePlugin()); // picks metrics up automatically
554
+ * ```
555
+ */
556
+ declare class ObservabilityServicePlugin implements Plugin {
557
+ name: string;
558
+ version: string;
559
+ type: string;
560
+ private readonly options;
561
+ constructor(options?: ObservabilityServicePluginOptions);
562
+ init(ctx: PluginContext): Promise<void>;
563
+ }
564
+ /**
565
+ * Helper used by consumer plugins to resolve a metrics backend with
566
+ * the canonical fallback chain. Never throws; always returns a usable
567
+ * `MetricsRegistry`.
568
+ *
569
+ * @param ctx the consuming plugin's `PluginContext`
570
+ * @param override explicit option set on the consuming plugin (wins)
571
+ */
572
+ declare function resolveMetrics(ctx: PluginContext, override?: MetricsRegistry): MetricsRegistry;
573
+ /**
574
+ * Sibling of {@link resolveMetrics} for {@link ErrorReporter}.
575
+ */
576
+ declare function resolveErrorReporter(ctx: PluginContext, override?: ErrorReporter): ErrorReporter;
577
+
495
578
  interface DispatcherPluginConfig {
496
579
  /**
497
580
  * API path prefix for all endpoints.
@@ -1745,6 +1828,155 @@ interface ObjectOSStackResult {
1745
1828
  }
1746
1829
  declare function createObjectOSStack(config: ObjectOSStackConfig): Promise<ObjectOSStackResult>;
1747
1830
 
1831
+ /**
1832
+ * MarketplaceProxyPlugin
1833
+ *
1834
+ * Forwards `GET /api/v1/marketplace/*` from a tenant ObjectOS runtime to
1835
+ * the configured ObjectStack Cloud control-plane URL. The cloud endpoint
1836
+ * (`packages/service-cloud/src/routes/marketplace.ts`) is unauthenticated
1837
+ * and only exposes packages whose owner has opted in to the public catalog
1838
+ * (`sys_package.marketplace_listed = true`) — so the proxy passes through
1839
+ * without any credentials.
1840
+ *
1841
+ * Why proxy instead of direct browser → cloud:
1842
+ * - The Console SPA stays on the tenant origin, so no CORS configuration
1843
+ * is required on the cloud side.
1844
+ * - Local-dev `os serve` works regardless of whether the developer's
1845
+ * browser has cookies for cloud.objectos.app.
1846
+ * - Adds a single, easily auditable network seam between tenant and
1847
+ * control plane.
1848
+ *
1849
+ * Install is NOT proxied here. Installing a package mutates control-plane
1850
+ * state and requires a cloud session + active organization context — the
1851
+ * Console SPA performs install by opening the cloud's install dialog in a
1852
+ * new tab so the user authenticates against cloud directly. A future
1853
+ * iteration may introduce a delegated install token; until then, browse
1854
+ * here and install on cloud.
1855
+ */
1856
+
1857
+ interface MarketplaceProxyPluginConfig {
1858
+ /**
1859
+ * Control-plane base URL (e.g. https://cloud.objectos.app). When the
1860
+ * caller passes nothing AND the runtime has no OS_CLOUD_URL set, the
1861
+ * plugin falls back to the public ObjectStack-operated cloud so that
1862
+ * `objectstack dev` can browse the marketplace out of the box. Set
1863
+ * OS_CLOUD_URL=off (or `local`) to opt out — the plugin then mounts
1864
+ * a stub that responds 503 and the SPA renders an empty-state
1865
+ * explaining marketplace is unavailable in this runtime.
1866
+ */
1867
+ controlPlaneUrl?: string;
1868
+ }
1869
+ declare class MarketplaceProxyPlugin implements Plugin {
1870
+ readonly name = "com.objectstack.runtime.marketplace-proxy";
1871
+ readonly version = "1.0.0";
1872
+ private readonly cloudUrl;
1873
+ constructor(config?: MarketplaceProxyPluginConfig);
1874
+ init: (_ctx: PluginContext) => Promise<void>;
1875
+ start: (ctx: PluginContext) => Promise<void>;
1876
+ }
1877
+
1878
+ interface MarketplaceInstallLocalPluginConfig {
1879
+ /** Cloud control-plane base URL. When unset, falls back to OS_CLOUD_URL
1880
+ * and then to the public ObjectStack cloud so a fresh `objectstack dev`
1881
+ * can install from the marketplace without configuration. Set
1882
+ * OS_CLOUD_URL=off to disable (the install endpoint then returns 503). */
1883
+ controlPlaneUrl?: string;
1884
+ /** Override the on-disk cache directory. Defaults to
1885
+ * `<cwd>/.objectstack/installed-packages`. */
1886
+ storageDir?: string;
1887
+ }
1888
+ declare class MarketplaceInstallLocalPlugin implements Plugin {
1889
+ readonly name = "com.objectstack.runtime.marketplace-install-local";
1890
+ readonly version = "1.0.0";
1891
+ private readonly cloudUrl;
1892
+ private readonly storageDir;
1893
+ constructor(config?: MarketplaceInstallLocalPluginConfig);
1894
+ init: (_ctx: PluginContext) => Promise<void>;
1895
+ start: (ctx: PluginContext) => Promise<void>;
1896
+ /**
1897
+ * Re-register every cached manifest with the kernel's manifest service.
1898
+ * Safe to call on a kernel that already has the same manifest_id (the
1899
+ * underlying ObjectQL registry overwrites by id, but we still warn so
1900
+ * a developer can spot the dev-time clash between their config.ts and
1901
+ * a marketplace package).
1902
+ */
1903
+ private rehydrate;
1904
+ private handleInstall;
1905
+ private handleList;
1906
+ private handleUninstall;
1907
+ /**
1908
+ * Detect whether `manifestId` is already known to the kernel and classify
1909
+ * the source so we can refuse vs upgrade gracefully.
1910
+ *
1911
+ * 'none' — fresh install
1912
+ * 'marketplace' — previously installed by this plugin (allow upgrade)
1913
+ * 'user-code' — defined by AppPlugin from objectstack.config.ts
1914
+ * (refuse to avoid silently overwriting authored code)
1915
+ */
1916
+ private findConflict;
1917
+ /**
1918
+ * Pull a userId out of the request's better-auth session, if any.
1919
+ * Returns null when there is no signed-in user. v1 does not check
1920
+ * admin role — UI gating + the auth requirement is sufficient for
1921
+ * dev / single-tenant runtimes. Stricter checks can be layered on
1922
+ * via a middleware in cloud-hosted multi-tenant deployments.
1923
+ */
1924
+ /**
1925
+ * Replicate the start-time side-effects that AppPlugin runs for
1926
+ * statically-declared apps but the `manifest` service does NOT:
1927
+ *
1928
+ * 1. Load `manifest.translations` (array of `Record<locale, data>`)
1929
+ * into the i18n service — auto-creating an in-memory fallback if
1930
+ * none is registered, matching AppPlugin's behaviour.
1931
+ *
1932
+ * 2. Merge `manifest.data` (an array of seed datasets) into the
1933
+ * kernel's `seed-datasets` service so SecurityPlugin's per-org
1934
+ * replay middleware picks them up on every future
1935
+ * sys_organization insert.
1936
+ *
1937
+ * 3. When `seedNow=true`, also run the seed immediately so the user
1938
+ * sees demo data without having to create a new org:
1939
+ * • single-tenant: run SeedLoaderService inline (mirrors
1940
+ * AppPlugin single-tenant branch)
1941
+ * • multi-tenant: invoke `seed-replayer` for the caller's
1942
+ * active org (resolved from the request session)
1943
+ *
1944
+ * Errors are logged but never thrown — install succeeds even if
1945
+ * post-register side-effects partially fail (the manifest itself is
1946
+ * already registered + cached). Returns a small summary for the
1947
+ * response envelope.
1948
+ */
1949
+ private applySideEffects;
1950
+ /**
1951
+ * Best-effort active-org resolution. Reads the better-auth session
1952
+ * (same path as requireAuthenticatedUser) and returns
1953
+ * `session.activeOrganizationId`, falling back to the user's first
1954
+ * org membership.
1955
+ */
1956
+ private resolveActiveOrgId;
1957
+ private requireAuthenticatedUser;
1958
+ private readAll;
1959
+ }
1960
+
1961
+ /**
1962
+ * Shared marketplace / cloud control-plane defaults.
1963
+ *
1964
+ * Centralised so every plugin + the CLI auto-inject path agree on
1965
+ * "what cloud URL do we mean when the user didn't set OS_CLOUD_URL?".
1966
+ * Until we have a competing public hosted cloud, this points at the
1967
+ * ObjectStack-operated control plane so a vanilla `objectstack dev` can
1968
+ * browse the marketplace out of the box.
1969
+ */
1970
+ declare const DEFAULT_CLOUD_URL = "https://cloud.objectos.app";
1971
+ /**
1972
+ * Resolve the effective control-plane URL from an explicit constructor
1973
+ * value, the OS_CLOUD_URL env var, or the default. Returns an empty
1974
+ * string when the caller explicitly disabled cloud with
1975
+ * `OS_CLOUD_URL=off` / `local` — callers should treat that as
1976
+ * "marketplace unavailable on this runtime".
1977
+ */
1978
+ declare function resolveCloudUrl(explicit?: string | null): string;
1979
+
1748
1980
  /**
1749
1981
  * Per-project driver registry contract.
1750
1982
  *
@@ -2227,4 +2459,4 @@ declare function actionBodyRunnerFactory(runner: ScriptRunner, opts: FactoryOpti
2227
2459
  timeoutMs?: number;
2228
2460
  }) => ((actionCtx: any) => Promise<unknown>) | undefined;
2229
2461
 
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 };
2462
+ 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 EnvironmentDriverRegistry, 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, 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, resolveCloudUrl, resolveDefaultArtifactPath, resolveErrorReporter, resolveMetrics, resolveRequestId, seedPlatformSsoClient };
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
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
13
  import { ProjectArtifact } from '@objectstack/spec/cloud';
13
14
  export { RestApiPluginConfig, RestServer, RouteEntry, RouteGroupBuilder, RouteManager, createRestApiPlugin } from '@objectstack/rest';
@@ -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,10 +75,10 @@ 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
+ turso: "turso";
68
82
  mongodb: "mongodb";
69
83
  }>>;
70
84
  projectId: z.ZodOptional<z.ZodString>;
@@ -492,6 +506,75 @@ declare function parseTraceparent(value: unknown): TraceContext | undefined;
492
506
  */
493
507
  declare function formatTraceparent(ctx: TraceContext): string;
494
508
 
509
+ /**
510
+ * Options for {@link ObservabilityServicePlugin}.
511
+ *
512
+ * Either or both backends can be omitted; the omitted one resolves to
513
+ * the corresponding no-op exporter so consumers can always rely on the
514
+ * service being present.
515
+ */
516
+ interface ObservabilityServicePluginOptions {
517
+ /** Metrics backend (e.g. `ConsoleMetricsRegistry`, `OtlpHttpMetricsRegistry`). */
518
+ metrics?: MetricsRegistry;
519
+ /** Error reporter backend (e.g. Sentry adapter). */
520
+ errors?: ErrorReporter;
521
+ }
522
+ /**
523
+ * `ObservabilityServicePlugin` — registers the host's
524
+ * {@link MetricsRegistry} and {@link ErrorReporter} in the kernel
525
+ * service registry under the canonical names so any other plugin can
526
+ * look them up without each host having to thread observability config
527
+ * through every plugin constructor.
528
+ *
529
+ * Resolution chain other plugins should follow:
530
+ *
531
+ * 1. Explicit option on the plugin's own options object (escape
532
+ * hatch for tests / explicit wiring).
533
+ * 2. `ctx.getService(OBSERVABILITY_METRICS_SERVICE)`.
534
+ * 3. `NoopMetricsRegistry()` — never null.
535
+ *
536
+ * Register this plugin **before** any plugin that wants to consume the
537
+ * services (cache, storage, dispatcher), otherwise the consumer's
538
+ * `init` will fall through to the no-op default.
539
+ *
540
+ * @example
541
+ * ```ts
542
+ * import { ObjectKernel } from '@objectstack/core';
543
+ * import {
544
+ * ObservabilityServicePlugin,
545
+ * CacheServicePlugin,
546
+ * } from '@objectstack/runtime';
547
+ * import { ConsoleMetricsRegistry } from '@objectstack/observability';
548
+ *
549
+ * const kernel = new ObjectKernel();
550
+ * kernel.use(new ObservabilityServicePlugin({
551
+ * metrics: new ConsoleMetricsRegistry(),
552
+ * }));
553
+ * kernel.use(new CacheServicePlugin()); // picks metrics up automatically
554
+ * ```
555
+ */
556
+ declare class ObservabilityServicePlugin implements Plugin {
557
+ name: string;
558
+ version: string;
559
+ type: string;
560
+ private readonly options;
561
+ constructor(options?: ObservabilityServicePluginOptions);
562
+ init(ctx: PluginContext): Promise<void>;
563
+ }
564
+ /**
565
+ * Helper used by consumer plugins to resolve a metrics backend with
566
+ * the canonical fallback chain. Never throws; always returns a usable
567
+ * `MetricsRegistry`.
568
+ *
569
+ * @param ctx the consuming plugin's `PluginContext`
570
+ * @param override explicit option set on the consuming plugin (wins)
571
+ */
572
+ declare function resolveMetrics(ctx: PluginContext, override?: MetricsRegistry): MetricsRegistry;
573
+ /**
574
+ * Sibling of {@link resolveMetrics} for {@link ErrorReporter}.
575
+ */
576
+ declare function resolveErrorReporter(ctx: PluginContext, override?: ErrorReporter): ErrorReporter;
577
+
495
578
  interface DispatcherPluginConfig {
496
579
  /**
497
580
  * API path prefix for all endpoints.
@@ -1745,6 +1828,155 @@ interface ObjectOSStackResult {
1745
1828
  }
1746
1829
  declare function createObjectOSStack(config: ObjectOSStackConfig): Promise<ObjectOSStackResult>;
1747
1830
 
1831
+ /**
1832
+ * MarketplaceProxyPlugin
1833
+ *
1834
+ * Forwards `GET /api/v1/marketplace/*` from a tenant ObjectOS runtime to
1835
+ * the configured ObjectStack Cloud control-plane URL. The cloud endpoint
1836
+ * (`packages/service-cloud/src/routes/marketplace.ts`) is unauthenticated
1837
+ * and only exposes packages whose owner has opted in to the public catalog
1838
+ * (`sys_package.marketplace_listed = true`) — so the proxy passes through
1839
+ * without any credentials.
1840
+ *
1841
+ * Why proxy instead of direct browser → cloud:
1842
+ * - The Console SPA stays on the tenant origin, so no CORS configuration
1843
+ * is required on the cloud side.
1844
+ * - Local-dev `os serve` works regardless of whether the developer's
1845
+ * browser has cookies for cloud.objectos.app.
1846
+ * - Adds a single, easily auditable network seam between tenant and
1847
+ * control plane.
1848
+ *
1849
+ * Install is NOT proxied here. Installing a package mutates control-plane
1850
+ * state and requires a cloud session + active organization context — the
1851
+ * Console SPA performs install by opening the cloud's install dialog in a
1852
+ * new tab so the user authenticates against cloud directly. A future
1853
+ * iteration may introduce a delegated install token; until then, browse
1854
+ * here and install on cloud.
1855
+ */
1856
+
1857
+ interface MarketplaceProxyPluginConfig {
1858
+ /**
1859
+ * Control-plane base URL (e.g. https://cloud.objectos.app). When the
1860
+ * caller passes nothing AND the runtime has no OS_CLOUD_URL set, the
1861
+ * plugin falls back to the public ObjectStack-operated cloud so that
1862
+ * `objectstack dev` can browse the marketplace out of the box. Set
1863
+ * OS_CLOUD_URL=off (or `local`) to opt out — the plugin then mounts
1864
+ * a stub that responds 503 and the SPA renders an empty-state
1865
+ * explaining marketplace is unavailable in this runtime.
1866
+ */
1867
+ controlPlaneUrl?: string;
1868
+ }
1869
+ declare class MarketplaceProxyPlugin implements Plugin {
1870
+ readonly name = "com.objectstack.runtime.marketplace-proxy";
1871
+ readonly version = "1.0.0";
1872
+ private readonly cloudUrl;
1873
+ constructor(config?: MarketplaceProxyPluginConfig);
1874
+ init: (_ctx: PluginContext) => Promise<void>;
1875
+ start: (ctx: PluginContext) => Promise<void>;
1876
+ }
1877
+
1878
+ interface MarketplaceInstallLocalPluginConfig {
1879
+ /** Cloud control-plane base URL. When unset, falls back to OS_CLOUD_URL
1880
+ * and then to the public ObjectStack cloud so a fresh `objectstack dev`
1881
+ * can install from the marketplace without configuration. Set
1882
+ * OS_CLOUD_URL=off to disable (the install endpoint then returns 503). */
1883
+ controlPlaneUrl?: string;
1884
+ /** Override the on-disk cache directory. Defaults to
1885
+ * `<cwd>/.objectstack/installed-packages`. */
1886
+ storageDir?: string;
1887
+ }
1888
+ declare class MarketplaceInstallLocalPlugin implements Plugin {
1889
+ readonly name = "com.objectstack.runtime.marketplace-install-local";
1890
+ readonly version = "1.0.0";
1891
+ private readonly cloudUrl;
1892
+ private readonly storageDir;
1893
+ constructor(config?: MarketplaceInstallLocalPluginConfig);
1894
+ init: (_ctx: PluginContext) => Promise<void>;
1895
+ start: (ctx: PluginContext) => Promise<void>;
1896
+ /**
1897
+ * Re-register every cached manifest with the kernel's manifest service.
1898
+ * Safe to call on a kernel that already has the same manifest_id (the
1899
+ * underlying ObjectQL registry overwrites by id, but we still warn so
1900
+ * a developer can spot the dev-time clash between their config.ts and
1901
+ * a marketplace package).
1902
+ */
1903
+ private rehydrate;
1904
+ private handleInstall;
1905
+ private handleList;
1906
+ private handleUninstall;
1907
+ /**
1908
+ * Detect whether `manifestId` is already known to the kernel and classify
1909
+ * the source so we can refuse vs upgrade gracefully.
1910
+ *
1911
+ * 'none' — fresh install
1912
+ * 'marketplace' — previously installed by this plugin (allow upgrade)
1913
+ * 'user-code' — defined by AppPlugin from objectstack.config.ts
1914
+ * (refuse to avoid silently overwriting authored code)
1915
+ */
1916
+ private findConflict;
1917
+ /**
1918
+ * Pull a userId out of the request's better-auth session, if any.
1919
+ * Returns null when there is no signed-in user. v1 does not check
1920
+ * admin role — UI gating + the auth requirement is sufficient for
1921
+ * dev / single-tenant runtimes. Stricter checks can be layered on
1922
+ * via a middleware in cloud-hosted multi-tenant deployments.
1923
+ */
1924
+ /**
1925
+ * Replicate the start-time side-effects that AppPlugin runs for
1926
+ * statically-declared apps but the `manifest` service does NOT:
1927
+ *
1928
+ * 1. Load `manifest.translations` (array of `Record<locale, data>`)
1929
+ * into the i18n service — auto-creating an in-memory fallback if
1930
+ * none is registered, matching AppPlugin's behaviour.
1931
+ *
1932
+ * 2. Merge `manifest.data` (an array of seed datasets) into the
1933
+ * kernel's `seed-datasets` service so SecurityPlugin's per-org
1934
+ * replay middleware picks them up on every future
1935
+ * sys_organization insert.
1936
+ *
1937
+ * 3. When `seedNow=true`, also run the seed immediately so the user
1938
+ * sees demo data without having to create a new org:
1939
+ * • single-tenant: run SeedLoaderService inline (mirrors
1940
+ * AppPlugin single-tenant branch)
1941
+ * • multi-tenant: invoke `seed-replayer` for the caller's
1942
+ * active org (resolved from the request session)
1943
+ *
1944
+ * Errors are logged but never thrown — install succeeds even if
1945
+ * post-register side-effects partially fail (the manifest itself is
1946
+ * already registered + cached). Returns a small summary for the
1947
+ * response envelope.
1948
+ */
1949
+ private applySideEffects;
1950
+ /**
1951
+ * Best-effort active-org resolution. Reads the better-auth session
1952
+ * (same path as requireAuthenticatedUser) and returns
1953
+ * `session.activeOrganizationId`, falling back to the user's first
1954
+ * org membership.
1955
+ */
1956
+ private resolveActiveOrgId;
1957
+ private requireAuthenticatedUser;
1958
+ private readAll;
1959
+ }
1960
+
1961
+ /**
1962
+ * Shared marketplace / cloud control-plane defaults.
1963
+ *
1964
+ * Centralised so every plugin + the CLI auto-inject path agree on
1965
+ * "what cloud URL do we mean when the user didn't set OS_CLOUD_URL?".
1966
+ * Until we have a competing public hosted cloud, this points at the
1967
+ * ObjectStack-operated control plane so a vanilla `objectstack dev` can
1968
+ * browse the marketplace out of the box.
1969
+ */
1970
+ declare const DEFAULT_CLOUD_URL = "https://cloud.objectos.app";
1971
+ /**
1972
+ * Resolve the effective control-plane URL from an explicit constructor
1973
+ * value, the OS_CLOUD_URL env var, or the default. Returns an empty
1974
+ * string when the caller explicitly disabled cloud with
1975
+ * `OS_CLOUD_URL=off` / `local` — callers should treat that as
1976
+ * "marketplace unavailable on this runtime".
1977
+ */
1978
+ declare function resolveCloudUrl(explicit?: string | null): string;
1979
+
1748
1980
  /**
1749
1981
  * Per-project driver registry contract.
1750
1982
  *
@@ -2227,4 +2459,4 @@ declare function actionBodyRunnerFactory(runner: ScriptRunner, opts: FactoryOpti
2227
2459
  timeoutMs?: number;
2228
2460
  }) => ((actionCtx: any) => Promise<unknown>) | undefined;
2229
2461
 
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 };
2462
+ 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 EnvironmentDriverRegistry, 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, 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, resolveCloudUrl, resolveDefaultArtifactPath, resolveErrorReporter, resolveMetrics, resolveRequestId, seedPlatformSsoClient };