@objectstack/cloud-connection 9.4.0 → 9.5.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cloud-url.ts","../src/marketplace-public-url.ts","../src/marketplace-ui.ts","../src/marketplace-proxy-plugin.ts","../src/marketplace-install-local-plugin.ts","../src/local-manifest-source.ts","../src/connection-credential-store.ts","../src/cloud-connection-plugin.ts","../src/cloud-connection-ui.ts","../src/runtime-config-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Shared marketplace / cloud control-plane defaults.\n *\n * Centralised so every plugin + the CLI auto-inject path agree on\n * \"what cloud URL do we mean when the user didn't set OS_CLOUD_URL?\".\n * Until we have a competing public hosted cloud, this points at the\n * ObjectStack-operated control plane so a vanilla `objectstack dev` can\n * browse the marketplace out of the box.\n */\nexport const DEFAULT_CLOUD_URL = 'https://cloud.objectos.ai';\n\n/**\n * Resolve the effective control-plane URL from an explicit constructor\n * value, the OS_CLOUD_URL env var, or the default. Returns an empty\n * string when the caller explicitly disabled cloud with\n * `OS_CLOUD_URL=off` / `local` — callers should treat that as\n * \"marketplace unavailable on this runtime\".\n */\nexport function resolveCloudUrl(explicit?: string | null): string {\n const raw = (explicit ?? process.env.OS_CLOUD_URL ?? '').trim();\n const lower = raw.toLowerCase();\n if (lower === 'off' || lower === 'none' || lower === 'local' || lower === 'disabled') {\n return '';\n }\n const picked = raw || DEFAULT_CLOUD_URL;\n return picked.replace(/\\/+$/, '');\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Marketplace public R2 base URL — when set, points at a Cloudflare R2\n * bucket (custom domain or `pub-*.r2.dev`) that serves pre-rendered\n * marketplace browse + install JSON snapshots. The snapshots are\n * written by ObjectStack Cloud (`packages/service-cloud/src/marketplace-snapshot.ts`).\n *\n * Architecture: cloud writes, tenants read directly from R2 → CDN.\n * Marketplace browse + install never touch the cloud control plane,\n * so Cloud cold-start (~12s) is bypassed entirely and the read path\n * scales to CF's edge capacity for free.\n *\n * Default: when OS_MARKETPLACE_PUBLIC_BASE_URL is unset we skip the\n * public fast-path and fall back to the legacy cloud proxy. Once the\n * R2 bucket public domain is wired up in operations, set\n * `OS_MARKETPLACE_PUBLIC_BASE_URL=https://marketplace.objectos.ai`\n * (or your own custom domain) to enable. Set to \"off\" / \"none\" to\n * explicitly disable even if a default is configured.\n *\n * Path layout under the base URL (matches the snapshot writer):\n * <base>/packages.json\n * <base>/packages/{id}.json\n * <base>/packages/{id}/versions/{versionId}/manifest.json\n * <base>/packages/{id}/versions/latest/manifest.json\n *\n * Each JSON file is already in the same `{ success: true, data: ... }`\n * shape as the corresponding cloud API endpoint, so callers can\n * substitute one for the other transparently.\n */\n\n/**\n * Resolve the effective public marketplace base URL. Returns an empty\n * string when the public fast-path is disabled — callers should fall\n * back to fetching via the cloud control plane.\n */\nexport function resolveMarketplacePublicBaseUrl(explicit?: string | null): string {\n const raw = (explicit ?? process.env.OS_MARKETPLACE_PUBLIC_BASE_URL ?? '').trim();\n const lower = raw.toLowerCase();\n if (!raw || lower === 'off' || lower === 'none' || lower === 'disabled' || lower === 'false') {\n return '';\n }\n return raw.replace(/\\/+$/, '');\n}\n\n/**\n * Map an incoming `/api/v1/marketplace/...` API path to a public R2\n * object key (relative — caller prepends the base URL).\n *\n * Returns `null` when the path is not snapshot-backed. Today three\n * paths are covered (list, detail, manifest); anything else (search\n * with non-trivial filters, install actions, etc.) routes via cloud.\n *\n * Query strings are NOT included in the returned key — R2 is static.\n * Callers that need filtering must fetch the full snapshot and filter\n * client-side.\n */\nexport function publicMarketplaceKeyForApiPath(pathname: string): string | null {\n const prefix = '/api/v1/marketplace/packages';\n if (pathname === prefix) return 'packages.json';\n if (!pathname.startsWith(`${prefix}/`)) return null;\n const tail = pathname.slice(prefix.length + 1);\n if (!tail) return null;\n const parts = tail.split('/');\n // /packages/{id}\n if (parts.length === 1) {\n const id = decodeURIComponent(parts[0] ?? '');\n if (!id) return null;\n return `packages/${encodeURIComponent(id)}.json`;\n }\n // /packages/{id}/versions/{versionId}/manifest\n if (parts.length === 4 && parts[1] === 'versions' && parts[3] === 'manifest') {\n const id = decodeURIComponent(parts[0] ?? '');\n const versionId = decodeURIComponent(parts[2] ?? '');\n if (!id || !versionId) return null;\n return `packages/${encodeURIComponent(id)}/versions/${encodeURIComponent(versionId)}/manifest.json`;\n }\n return null;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Marketplace — plugin-owned Setup navigation (cloud ADR-0009: cloud\n * functionality ships as plugins carrying their FULL UI surface).\n *\n * Ownership moved here from `@objectstack/platform-objects`'\n * setup-nav.contributions.ts (ADR-0029 K2's standing direction): the nav\n * entry now lives and dies with the capability —\n *\n * - no MarketplaceProxyPlugin mounted (`OS_CLOUD_URL=off`) → no\n * \"Browse Marketplace\" entry → no dead page.\n * - no MarketplaceInstallLocalPlugin → no \"Installed Apps\" entry.\n *\n * The URLs still point at the console's existing marketplace routes; the\n * pages themselves migrate to plugin-carried metadata in later ADR-0009\n * stages (Installed Apps first).\n */\n\n/** \"Browse Marketplace\" — owned by the browse capability (the proxy). */\nexport const MARKETPLACE_BROWSE_UI_BUNDLE = {\n id: 'com.objectstack.cloud-connection.marketplace-browse-ui',\n namespace: 'sys',\n version: '0.1.0',\n type: 'plugin',\n scope: 'system',\n name: 'Marketplace Browse UI',\n description: 'Setup navigation for the public marketplace catalog (browse).',\n navigationContributions: [\n {\n app: 'setup',\n group: 'group_apps',\n priority: 100,\n items: [\n { id: 'nav_marketplace_browse', type: 'url', label: 'Browse Marketplace', url: '/apps/setup/system/marketplace', icon: 'store' },\n ],\n },\n ],\n};\n\n/** \"Installed Apps\" — owned by the local-install capability (ADR-0009 P2a:\n * the page itself is now metadata; the console provides only the\n * `marketplace:installed-list` widget). */\nexport const MarketplaceInstalledPage = {\n name: 'marketplace_installed',\n label: 'Installed Apps',\n type: 'app' as const,\n template: 'default',\n kind: 'full' as const,\n isDefault: false,\n regions: [\n {\n name: 'header',\n width: 'full' as const,\n components: [\n {\n type: 'page:header',\n properties: {\n title: 'Installed Apps',\n subtitle: 'Marketplace packages currently installed into this runtime\\'s kernel.',\n icon: 'package-check',\n },\n },\n ],\n },\n {\n name: 'main',\n width: 'large' as const,\n components: [\n { type: 'marketplace:installed-list', properties: {} },\n ],\n },\n ],\n};\n\nexport const MARKETPLACE_INSTALLED_UI_BUNDLE = {\n id: 'com.objectstack.cloud-connection.marketplace-installed-ui',\n namespace: 'sys',\n version: '0.2.0',\n type: 'plugin',\n scope: 'system',\n name: 'Marketplace Installed UI',\n description: 'Installed Apps page + Setup navigation for locally-installed marketplace packages.',\n pages: [MarketplaceInstalledPage],\n navigationContributions: [\n {\n app: 'setup',\n group: 'group_apps',\n priority: 110,\n items: [\n { id: 'nav_marketplace_installed', type: 'page', pageName: 'marketplace_installed', label: 'Installed Apps', icon: 'package-check' },\n ],\n },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * MarketplaceProxyPlugin\n *\n * Forwards `GET /api/v1/marketplace/*` from a tenant ObjectOS runtime to\n * the configured ObjectStack Cloud control-plane URL. The cloud endpoint\n * is unauthenticated and only exposes packages whose owner has opted in\n * to the public catalog (`sys_package.marketplace_listed = true`) — so the\n * proxy passes through without any credentials.\n *\n * Why proxy instead of direct browser → cloud:\n * - The Console SPA stays on the tenant origin, so no CORS configuration\n * is required on the cloud side.\n * - Local-dev `os serve` works regardless of whether the developer's\n * browser has cookies for cloud.objectos.ai.\n * - Adds a single, easily auditable network seam between tenant and\n * control plane.\n *\n * Install is NOT proxied here. Installing a package mutates control-plane\n * state and requires a cloud session + active organization context — the\n * Console SPA performs install by opening the cloud's install dialog in a\n * new tab so the user authenticates against cloud directly. A future\n * iteration may introduce a delegated install token; until then, browse\n * here and install on cloud.\n */\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { resolveCloudUrl } from './cloud-url.js';\nimport { MARKETPLACE_BROWSE_UI_BUNDLE } from './marketplace-ui.js';\nimport {\n resolveMarketplacePublicBaseUrl,\n publicMarketplaceKeyForApiPath,\n} from './marketplace-public-url.js';\n\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\n\n/**\n * In-memory cache for GET/HEAD marketplace responses.\n *\n * Marketplace data changes infrequently (new package versions are\n * audited & published in ~hours, not seconds), so we cache aggressively\n * with conditional revalidation:\n *\n * - listing/search → 30 min hard TTL\n * - package detail → 2 h\n * - version detail /\n * readme / assets → 24 h (versions are immutable once published)\n *\n * After TTL expiry the next request issues an `If-None-Match` /\n * `If-Modified-Since` and, on `304 Not Modified`, simply refreshes the\n * TTL without re-downloading the body.\n *\n * Bypass conditions (always re-fetch, no cache write):\n * - `OS_MARKETPLACE_CACHE=off`\n * - Request header `Cache-Control: no-cache` (the Console SPA's\n * \"Refresh\" button sets this)\n * - Non-2xx upstream responses (avoid pinning transient errors)\n *\n * Every response carries `X-Cache: HIT|REVALIDATED|MISS|BYPASS` to make\n * the layer observable in browser devtools.\n */\nconst DEFAULT_LRU_MAX = 200;\nconst LIST_TTL_MS = 30 * 60 * 1000; // 30 min\nconst PACKAGE_TTL_MS = 2 * 60 * 60 * 1000; // 2 h\nconst VERSION_TTL_MS = 24 * 60 * 60 * 1000; // 24 h\n\ninterface CacheEntry {\n status: number;\n body: ArrayBuffer;\n headers: Record<string, string>;\n etag?: string;\n lastModified?: string;\n expiresAt: number;\n ttlMs: number;\n}\n\nfunction ttlForPath(pathname: string): number {\n // `/api/v1/marketplace/packages/:id/versions/:v(.../...)?` → 24h\n if (/\\/packages\\/[^/]+\\/versions\\//.test(pathname)) return VERSION_TTL_MS;\n // `/api/v1/marketplace/packages/:id(/readme)?` → 2h\n if (/\\/packages\\/[^/]+/.test(pathname)) return PACKAGE_TTL_MS;\n // Listings, search, categories, anything else → 30 min\n return LIST_TTL_MS;\n}\n\nclass LruTtlCache {\n private readonly map = new Map<string, CacheEntry>();\n constructor(private readonly max: number) {}\n\n get(key: string): CacheEntry | undefined {\n const entry = this.map.get(key);\n if (!entry) return undefined;\n // LRU touch: re-insert to move to end.\n this.map.delete(key);\n this.map.set(key, entry);\n return entry;\n }\n\n set(key: string, entry: CacheEntry): void {\n if (this.map.has(key)) this.map.delete(key);\n this.map.set(key, entry);\n while (this.map.size > this.max) {\n const oldest = this.map.keys().next().value;\n if (oldest === undefined) break;\n this.map.delete(oldest);\n }\n }\n\n clear(): void {\n this.map.clear();\n }\n}\n\nexport interface MarketplaceProxyPluginConfig {\n /**\n * Control-plane base URL (e.g. https://cloud.objectos.ai). When the\n * caller passes nothing AND the runtime has no OS_CLOUD_URL set, the\n * plugin falls back to the public ObjectStack-operated cloud so that\n * `objectstack dev` can browse the marketplace out of the box. Set\n * OS_CLOUD_URL=off (or `local`) to opt out — the plugin then mounts\n * a stub that responds 503 and the SPA renders an empty-state\n * explaining marketplace is unavailable in this runtime.\n */\n controlPlaneUrl?: string;\n\n /**\n * Disable the in-memory response cache (testing / debugging).\n * Defaults to the value of `OS_MARKETPLACE_CACHE` (anything in\n * {\"off\",\"false\",\"0\",\"no\"} disables).\n */\n cacheDisabled?: boolean;\n\n /**\n * Override the LRU upper bound. Defaults to 200 entries.\n */\n cacheMaxEntries?: number;\n /**\n * Public R2 base URL for marketplace snapshots. When set, GETs for\n * snapshot-backed paths (`/packages`, `/packages/:id`,\n * `/packages/:id/versions/:vid/manifest`) are fetched directly from\n * R2 (CF edge) — bypassing the cloud control plane entirely.\n * Defaults to the value of OS_MARKETPLACE_PUBLIC_BASE_URL. Empty\n * string disables the public fast-path (legacy cloud-proxy only).\n */\n publicMarketplaceBaseUrl?: string;\n}\n\nexport class MarketplaceProxyPlugin implements Plugin {\n readonly name = 'com.objectstack.runtime.marketplace-proxy';\n readonly version = '1.1.0';\n\n private readonly cloudUrl: string;\n private readonly publicBaseUrl: string;\n private readonly cache: LruTtlCache | null;\n\n constructor(config: MarketplaceProxyPluginConfig = {}) {\n this.cloudUrl = resolveCloudUrl(config.controlPlaneUrl);\n this.publicBaseUrl = resolveMarketplacePublicBaseUrl(config.publicMarketplaceBaseUrl);\n\n const envFlag = (process.env.OS_MARKETPLACE_CACHE ?? '').trim().toLowerCase();\n const envDisabled = ['off', 'false', '0', 'no', 'disable', 'disabled'].includes(envFlag);\n const disabled = config.cacheDisabled ?? envDisabled;\n this.cache = disabled\n ? null\n : new LruTtlCache(Math.max(8, config.cacheMaxEntries ?? DEFAULT_LRU_MAX));\n }\n\n init = async (_ctx: PluginContext): Promise<void> => {\n // No services registered — pure HTTP wiring during start().\n };\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n // Plugin-owned Setup nav (cloud ADR-0009): the \"Browse\n // Marketplace\" entry ships WITH the browse capability — no\n // proxy mounted, no entry. Best-effort: headless kernels\n // simply have no Setup surface.\n try {\n const manifest = ctx.getService<{ register(m: any): void }>('manifest');\n manifest?.register?.(MARKETPLACE_BROWSE_UI_BUNDLE);\n } catch { /* no manifest service */ }\n\n let httpServer: any;\n try {\n httpServer = ctx.getService('http-server');\n } catch {\n ctx.logger?.warn?.('[MarketplaceProxyPlugin] http-server not available — marketplace routes not mounted');\n return;\n }\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[MarketplaceProxyPlugin] http-server missing getRawApp() — marketplace routes not mounted');\n return;\n }\n\n const rawApp = httpServer.getRawApp();\n const cloudUrl = this.cloudUrl;\n const publicBaseUrl = this.publicBaseUrl;\n const cache = this.cache;\n\n if (publicBaseUrl) {\n ctx.logger?.info?.(`[MarketplaceProxyPlugin] public R2 fast-path enabled → ${publicBaseUrl}`);\n }\n\n const handler = async (c: any, next: any) => {\n if (!cloudUrl) {\n return c.json({\n success: false,\n error: {\n code: 'marketplace_unavailable',\n message: 'No control-plane URL configured for this runtime (OS_CLOUD_URL).',\n },\n }, 503);\n }\n try {\n const incomingUrl = new URL(c.req.url);\n // Do NOT proxy install-local — those are owned by\n // MarketplaceInstallLocalPlugin and must hit this\n // runtime, never cloud. Pass through so Hono can match\n // the install-local route registered on the same app.\n if (incomingUrl.pathname.startsWith(`${MARKETPLACE_PREFIX}/install-local`)) {\n return next();\n }\n\n const method = String(c.req.method ?? 'GET').toUpperCase();\n\n // ── Public R2 fast-path ─────────────────────────\n // When OS_MARKETPLACE_PUBLIC_BASE_URL is configured,\n // GETs for snapshot-backed paths fetch directly from\n // R2 → CF edge cache. This skips the cloud control\n // plane entirely so marketplace browse + install\n // work even when cloud is asleep or completely down.\n if (publicBaseUrl && (method === 'GET' || method === 'HEAD')) {\n const r2Resp = await tryPublicMarketplaceFetch(\n publicBaseUrl, incomingUrl, method, c.req.header('accept'),\n ctx.logger,\n );\n if (r2Resp) return r2Resp;\n // Fall through on miss / error to the cloud path.\n }\n\n // Preserve the full /api/v1/marketplace/... path on cloud.\n const target = `${cloudUrl}${incomingUrl.pathname}${incomingUrl.search}`;\n\n // Browse-only mechanism: this plugin forwards only safe,\n // idempotent GET/HEAD (it carries no credentialled cloud\n // auth). It does NOT own install *policy* — that is a host\n // concern (ObjectStack Cloud supplies a credentialled\n // install route via the `extraPlugins` seam; see ADR\n // docs/design/cloud-account-binding-marketplace-install.md\n // §5.2). So instead of dead-ending non-GET with a 405\n // \"install via cloud\", we PASS THROUGH: a host-supplied\n // handler mounted after this plugin can claim the request;\n // if none does, the app returns its normal 404. This\n // removes the browse-only install dead-end (framework#1548)\n // without this plugin pretending to know install policy.\n if (method !== 'GET' && method !== 'HEAD') {\n return next();\n }\n\n // Cache lookup. Key includes accept-language because\n // cloud may serve locale-specific copy in the future;\n // HEAD shares the cache slot with GET (we just elide the\n // body in the response).\n const accept = c.req.header('accept') ?? 'application/json';\n const acceptLang = c.req.header('accept-language') ?? '';\n const cacheKey = `${incomingUrl.pathname}${incomingUrl.search}|al=${acceptLang}|a=${accept}`;\n const reqCacheCtl = (c.req.header('cache-control') ?? '').toLowerCase();\n const bypass = !cache || reqCacheCtl.includes('no-cache') || reqCacheCtl.includes('no-store');\n const now = Date.now();\n\n if (cache && !bypass) {\n const hit = cache.get(cacheKey);\n if (hit && hit.expiresAt > now) {\n return buildCachedResponse(hit, method, 'HIT');\n }\n if (hit) {\n // TTL expired — try conditional revalidate so we\n // don't pay for the body when nothing changed.\n const revalHeaders: Record<string, string> = {\n 'Accept': accept,\n 'User-Agent': `objectos-marketplace-proxy/${MarketplaceProxyPlugin.prototype.version ?? '1.0.0'}`,\n };\n if (acceptLang) revalHeaders['Accept-Language'] = acceptLang;\n if (hit.etag) revalHeaders['If-None-Match'] = hit.etag;\n if (hit.lastModified) revalHeaders['If-Modified-Since'] = hit.lastModified;\n const revalResp = await fetch(target, { method: 'GET', headers: revalHeaders });\n if (revalResp.status === 304) {\n hit.expiresAt = now + hit.ttlMs;\n // Refresh ETag/Last-Modified if the upstream\n // re-issued them on the 304 (per RFC 7232 §4.1).\n const newEtag = revalResp.headers.get('etag');\n const newLm = revalResp.headers.get('last-modified');\n if (newEtag) hit.etag = newEtag;\n if (newLm) hit.lastModified = newLm;\n cache.set(cacheKey, hit);\n return buildCachedResponse(hit, method, 'REVALIDATED');\n }\n // 200 (or anything else): fall through to the\n // normal fetch+store path below, using the\n // revalidation response we already have in hand.\n return await consumeAndMaybeCache(revalResp, cacheKey, incomingUrl.pathname, method, cache);\n }\n }\n\n // MISS (or BYPASS): origin fetch.\n const reqHeaders: Record<string, string> = {\n // Strip the inbound Host header — fetch will set\n // it to the cloud host. Forward only the\n // identifying headers cloud might log.\n 'Accept': accept,\n 'User-Agent': `objectos-marketplace-proxy/${MarketplaceProxyPlugin.prototype.version ?? '1.0.0'}`,\n };\n if (acceptLang) reqHeaders['Accept-Language'] = acceptLang;\n const resp = await fetch(target, { method: 'GET', headers: reqHeaders });\n\n if (bypass || !cache) {\n // Don't write to cache; just stream back.\n return await passthroughResponse(resp, method, bypass ? 'BYPASS' : 'MISS');\n }\n return await consumeAndMaybeCache(resp, cacheKey, incomingUrl.pathname, method, cache);\n } catch (err: any) {\n const errObj = err instanceof Error ? err : new Error(err?.message ?? String(err));\n ctx.logger?.error?.('[MarketplaceProxyPlugin] proxy failed', errObj);\n return c.json({\n success: false,\n error: {\n code: 'marketplace_proxy_failed',\n message: err?.message ?? String(err),\n },\n }, 502);\n }\n };\n\n if (typeof rawApp.all === 'function') {\n rawApp.all(`${MARKETPLACE_PREFIX}/*`, handler);\n } else {\n for (const m of ['get', 'head'] as const) {\n try { rawApp[m]?.(`${MARKETPLACE_PREFIX}/*`, handler); } catch { /* best effort */ }\n }\n }\n\n ctx.logger?.info?.(`[MarketplaceProxyPlugin] mounted at ${MARKETPLACE_PREFIX}/* → ${cloudUrl || '(unconfigured)'} (cache=${this.cache ? 'on' : 'off'})`);\n });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public R2 fast-path (module-private)\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch a marketplace API path from the public R2 base URL and return\n * the response shaped exactly like the cloud API endpoint would. The\n * snapshots are already in `{ success: true, data: ... }` shape so for\n * direct lookups we stream bytes verbatim. The list endpoint applies\n * query-string filters (q / category / limit / offset) client-side\n * from the full snapshot.\n *\n * Returns `null` for any of:\n * - path is not snapshot-backed (e.g. featured / categories / etc.)\n * - R2 returned 404 (snapshot not yet generated for this id)\n * - network error fetching from R2\n *\n * On `null`, the caller falls back to the cloud proxy path.\n */\nasync function tryPublicMarketplaceFetch(\n publicBaseUrl: string,\n incomingUrl: URL,\n method: string,\n acceptHeader: string | undefined,\n logger: any,\n): Promise<Response | null> {\n const key = publicMarketplaceKeyForApiPath(incomingUrl.pathname);\n if (!key) return null;\n\n const target = `${publicBaseUrl}/${key}`;\n let resp: Response;\n try {\n resp = await fetch(target, {\n method: 'GET',\n headers: {\n 'Accept': acceptHeader || 'application/json',\n 'User-Agent': `objectos-marketplace-proxy/public-r2`,\n },\n });\n } catch (err: any) {\n logger?.warn?.(`[MarketplaceProxyPlugin] public R2 fetch failed (${target}): ${err?.message ?? err}`);\n return null;\n }\n if (resp.status === 404) return null;\n if (!resp.ok) {\n logger?.warn?.(`[MarketplaceProxyPlugin] public R2 ${target} returned ${resp.status} — falling back to cloud`);\n return null;\n }\n\n // List endpoint: apply optional q/category/limit/offset filters on\n // the full snapshot. Detail + manifest snapshots stream verbatim.\n const isList = key === 'packages.json';\n const hasFilters = isList && (\n incomingUrl.searchParams.has('q') ||\n incomingUrl.searchParams.has('category') ||\n incomingUrl.searchParams.has('limit') ||\n incomingUrl.searchParams.has('offset')\n );\n\n if (!hasFilters) {\n // Verbatim passthrough — preserve cache headers from R2 / CF.\n const headers = new Headers();\n const ct = resp.headers.get('content-type') ?? 'application/json; charset=utf-8';\n headers.set('content-type', ct);\n const cc = resp.headers.get('cache-control');\n if (cc) headers.set('cache-control', cc);\n const etag = resp.headers.get('etag');\n if (etag) headers.set('etag', etag);\n headers.set('x-cache', 'PUBLIC-R2');\n const body = method === 'HEAD' ? null : resp.body;\n return new Response(body, { status: 200, headers });\n }\n\n // Filtered list — parse, filter, re-serialize.\n let snapshot: any;\n try { snapshot = await resp.json(); }\n catch (err: any) {\n logger?.warn?.(`[MarketplaceProxyPlugin] public R2 list snapshot parse failed: ${err?.message ?? err}`);\n return null;\n }\n const items: any[] = Array.isArray(snapshot?.data?.items) ? snapshot.data.items : [];\n\n const q = (incomingUrl.searchParams.get('q') ?? '').trim().toLowerCase();\n const category = (incomingUrl.searchParams.get('category') ?? '').trim();\n const limit = Math.min(Math.max(Number(incomingUrl.searchParams.get('limit') ?? 50), 1), 100);\n const offset = Math.max(Number(incomingUrl.searchParams.get('offset') ?? 0), 0);\n\n let filtered = items;\n if (q) {\n filtered = filtered.filter((r) => {\n const dn = String(r?.display_name ?? '').toLowerCase();\n const mid = String(r?.manifest_id ?? '').toLowerCase();\n return dn.includes(q) || mid.includes(q);\n });\n }\n if (category) {\n filtered = filtered.filter((r) => String(r?.category ?? '') === category);\n }\n const total = filtered.length;\n const page = filtered.slice(offset, offset + limit);\n const body = JSON.stringify({ success: true, data: { items: page, total, limit, offset } });\n\n const headers = new Headers({\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'public, max-age=30',\n 'x-cache': 'PUBLIC-R2-FILTERED',\n });\n return new Response(method === 'HEAD' ? null : body, { status: 200, headers });\n}\n\n// ---------------------------------------------------------------------------\n// Cache helpers (module-private)\n// ---------------------------------------------------------------------------\n\nconst PASSTHROUGH_HEADERS = ['content-type', 'cache-control', 'etag', 'last-modified', 'vary'] as const;\n\nfunction collectHeaders(src: Response): Record<string, string> {\n const out: Record<string, string> = {};\n for (const h of PASSTHROUGH_HEADERS) {\n const v = src.headers.get(h);\n if (v) out[h] = v;\n }\n return out;\n}\n\nfunction buildCachedResponse(entry: CacheEntry, method: string, xCache: 'HIT' | 'REVALIDATED'): Response {\n const headers = new Headers(entry.headers);\n headers.set('X-Cache', xCache);\n // Surface remaining freshness so downstream HTTP caches / devtools\n // can reason about it (clamped at 0).\n const ageSec = Math.max(0, Math.floor((entry.expiresAt - entry.ttlMs - Date.now()) / -1000));\n headers.set('Age', String(Math.max(0, ageSec)));\n const body = method === 'HEAD' ? null : entry.body;\n return new Response(body, { status: entry.status, headers });\n}\n\nasync function passthroughResponse(resp: Response, method: string, xCache: 'MISS' | 'BYPASS'): Promise<Response> {\n const headers = new Headers(collectHeaders(resp));\n headers.set('X-Cache', xCache);\n if (method === 'HEAD') {\n // Drain to release the connection.\n try { await resp.arrayBuffer(); } catch { /* ignore */ }\n return new Response(null, { status: resp.status, headers });\n }\n const body = await resp.arrayBuffer();\n return new Response(body, { status: resp.status, headers });\n}\n\nasync function consumeAndMaybeCache(\n resp: Response,\n key: string,\n pathname: string,\n method: string,\n cache: LruTtlCache,\n): Promise<Response> {\n const body = await resp.arrayBuffer();\n const headers = collectHeaders(resp);\n // Only cache success responses — pinning a 404 / 5xx would just\n // amplify a transient failure.\n if (resp.status >= 200 && resp.status < 300) {\n const ttlMs = ttlForPath(pathname);\n const entry: CacheEntry = {\n status: resp.status,\n body,\n headers,\n etag: resp.headers.get('etag') ?? undefined,\n lastModified: resp.headers.get('last-modified') ?? undefined,\n expiresAt: Date.now() + ttlMs,\n ttlMs,\n };\n cache.set(key, entry);\n }\n const respHeaders = new Headers(headers);\n respHeaders.set('X-Cache', 'MISS');\n const outBody = method === 'HEAD' ? null : body;\n return new Response(outBody, { status: resp.status, headers: respHeaders });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * MarketplaceInstallLocalPlugin\n *\n * Installs marketplace packages into THIS runtime's kernel as opposed to a\n * remote cloud environment. Conceptually different from cloud install in\n * three important ways:\n *\n * 1. Single target — the local kernel is the only install target; there\n * is no `sys_environment` picker.\n * 2. Manifests are cached on disk — once installed, the package is\n * runnable offline. Cloud is only needed during the install action\n * itself (to fetch the manifest snapshot).\n * 3. Coexists with user-authored apps — the local runtime usually has\n * its own `objectstack.config.ts` declared apps. Install refuses to\n * overwrite a manifest_id that's already registered to avoid silently\n * replacing user code.\n *\n * Endpoints (mounted by `start()` on the `kernel:ready` hook):\n *\n * POST /api/v1/marketplace/install-local\n * body: { packageId: string, versionId?: string } (default: \"latest\")\n * → fetches manifest from cloud, caches to disk, registers via\n * the kernel's `manifest` service. Returns the installed entry.\n *\n * GET /api/v1/marketplace/install-local\n * → lists currently installed marketplace packages\n *\n * DELETE /api/v1/marketplace/install-local/:manifestId\n * → removes the cached manifest. Kernel must be restarted to fully\n * unload — `engine.registerApp` is additive only. We document\n * this in the response message.\n *\n * Persistence layout:\n * <cwd>/.objectstack/installed-packages/<safe-manifest-id>.json\n * Each file: { packageId, versionId, manifestId, version, manifest, installedAt, installedBy }\n *\n * On `kernel:ready`, the plugin scans the directory and re-registers each\n * cached manifest so installs survive process restarts without further\n * cloud round-trips.\n */\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport { resolveCloudUrl } from './cloud-url.js';\nimport { resolveMarketplacePublicBaseUrl } from './marketplace-public-url.js';\nimport { LocalManifestSource, type InstalledManifestEntry } from './local-manifest-source.js';\nimport { ConnectionCredentialStore } from './connection-credential-store.js';\nimport { MARKETPLACE_INSTALLED_UI_BUNDLE } from './marketplace-ui.js';\n\nconst ROUTE_BASE = '/api/v1/marketplace/install-local';\n\nexport interface MarketplaceInstallLocalPluginConfig {\n /** Cloud control-plane base URL. When unset, falls back to OS_CLOUD_URL\n * and then to the public ObjectStack cloud so a fresh `objectstack dev`\n * can install from the marketplace without configuration. Set\n * OS_CLOUD_URL=off to disable (the install endpoint then returns 503). */\n controlPlaneUrl?: string;\n /** Override the on-disk cache directory. Defaults to\n * `<cwd>/.objectstack/installed-packages`. */\n storageDir?: string;\n}\n\n// Desired-state entry shape — owned by the LocalManifestSource ledger\n// (ADR-0007 step ⑤: the ledger is the named local desired-state owner;\n// this plugin is its HTTP mutation surface).\ntype InstalledEntry = InstalledManifestEntry;\n\nexport class MarketplaceInstallLocalPlugin implements Plugin {\n readonly name = 'com.objectstack.runtime.marketplace-install-local';\n readonly version = '1.0.0';\n\n private readonly cloudUrl: string;\n private readonly ledger: LocalManifestSource;\n private readonly storageDir: string;\n private readonly credentials: ConnectionCredentialStore;\n\n constructor(config: MarketplaceInstallLocalPluginConfig = {}) {\n this.cloudUrl = resolveCloudUrl(config.controlPlaneUrl);\n this.ledger = new LocalManifestSource(config.storageDir);\n this.storageDir = this.ledger.dir;\n this.credentials = new ConnectionCredentialStore();\n }\n\n init = async (_ctx: PluginContext): Promise<void> => {\n // No services registered — pure HTTP wiring during start().\n };\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n // Plugin-owned Setup nav (cloud ADR-0009): \"Installed Apps\"\n // ships WITH the local-install capability.\n try {\n const manifest = ctx.getService<{ register(m: any): void }>('manifest');\n manifest?.register?.(MARKETPLACE_INSTALLED_UI_BUNDLE);\n } catch { /* no manifest service */ }\n\n // 1. Rehydrate previously installed packages so they survive restart.\n await this.rehydrate(ctx);\n\n // 2. Mount HTTP endpoints.\n let httpServer: any;\n try {\n httpServer = ctx.getService('http-server');\n } catch {\n ctx.logger?.warn?.('[MarketplaceInstallLocal] http-server not available — install endpoints not mounted');\n return;\n }\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[MarketplaceInstallLocal] http-server missing getRawApp() — install endpoints not mounted');\n return;\n }\n const rawApp = httpServer.getRawApp();\n\n const postHandler = async (c: any) => this.handleInstall(c, ctx);\n const getHandler = async (c: any) => this.handleList(c);\n const deleteHandler = async (c: any) => this.handleUninstall(c, ctx);\n\n const reseedHandler = async (c: any) => this.handleReseed(c, ctx);\n const purgeHandler = async (c: any) => this.handlePurge(c, ctx);\n\n if (typeof rawApp.post === 'function') rawApp.post(ROUTE_BASE, postHandler);\n if (typeof rawApp.get === 'function') rawApp.get(ROUTE_BASE, getHandler);\n if (typeof rawApp.delete === 'function') rawApp.delete(`${ROUTE_BASE}/:manifestId`, deleteHandler);\n if (typeof rawApp.post === 'function') {\n rawApp.post(`${ROUTE_BASE}/:manifestId/reseed-sample-data`, reseedHandler);\n rawApp.post(`${ROUTE_BASE}/:manifestId/purge-sample-data`, purgeHandler);\n }\n\n ctx.logger?.info?.(`[MarketplaceInstallLocal] mounted at ${ROUTE_BASE} (storage: ${this.storageDir})`);\n });\n };\n\n /**\n * Re-register every cached manifest with the kernel's manifest service.\n * Safe to call on a kernel that already has the same manifest_id (the\n * underlying ObjectQL registry overwrites by id, but we still warn so\n * a developer can spot the dev-time clash between their config.ts and\n * a marketplace package).\n */\n private rehydrate = async (ctx: PluginContext): Promise<void> => {\n const entries = this.readAll();\n if (entries.length === 0) return;\n\n let manifestService: { register(m: any): void } | null = null;\n try {\n manifestService = ctx.getService('manifest') as any;\n } catch {\n ctx.logger?.warn?.('[MarketplaceInstallLocal] no `manifest` service — rehydrate skipped');\n return;\n }\n\n for (const entry of entries) {\n try {\n manifestService!.register(entry.manifest);\n // Sync schemas so the driver creates tables for the newly-\n // registered objects (idempotent — already-synced tables\n // are no-ops).\n try {\n const ql: any = ctx.getService('objectql');\n if (ql && typeof ql.syncSchemas === 'function') await ql.syncSchemas();\n } catch { /* non-fatal */ }\n // Replay translations + register seed datasets, but don't\n // re-run seeding — existing rows are already in the DB from\n // the original install, and multi-tenant orgs will replay\n // via the security middleware on next sys_organization insert.\n await this.applySideEffects(ctx, entry.manifest, { seedNow: false });\n ctx.logger?.info?.(`[MarketplaceInstallLocal] rehydrated ${entry.manifestId}@${entry.version}`);\n } catch (err: any) {\n ctx.logger?.error?.(`[MarketplaceInstallLocal] rehydrate failed for ${entry.manifestId}`, err instanceof Error ? err : new Error(String(err)));\n }\n }\n };\n\n private handleInstall = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required to install packages.' } }, 401);\n }\n\n let body: any = {};\n try { body = await c.req.json(); } catch { /* empty body */ }\n\n // ── Offline path: an inline manifest was supplied (file import). ──\n // Bypass the cloud-fetch entirely; no OS_CLOUD_URL required.\n const inlineManifest = body?.manifest && typeof body.manifest === 'object' ? body.manifest : null;\n\n // A COMPILED stack bundle (`dist/objectstack.json`, what publish\n // uploads as the version payload) nests its meta under `.manifest`:\n // { manifest: { id, namespace, version, … }, objects, views, … }\n // while ObjectQL's registerApp expects the FLAT app shape (top-level\n // id + sections). Flatten when detected — otherwise every install of\n // a published compiled bundle dies with \"Invalid manifest payload\".\n const normalizeBundle = (m: any): any => {\n if (m && !m.id && !m.name && m.manifest && typeof m.manifest === 'object' && (m.manifest.id || m.manifest.name)) {\n const { manifest: meta, ...sections } = m;\n return { ...meta, ...sections };\n }\n return m;\n };\n\n let manifest: any;\n let resolvedVersionId: string;\n let version: string;\n let packageId: string;\n\n if (inlineManifest) {\n manifest = normalizeBundle(inlineManifest);\n packageId = String(manifest.id ?? manifest.name ?? '').trim();\n version = String(manifest.version ?? 'unknown');\n resolvedVersionId = String(body?.versionId ?? version);\n if (!packageId) {\n return c.json({ success: false, error: { code: 'invalid_manifest', message: 'Inline manifest must have an \"id\" or \"name\".' } }, 400);\n }\n } else {\n if (!this.cloudUrl) {\n return c.json({ success: false, error: { code: 'marketplace_unavailable', message: 'OS_CLOUD_URL not configured.' } }, 503);\n }\n packageId = String(body?.packageId ?? '').trim();\n const versionId = String(body?.versionId ?? 'latest').trim() || 'latest';\n if (!packageId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'packageId is required.' } }, 400);\n }\n\n // 1. Fetch manifest snapshot — prefer public R2 fast-path so\n // install works even when cloud is asleep or down. Fall back\n // to cloud on miss/error.\n let payload: any;\n const publicBase = resolveMarketplacePublicBaseUrl();\n const fetchAttempts: { label: string; url: string }[] = [];\n if (publicBase) {\n fetchAttempts.push({\n label: 'public-r2',\n url: `${publicBase}/packages/${encodeURIComponent(packageId)}/versions/${encodeURIComponent(versionId)}/manifest.json`,\n });\n }\n fetchAttempts.push({\n label: 'cloud',\n url: `${this.cloudUrl}/api/v1/marketplace/packages/${encodeURIComponent(packageId)}/versions/${encodeURIComponent(versionId)}/manifest`,\n });\n\n // Credential for the CLOUD attempt: the env→cloud service key\n // (cloud-hosted) or the bound oscc_ bearer (self-hosted). With it\n // the catalog also serves the caller's OWN org/private packages —\n // anonymous fetches keep getting public/listed only. The public\n // R2 fast-path stays anonymous (it only ever holds public).\n const cloudCredential = (process.env.OS_CLOUD_API_KEY ?? '').trim()\n || this.credentials.read()?.runtimeToken\n || '';\n\n let lastErrStatus = 0;\n let lastErrText = '';\n for (const attempt of fetchAttempts) {\n try {\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (attempt.label === 'cloud' && cloudCredential) headers.Authorization = `Bearer ${cloudCredential}`;\n const resp = await fetch(attempt.url, { headers });\n if (!resp.ok) {\n lastErrStatus = resp.status;\n lastErrText = (await resp.text().catch(() => '')).slice(0, 200);\n // 404 from public R2 is not fatal — fall through to cloud.\n if (attempt.label === 'public-r2' && resp.status === 404) {\n ctx.logger?.info?.(`[MarketplaceInstallLocal] public-r2 miss for ${packageId}@${versionId}, falling back to cloud`);\n continue;\n }\n if (attempt.label === 'public-r2' && resp.status >= 500) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] public-r2 ${resp.status}, falling back to cloud`);\n continue;\n }\n break; // cloud non-ok → surface error\n }\n payload = await resp.json();\n lastErrStatus = 0;\n break;\n } catch (err: any) {\n if (attempt.label === 'public-r2') {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] public-r2 fetch error: ${err?.message ?? err}, falling back to cloud`);\n continue;\n }\n return c.json({\n success: false,\n error: { code: 'cloud_fetch_failed', message: err?.message ?? String(err) },\n }, 502);\n }\n }\n if (!payload) {\n return c.json({\n success: false,\n error: { code: 'cloud_fetch_failed', message: `Cloud returned ${lastErrStatus}: ${lastErrText}` },\n }, lastErrStatus === 404 ? 404 : 502);\n }\n\n const data = payload?.data ?? payload;\n manifest = normalizeBundle(data?.manifest);\n resolvedVersionId = String(data?.version_id ?? versionId);\n version = String(data?.version ?? 'unknown');\n }\n\n const manifestId = String(manifest?.id ?? manifest?.name ?? '');\n if (!manifest || !manifestId) {\n return c.json({ success: false, error: { code: 'invalid_manifest', message: 'Invalid manifest payload.' } }, inlineManifest ? 400 : 502);\n }\n\n // 2. Conflict check — refuse to overwrite user-authored apps\n const conflict = this.findConflict(ctx, manifestId);\n if (conflict === 'user-code') {\n return c.json({\n success: false,\n error: {\n code: 'manifest_conflict',\n message: `manifest_id \"${manifestId}\" is already defined by this runtime's local code. Refusing to overwrite. Uninstall the local definition first.`,\n },\n }, 409);\n }\n\n // 3. Hot-register FIRST so a malformed inline manifest fails the\n // install loudly rather than persisting a broken record that\n // would also fail on every subsequent rehydrate.\n try {\n const manifestService = ctx.getService('manifest') as any;\n manifestService.register(manifest);\n } catch (err: any) {\n // For offline file imports we treat a register failure as a hard\n // failure (don't persist). Cloud installs historically tolerated\n // this (the on-disk record survives a restart), so keep that path\n // lenient for backwards compatibility.\n if (inlineManifest) {\n return c.json({\n success: false,\n error: { code: 'register_failed', message: `Failed to register imported manifest: ${err?.message ?? err}` },\n }, 422);\n }\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] hot-register failed for ${manifestId} (will load on next restart): ${err?.message ?? err}`);\n }\n\n // 4. Persist on disk\n const entry: InstalledEntry = {\n packageId,\n versionId: resolvedVersionId,\n manifestId,\n version,\n manifest,\n installedAt: new Date().toISOString(),\n installedBy: userId,\n withSampleData: false,\n };\n try {\n this.ledger.write(entry);\n } catch (err: any) {\n return c.json({\n success: false,\n error: { code: 'storage_failed', message: `Failed to persist manifest: ${err?.message ?? err}` },\n }, 500);\n }\n\n // 4b. Sync schemas to physical tables — registerApp only adds the\n // object definitions to the in-memory registry; the driver\n // must be asked to materialize tables/columns before any seed\n // insert (or user write) succeeds.\n try {\n const ql: any = ctx.getService('objectql');\n if (ql && typeof ql.syncSchemas === 'function') {\n await ql.syncSchemas();\n ctx.logger?.info?.(`[MarketplaceInstallLocal] syncSchemas() ran after registering ${manifestId}`);\n }\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] syncSchemas failed for ${manifestId}: ${err?.message ?? err}`);\n }\n\n // 5. Replicate the AppPlugin start-time side-effects that the\n // `manifest` service does NOT do on its own:\n // • load translation bundles into the i18n service\n // • stash seed datasets on the kernel + run them now so the\n // installed app has demo data on first paint.\n const seededSummary = await this.applySideEffects(ctx, manifest, { seedNow: true, c });\n if (seededSummary.seeded.mode === 'inline' && (seededSummary.seeded.inserted ?? 0) + (seededSummary.seeded.updated ?? 0) > 0) {\n entry.withSampleData = true;\n try {\n this.ledger.write(entry);\n } catch { /* non-fatal — entry already on disk */ }\n }\n\n return c.json({\n success: true,\n data: {\n manifestId,\n version,\n versionId: resolvedVersionId,\n installedAt: entry.installedAt,\n hotLoaded: true,\n upgradedFrom: conflict === 'marketplace' ? 'previous-marketplace-version' : null,\n translationsLoaded: seededSummary.translationsLoaded,\n seeded: seededSummary.seeded,\n note: 'App is now available in this runtime. Refresh the console to see it in the app switcher.',\n },\n }, 200);\n };\n\n private handleList = async (c: any): Promise<Response> => {\n const entries = this.readAll();\n return c.json({\n success: true,\n data: {\n items: entries.map(e => ({\n packageId: e.packageId,\n versionId: e.versionId,\n manifestId: e.manifestId,\n version: e.version,\n installedAt: e.installedAt,\n installedBy: e.installedBy,\n withSampleData: e.withSampleData ?? false,\n })),\n total: entries.length,\n storageDir: this.storageDir,\n },\n }, 200);\n };\n\n private handleUninstall = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required.' } }, 401);\n }\n const manifestId = String(c.req.param?.('manifestId') ?? c.req.params?.manifestId ?? '').trim();\n if (!manifestId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'manifestId path param required.' } }, 400);\n }\n if (!this.ledger.has(manifestId)) {\n return c.json({ success: false, error: { code: 'not_found', message: `No marketplace install for ${manifestId}.` } }, 404);\n }\n try {\n this.ledger.remove(manifestId);\n } catch (err: any) {\n return c.json({ success: false, error: { code: 'storage_failed', message: err?.message ?? String(err) } }, 500);\n }\n ctx.logger?.info?.(`[MarketplaceInstallLocal] uninstalled ${manifestId} (cached manifest removed; restart runtime to unload from running kernel)`);\n return c.json({\n success: true,\n data: {\n manifestId,\n note: 'Cached manifest removed. The app remains loaded in the running kernel until the next restart (the kernel API does not support unregistering apps in-place).',\n },\n }, 200);\n };\n\n /**\n * Detect whether `manifestId` is already known to the kernel and classify\n * the source so we can refuse vs upgrade gracefully.\n *\n * 'none' — fresh install\n * 'marketplace' — previously installed by this plugin (allow upgrade)\n * 'user-code' — defined by AppPlugin from objectstack.config.ts\n * (refuse to avoid silently overwriting authored code)\n */\n private findConflict = (ctx: PluginContext, manifestId: string): 'none' | 'marketplace' | 'user-code' => {\n // First check: do we already have a marketplace install entry?\n if (this.ledger.has(manifestId)) {\n return 'marketplace';\n }\n // Then check: is the manifest_id already in the engine's registry?\n try {\n const ql: any = ctx.getService('objectql');\n const packages: any[] = ql?.registry?.getAllPackages?.() ?? [];\n const hit = packages.find((p: any) =>\n (p?.manifest?.id ?? p?.id ?? p?.manifest?.name) === manifestId,\n );\n if (hit) return 'user-code';\n } catch { /* objectql not registered yet — treat as fresh */ }\n return 'none';\n };\n\n /**\n * Pull a userId out of the request's better-auth session, if any.\n * Returns null when there is no signed-in user. v1 does not check\n * admin role — UI gating + the auth requirement is sufficient for\n * dev / single-tenant runtimes. Stricter checks can be layered on\n * via a middleware in cloud-hosted multi-tenant deployments.\n */\n /**\n * POST /api/v1/marketplace/install-local/:manifestId/reseed-sample-data\n *\n * Re-runs SeedLoaderService against the cached manifest's `data` arrays.\n * Idempotent (upsert by id). Useful when:\n * • The user installed an app and skipped sample data\n * • A purge was undone\n * • The user wants a clean baseline back after editing demo rows\n *\n * Multi-tenant: requires an active organization on the session (same\n * rule as install seed path).\n */\n private handleReseed = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required.' } }, 401);\n }\n const manifestId = String(c.req.param?.('manifestId') ?? c.req.params?.manifestId ?? '').trim();\n if (!manifestId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'manifestId path param required.' } }, 400);\n }\n if (!this.ledger.has(manifestId)) {\n return c.json({ success: false, error: { code: 'not_found', message: `No marketplace install for ${manifestId}.` } }, 404);\n }\n const entry: InstalledEntry | null = this.ledger.read(manifestId);\n if (!entry) {\n return c.json({ success: false, error: { code: 'storage_failed', message: 'Failed to read manifest cache.' } }, 500);\n }\n\n const summary = await this.applySideEffects(ctx, entry.manifest, { seedNow: true, c });\n if (summary.seeded.mode === 'skipped') {\n return c.json({\n success: false,\n error: {\n code: 'reseed_skipped',\n message: `Reseed did not run: ${summary.seeded.reason ?? 'unknown reason'}`,\n },\n }, 400);\n }\n\n // Persist flag flip\n try {\n entry.withSampleData = true;\n this.ledger.write(entry);\n } catch { /* non-fatal */ }\n\n return c.json({\n success: true,\n data: {\n manifestId,\n inserted: summary.seeded.inserted ?? 0,\n updated: summary.seeded.updated ?? 0,\n errors: summary.seeded.errors ?? 0,\n withSampleData: true,\n },\n }, 200);\n };\n\n /**\n * POST /api/v1/marketplace/install-local/:manifestId/purge-sample-data\n *\n * Deletes every record whose id is declared in the cached manifest's\n * seed datasets. Uses the `driver` service directly to bypass ACL /\n * lifecycle hooks (same pattern as cloud purge). User-created records\n * are never touched — only ids declared in the package's bundled\n * datasets are removed. Already-deleted rows count as `skipped`.\n */\n private handlePurge = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required.' } }, 401);\n }\n const manifestId = String(c.req.param?.('manifestId') ?? c.req.params?.manifestId ?? '').trim();\n if (!manifestId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'manifestId path param required.' } }, 400);\n }\n if (!this.ledger.has(manifestId)) {\n return c.json({ success: false, error: { code: 'not_found', message: `No marketplace install for ${manifestId}.` } }, 404);\n }\n const entry: InstalledEntry | null = this.ledger.read(manifestId);\n if (!entry) {\n return c.json({ success: false, error: { code: 'storage_failed', message: 'Failed to read manifest cache.' } }, 500);\n }\n\n const datasets = Array.isArray(entry.manifest?.data)\n ? entry.manifest.data.filter((d: any) => d && d.object && Array.isArray(d.records))\n : [];\n\n if (datasets.length === 0) {\n return c.json({\n success: false,\n error: { code: 'nothing_to_purge', message: 'This package declares no seed datasets.' },\n }, 400);\n }\n\n let driver: any;\n try { driver = ctx.getService('driver'); } catch { /* none */ }\n if (!driver || typeof driver.delete !== 'function') {\n return c.json({\n success: false,\n error: { code: 'driver_missing', message: 'driver service unavailable — cannot purge.' },\n }, 500);\n }\n\n let deleted = 0;\n let skipped = 0;\n let errors = 0;\n for (const ds of datasets) {\n const object = String(ds.object);\n for (const rec of ds.records as any[]) {\n const id = rec?.id;\n if (id === undefined || id === null || id === '') { skipped++; continue; }\n try {\n const r = await driver.delete(object, id);\n if (r === false || r === 0 || r?.deleted === 0) skipped++;\n else deleted++;\n } catch (err: any) {\n // Treat \"not found\" as skipped; anything else as error.\n const msg = String(err?.message ?? err);\n if (/not.?found|no row/i.test(msg)) skipped++;\n else { errors++; ctx.logger?.warn?.(`[MarketplaceInstallLocal] purge ${object}#${id}: ${msg}`); }\n }\n }\n }\n\n // Flip flag so UI reflects the empty baseline\n try {\n entry.withSampleData = false;\n this.ledger.write(entry);\n } catch { /* non-fatal */ }\n\n ctx.logger?.info?.(`[MarketplaceInstallLocal] purged ${manifestId}: deleted=${deleted} skipped=${skipped} errors=${errors}`);\n return c.json({\n success: true,\n data: { manifestId, deleted, skipped, errors, withSampleData: false },\n }, 200);\n };\n\n /**\n * Replicate the start-time side-effects that AppPlugin runs for\n * statically-declared apps but the `manifest` service does NOT:\n *\n * 1. Load `manifest.translations` (array of `Record<locale, data>`)\n * into the i18n service — auto-creating an in-memory fallback if\n * none is registered, matching AppPlugin's behaviour.\n *\n * 2. Merge `manifest.data` (an array of seed datasets) into the\n * kernel's `seed-datasets` service so SecurityPlugin's per-org\n * replay middleware picks them up on every future\n * sys_organization insert.\n *\n * 3. When `seedNow=true`, also run the seed immediately so the user\n * sees demo data without having to create a new org:\n * • single-tenant: run SeedLoaderService inline (mirrors\n * AppPlugin single-tenant branch)\n * • multi-tenant: invoke `seed-replayer` for the caller's\n * active org (resolved from the request session)\n *\n * Errors are logged but never thrown — install succeeds even if\n * post-register side-effects partially fail (the manifest itself is\n * already registered + cached). Returns a small summary for the\n * response envelope.\n */\n private applySideEffects = async (\n ctx: PluginContext,\n manifest: any,\n opts: { seedNow: boolean; c?: any },\n ): Promise<{ translationsLoaded: number; seeded: { mode: 'inline' | 'replayer' | 'skipped'; inserted?: number; updated?: number; errors?: number; reason?: string } }> => {\n const appId = String(manifest?.id ?? 'unknown');\n let translationsLoaded = 0;\n let seedSummary: any = { mode: 'skipped', reason: 'no-datasets' };\n\n // ── 1. i18n bundles ─────────────────────────────────────────────\n try {\n const bundles: Array<Record<string, unknown>> = [];\n if (Array.isArray(manifest?.translations)) bundles.push(...manifest.translations);\n if (Array.isArray(manifest?.i18n)) bundles.push(...manifest.i18n);\n\n if (bundles.length > 0) {\n let i18nService: any;\n try { i18nService = ctx.getService('i18n'); } catch { /* not registered */ }\n if (!i18nService) {\n try {\n const mod = await import('@objectstack/core');\n const createMemoryI18n = (mod as any).createMemoryI18n;\n if (typeof createMemoryI18n === 'function') {\n i18nService = createMemoryI18n();\n (ctx as any).registerService?.('i18n', i18nService);\n ctx.logger?.info?.(`[MarketplaceInstallLocal] auto-registered in-memory i18n fallback for \"${appId}\"`);\n }\n } catch { /* fallback unavailable */ }\n }\n if (i18nService?.loadTranslations) {\n for (const bundle of bundles) {\n for (const [locale, data] of Object.entries(bundle)) {\n if (data && typeof data === 'object') {\n try {\n i18nService.loadTranslations(locale, data as Record<string, unknown>);\n translationsLoaded++;\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] failed to load ${appId} translations for ${locale}: ${err?.message ?? err}`);\n }\n }\n }\n }\n ctx.logger?.info?.(`[MarketplaceInstallLocal] loaded ${translationsLoaded} locale bundle(s) for ${appId}`);\n }\n }\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] i18n side-effect failed for ${appId}: ${err?.message ?? err}`);\n }\n\n // ── 2. Seed datasets — merge into kernel service ─────────────────\n const datasets = Array.isArray(manifest?.data)\n ? manifest.data.filter((d: any) => d && d.object && Array.isArray(d.records))\n : [];\n\n if (datasets.length > 0) {\n try {\n const kernel: any = (ctx as any).kernel;\n let existing: any[] = [];\n try {\n const v = kernel?.getService?.('seed-datasets');\n if (Array.isArray(v)) existing = v;\n } catch { /* unset */ }\n const merged = [...existing, ...datasets];\n if (kernel?.registerService) kernel.registerService('seed-datasets', merged);\n else (ctx as any).registerService?.('seed-datasets', merged);\n ctx.logger?.info?.(`[MarketplaceInstallLocal] merged ${datasets.length} seed dataset(s) into kernel (total: ${merged.length})`);\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] failed to merge seed-datasets: ${err?.message ?? err}`);\n }\n }\n\n // ── 3. Optional immediate seed ───────────────────────────────────\n // Always seed inline via SeedLoaderService — don't rely on the\n // `seed-replayer` registered by AppPlugin since (a) it isn't\n // registered when the host runtime has no AppPlugin app with\n // seed data, and (b) its closure may use stale datasets. In\n // multi-tenant mode we pass `organizationId` so the loader\n // writes tenant-scoped rows the same way AppPlugin's\n // single-tenant branch + SecurityPlugin's per-org replay do.\n if (opts.seedNow && datasets.length > 0) {\n const multiTenant = String(readEnvWithDeprecation('OS_MULTI_ORG_ENABLED', 'OS_MULTI_TENANT') ?? 'false').toLowerCase() !== 'false';\n try {\n const ql: any = ctx.getService('objectql');\n let metadata: any;\n try { metadata = ctx.getService('metadata'); } catch { /* none */ }\n if (!ql || !metadata) {\n seedSummary = { mode: 'skipped', reason: 'objectql-or-metadata-missing' };\n } else {\n let organizationId: string | undefined;\n if (multiTenant) {\n const resolved = await this.resolveActiveOrgId(opts.c, ctx);\n if (resolved) organizationId = resolved;\n else {\n seedSummary = { mode: 'skipped', reason: 'multi-tenant-no-active-org' };\n ctx.logger?.warn?.('[MarketplaceInstallLocal] multi-tenant: no active org on request — data not seeded');\n }\n }\n if (!multiTenant || organizationId) {\n const [{ SeedLoaderService }, { SeedLoaderRequestSchema }] = await Promise.all([\n import('@objectstack/runtime'),\n import('@objectstack/spec/data'),\n ]);\n const seedLoader = new (SeedLoaderService as any)(ql, metadata, ctx.logger);\n const request = (SeedLoaderRequestSchema as any).parse({\n // ADR-0036 / seed rename: the field is `seeds` (was `datasets`).\n seeds: datasets,\n config: {\n defaultMode: 'upsert',\n multiPass: true,\n ...(organizationId ? { organizationId } : {}),\n },\n });\n const result = await seedLoader.load(request);\n seedSummary = {\n mode: 'inline',\n inserted: result.summary.totalInserted,\n updated: result.summary.totalUpdated,\n errors: result.errors.length,\n };\n ctx.logger?.info?.(`[MarketplaceInstallLocal] inline seed for ${appId}${organizationId ? ` (org=${organizationId})` : ''}: inserted=${seedSummary.inserted} updated=${seedSummary.updated} errors=${seedSummary.errors}`);\n }\n }\n } catch (err: any) {\n seedSummary = { mode: 'skipped', reason: `seed-error: ${err?.message ?? err}` };\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] seed run failed for ${appId}: ${err?.message ?? err}`);\n }\n }\n\n return { translationsLoaded, seeded: seedSummary };\n };\n\n /**\n * Best-effort active-org resolution. Reads the better-auth session\n * (same path as requireAuthenticatedUser) and returns\n * `session.activeOrganizationId`, falling back to the user's first\n * org membership.\n */\n private resolveActiveOrgId = async (c: any, ctx: PluginContext): Promise<string | null> => {\n if (!c?.req?.raw?.headers) return null;\n try {\n const authService: any = ctx.getService('auth');\n let api: any = authService?.api;\n if (!api && typeof authService?.getApi === 'function') api = await authService.getApi();\n if (!api?.getSession) return null;\n const session = await api.getSession({ headers: c.req.raw.headers });\n const direct = session?.session?.activeOrganizationId ?? session?.activeOrganizationId ?? null;\n if (direct) return String(direct);\n // Fall back to the user's first membership row.\n const userId = session?.user?.id;\n if (!userId) return null;\n try {\n const ql: any = ctx.getService('objectql');\n if (ql?.find) {\n const rows = await ql.find('sys_organization_member', { where: { user_id: userId }, limit: 1, context: { isSystem: true } } as any);\n const row = Array.isArray(rows) ? rows[0] : (rows?.items?.[0] ?? null);\n return row?.organization_id ? String(row.organization_id) : null;\n }\n } catch { /* ignore */ }\n } catch { /* ignore */ }\n return null;\n };\n\n private requireAuthenticatedUser = async (c: any, ctx: PluginContext): Promise<string | null> => {\n try {\n // Mirror `hono-plugin.ts` resolveCtx: pull the better-auth `api`\n // off the auth service and call `getSession({ headers })`. The\n // earlier guess `c.get('auth').session` is wrong — AuthPlugin\n // does not pre-populate the Hono context.\n const authService: any = ctx.getService('auth');\n let api: any = authService?.api;\n if (!api && typeof authService?.getApi === 'function') {\n api = await authService.getApi();\n }\n if (api?.getSession && c?.req?.raw?.headers) {\n const session = await api.getSession({ headers: c.req.raw.headers });\n const userId = session?.user?.id ?? null;\n if (userId) return String(userId);\n }\n } catch { /* ignore — fall through */ }\n // Header fallback for cases where auth is disabled (e.g. test stubs)\n const xUserId = c?.req?.header?.('x-user-id');\n if (xUserId) return String(xUserId);\n return null;\n };\n\n private readAll = (): InstalledEntry[] => this.ledger.list();\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * LocalManifestSource — the local desired-state ledger for package installs\n * (cloud ADR-0007 step ⑤).\n *\n * A self-hosted / single-environment runtime OWNS its desired state: the\n * answer to \"which packages should this runtime load\" lives on the runtime's\n * own disk, one JSON file per installed manifest under\n * `<cwd>/.objectstack/installed-packages/`. This class is that ledger,\n * promoted to a first-class named seam.\n *\n * It is the LOCAL isomorph of what a cloud control plane does for managed\n * environments (`sys_package_installation` desired rows → compiled\n * artifact): same role — desired-state owner — different authority:\n *\n * | Deployment | Desired-state owner | Runtime truth |\n * |-------------------|--------------------------------------|----------------------|\n * | Cloud-managed env | control plane (sys_package_installation → artifact) | env-local artifact cache |\n * | Self-hosted env | THIS ledger (LocalManifestSource) | the same ledger (rehydrated at boot) |\n *\n * Nothing here talks to a network: reads and writes are synchronous local\n * file operations, so a runtime boots and serves its installed packages\n * with zero cloud dependency (\"云崩环境不崩\").\n *\n * Consumed by {@link MarketplaceInstallLocalPlugin} (the HTTP surface that\n * mutates the ledger) — exported so hosts and future reconcilers can read\n * the same ledger without going through HTTP.\n */\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\n/** One installed-package entry — desired state + provenance. */\nexport interface InstalledManifestEntry {\n packageId: string;\n versionId: string;\n manifestId: string;\n version: string;\n manifest: any;\n installedAt: string;\n installedBy: string | null;\n /** Whether the bundled seed datasets have been loaded into the kernel\n * database. True after install (seedNow=true) or an explicit reseed;\n * false after a purge. Persisted so the UI can show \"Add\" vs \"Re-seed\". */\n withSampleData?: boolean;\n}\n\n/** Default ledger location, relative to the runtime's working directory. */\nexport const DEFAULT_INSTALLED_PACKAGES_DIR = '.objectstack/installed-packages';\n\nfunction safeFilename(manifestId: string): string {\n return manifestId.replace(/[^a-zA-Z0-9._-]/g, '_') + '.json';\n}\n\nexport class LocalManifestSource {\n /** Resolved ledger directory. */\n readonly dir: string;\n\n constructor(storageDir?: string) {\n this.dir = storageDir\n ? resolve(storageDir)\n : resolve(process.cwd(), DEFAULT_INSTALLED_PACKAGES_DIR);\n }\n\n /** Every valid entry in the ledger (corrupt files are skipped). */\n list(): InstalledManifestEntry[] {\n if (!existsSync(this.dir)) return [];\n const out: InstalledManifestEntry[] = [];\n for (const name of readdirSync(this.dir)) {\n if (!name.endsWith('.json')) continue;\n try {\n const raw = readFileSync(join(this.dir, name), 'utf8');\n out.push(JSON.parse(raw));\n } catch { /* skip corrupt files */ }\n }\n return out;\n }\n\n /** Read one entry; null when absent or unreadable. */\n read(manifestId: string): InstalledManifestEntry | null {\n const file = this.fileFor(manifestId);\n if (!existsSync(file)) return null;\n try {\n return JSON.parse(readFileSync(file, 'utf8'));\n } catch {\n return null;\n }\n }\n\n /** Whether the ledger holds an entry for this manifest id. */\n has(manifestId: string): boolean {\n return existsSync(this.fileFor(manifestId));\n }\n\n /** Create or replace an entry (upsert by manifestId). */\n write(entry: InstalledManifestEntry): void {\n mkdirSync(this.dir, { recursive: true });\n writeFileSync(this.fileFor(entry.manifestId), JSON.stringify(entry, null, 2), 'utf8');\n }\n\n /** Remove an entry. Returns false when it was not present. */\n remove(manifestId: string): boolean {\n const file = this.fileFor(manifestId);\n if (!existsSync(file)) return false;\n unlinkSync(file);\n return true;\n }\n\n private fileFor(manifestId: string): string {\n return join(this.dir, safeFilename(manifestId));\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ConnectionCredentialStore — where a SELF-HOSTED runtime keeps the\n * credential it received at bind time (cloud ADR-0008 consumption side).\n *\n * Cloud-hosted runtimes authenticate to the control plane with an\n * env→cloud service key (`OS_CLOUD_API_KEY`, injected by the cloud).\n * Self-hosted runtimes have no such key: their identity ceremony is the\n * RFC 8628 device-code bind, whose response carries a one-time\n * `runtime_token` (`oscc_…`). This store persists that bearer — plus the\n * environment id the binding established — under the runtime's own\n * working directory, next to the LocalManifestSource ledger:\n *\n * <cwd>/.objectstack/cloud-connection.json\n *\n * Like everything on the runtime's serving path, reads are local file\n * operations: presenting the credential is how the runtime reaches the\n * control plane for org-scoped catalog/install calls, but nothing at\n * boot or serve time DEPENDS on those calls succeeding.\n *\n * Treat the file as a secret (it is written 0600).\n */\n\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\n/** Persisted binding credential + context. */\nexport interface StoredConnectionCredential {\n /** The `oscc_…` runtime bearer returned ONCE by the bind route. */\n runtimeToken: string;\n /**\n * Cloud-minted durable runtime identity (ADR runtime-identity-binding).\n * Presented as a claim on re-bind so the registration survives token\n * rotation. Absent on stores written before v2.\n */\n runtimeId?: string;\n /**\n * Control-plane environment id — set only when the binding targeted a\n * cloud-hosted environment. Self-hosted v2 registrations have none.\n */\n environmentId?: string;\n /** Control-plane base URL the binding was made against. */\n controlPlaneUrl?: string;\n organizationId?: string;\n accountEmail?: string;\n boundAt?: string;\n}\n\n/** Default store location, relative to the runtime's working directory. */\nexport const DEFAULT_CONNECTION_CREDENTIAL_PATH = '.objectstack/cloud-connection.json';\n\nexport class ConnectionCredentialStore {\n /** Resolved file path. */\n readonly path: string;\n\n constructor(path?: string) {\n this.path = path\n ? resolve(path)\n : resolve(process.cwd(), DEFAULT_CONNECTION_CREDENTIAL_PATH);\n }\n\n /**\n * Read the stored credential; null when absent or unreadable.\n *\n * An IDENTITY RESIDUAL — `runtimeToken: ''` with a `runtimeId` — is a\n * valid record: unbind leaves one behind so a later re-bind to the same\n * org claims the same registration (ADR runtime-identity-binding §2.1).\n * Callers already treat the empty token as \"no credential\".\n */\n read(): StoredConnectionCredential | null {\n if (!existsSync(this.path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(this.path, 'utf8'));\n if (!parsed || typeof parsed.runtimeToken !== 'string') return null;\n if (!parsed.runtimeToken && !(typeof parsed.runtimeId === 'string' && parsed.runtimeId)) return null;\n return parsed as StoredConnectionCredential;\n } catch {\n return null;\n }\n }\n\n /** Persist (replace) the credential. Written 0600 — it is a secret. */\n write(credential: StoredConnectionCredential): void {\n mkdirSync(dirname(this.path), { recursive: true });\n writeFileSync(this.path, JSON.stringify(credential, null, 2), { encoding: 'utf8', mode: 0o600 });\n }\n\n /** Remove the credential (unbind). Returns false when nothing was stored. */\n clear(): boolean {\n if (!existsSync(this.path)) return false;\n unlinkSync(this.path);\n return true;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * CloudConnectionPlugin — the runtime-side client surface for a cloud\n * control plane (ADR-0008 Phase 1).\n *\n * Mounts the same-origin `/api/v1/cloud-connection/*` routes the Console\n * marketplace depends on:\n *\n * GET /api/v1/cloud-connection/status — is this env bound to a cloud account?\n * POST /api/v1/cloud-connection/bind/start — begin an RFC 8628 device-code bind\n * POST /api/v1/cloud-connection/bind/poll — poll device token + persist the binding\n * POST /api/v1/cloud-connection/install — install a package via the control plane\n * GET /api/v1/cloud-connection/installation — single-package installed-state probe\n * GET /api/v1/cloud-connection/installed — env's full installed list (Installed view)\n * GET /api/v1/cloud-connection/org-packages — owning org's own catalog (\"Your organization\")\n *\n * History: these routes started as app-level wiring in\n * `apps/objectos/cloud-runtime-plugins.ts` (two ad-hoc plugins). ADR-0008\n * Phase 1 consolidates them here as ONE plugin so both deployment shapes —\n * `apps/objectos` (multi-tenant) and `apps/objectos-ee` (single-environment)\n * — wire the same canonical implementation. ADR-0008 Phase 2 moves this\n * surface into the open `@objectstack/cloud-connection` package; keep this\n * file dependency-light (structural Plugin types, no @objectstack/core) so\n * the move is mechanical.\n *\n * ## Environment & session resolution — two modes\n *\n * Multi-tenant (default): the request hostname is resolved to an environment\n * via the host kernel's `env-registry` service, and the caller's session is\n * validated against that environment's OWN per-env kernel (via\n * `kernel-manager`) — auth is per-environment (ADR-0006).\n *\n * Single-environment (`singleEnvironment: true`, e.g. objectos-ee): there is\n * no registry/manager; the environment id comes from config\n * (`environmentId` / `OS_ENVIRONMENT_ID`, typically assigned when the\n * runtime is bound to a control plane) and sessions are validated against\n * the host kernel's own `auth` service. Routes degrade gracefully when the\n * id is not (yet) configured: status reports `bound:false`; the others 404.\n *\n * ## Why a same-origin proxy at all\n *\n * The SPA cannot call the control plane from a tenant subdomain — that is a\n * cross-origin, cross-site-cookie request the browser blocks. So the runtime\n * answers on its own origin, authorizes against the environment's session,\n * and talks to the control plane server-to-server (env→cloud service\n * credential today; the device-code-bound `sys_cloud_connection` token for\n * self-hosted runtimes).\n */\n\n// Minimal structural plugin contract — keep this module independent of\n// @objectstack/core so the ADR-0008 Phase 2 move to the open package stays\n// mechanical (mirrors the other plugins in this package).\ninterface PluginContext {\n hook(event: string, handler: (...args: any[]) => any): void;\n getService<T = any>(name: string): T;\n logger?: {\n info?: (msg: string) => void;\n warn?: (msg: string) => void;\n error?: (msg: string, err?: unknown) => void;\n };\n}\ninterface Plugin {\n readonly name: string;\n readonly version: string;\n init(ctx: PluginContext): Promise<void>;\n start(ctx: PluginContext): Promise<void>;\n}\n\nimport { hostname } from 'node:os';\nimport { ConnectionCredentialStore } from './connection-credential-store.js';\nimport { CLOUD_CONNECTION_UI_BUNDLE } from './cloud-connection-ui.js';\n\nconst CLOUD_CONNECTION_PREFIX = '/api/v1/cloud-connection';\n\nexport interface CloudConnectionPluginConfig {\n /** Control-plane base URL. Default: `OS_CLOUD_URL` (read lazily at kernel:ready). */\n controlPlaneUrl?: string;\n /** env→cloud service credential. Default: `OS_CLOUD_API_KEY`. */\n controlPlaneApiKey?: string;\n /** OAuth device-flow client id. Default: `OS_CLI_CLIENT_ID` → `objectstack-cli`. */\n deviceClientId?: string;\n /**\n * Fixed environment id (single-environment runtimes). Default:\n * `OS_ENVIRONMENT_ID`. In multi-tenant mode leave unset — the id is\n * resolved per-request from the hostname via `env-registry`.\n */\n environmentId?: string;\n /**\n * Single-environment mode (objectos-ee shipped shape): skip the\n * env-registry/kernel-manager lookups and validate sessions against the\n * host kernel's own `auth` service.\n */\n singleEnvironment?: boolean;\n /**\n * Override the on-disk credential store location. Defaults to\n * `<cwd>/.objectstack/cloud-connection.json` — where the bind flow\n * persists the `oscc_…` runtime bearer for self-hosted runtimes.\n */\n credentialPath?: string;\n}\n\nexport class CloudConnectionPlugin implements Plugin {\n readonly name = 'com.objectstack.cloud.connection';\n readonly version = '0.3.0';\n\n private readonly cfg: CloudConnectionPluginConfig;\n private readonly store: ConnectionCredentialStore;\n\n constructor(config: CloudConnectionPluginConfig = {}) {\n this.cfg = config;\n this.store = new ConnectionCredentialStore(config.credentialPath);\n }\n\n init = async (_ctx: PluginContext): Promise<void> => { /* HTTP wiring on kernel:ready */ };\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n const httpServer: any = (() => { try { return ctx.getService('http-server'); } catch { return undefined; } })();\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[CloudConnectionPlugin] http-server unavailable — routes not mounted');\n return;\n }\n const rawApp = httpServer.getRawApp();\n // Env vars are read here (not at construction) so a host can set\n // them between config load and kernel boot — preserves the\n // behavior of the original app-level wiring.\n const cloudUrl = (this.cfg.controlPlaneUrl ?? process.env.OS_CLOUD_URL ?? '').trim().replace(/\\/+$/, '');\n const cloudApiKey = (this.cfg.controlPlaneApiKey ?? process.env.OS_CLOUD_API_KEY ?? '').trim();\n const deviceClientId = (this.cfg.deviceClientId ?? process.env.OS_CLI_CLIENT_ID ?? 'objectstack-cli').trim();\n const deviceScope = 'openid profile email';\n\n // Effective control-plane credential, resolved PER REQUEST:\n // cloud-hosted runtimes carry the env→cloud service key; a\n // self-hosted runtime presents the `oscc_…` bearer the bind flow\n // persisted. Lazy so a bind that completes while the runtime is\n // up takes effect without a restart.\n const credential = (): string => cloudApiKey || this.store.read()?.runtimeToken || '';\n const authHeaders = (): Record<string, string> => {\n const cred = credential();\n return cred ? { Authorization: `Bearer ${cred}` } : {};\n };\n\n const hostOf = (c: any): string => {\n try { return new URL(c.req.url).hostname; } catch { return ''; }\n };\n\n const resolveEnvironmentId = async (c: any): Promise<string | undefined> => {\n const fixed = (this.cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? '').trim();\n // The CLI's local-dev defaults ('env_local' / 'proj_local')\n // identify the LOCAL kernel, not a cloud environment — never\n // present them to the control plane as one (they would 404\n // the bind and resurrect the phantom-environment confusion\n // ADR runtime-identity-binding removes).\n if (fixed && fixed !== 'env_local' && fixed !== 'proj_local') return fixed;\n if (this.cfg.singleEnvironment) {\n // A completed bind persisted the environment id — a\n // self-hosted runtime needs no OS_ENVIRONMENT_ID after it.\n return this.store.read()?.environmentId || undefined;\n }\n try {\n const envRegistry = ctx.getService<any>('env-registry');\n const env = await envRegistry?.resolveByHostname?.(hostOf(c));\n return env?.environmentId;\n } catch {\n return undefined;\n }\n };\n\n // SDUI surface: the binding page + Setup-nav entry ship with the\n // plugin as metadata (ADR-0029 K2); the console only provides the\n // registered `cloud-connection:panel` widget. Best-effort — a\n // kernel without a manifest service simply has no Setup entry.\n try {\n const manifest = ctx.getService<{ register(m: any): void }>('manifest');\n manifest?.register?.(CLOUD_CONNECTION_UI_BUNDLE);\n } catch { /* no manifest service — headless kernel */ }\n\n const sessionFromAuthService = async (authSvc: any, rawReq: Request): Promise<{ userId?: string } | null> => {\n const api = typeof authSvc?.getApi === 'function' ? await authSvc.getApi() : authSvc?.api ?? authSvc;\n const session = await api?.getSession?.({ headers: rawReq.headers });\n const userId = session?.user?.id ? String(session.user.id) : undefined;\n return userId ? { userId } : null;\n };\n\n const resolveSession = async (environmentId: string, rawReq: Request): Promise<{ userId?: string } | null> => {\n try {\n if (this.cfg.singleEnvironment) {\n // Single-env: the host kernel owns auth.\n let authSvc: any;\n try { authSvc = ctx.getService('auth'); } catch { /* ignore */ }\n if (!authSvc) return null;\n return await sessionFromAuthService(authSvc, rawReq);\n }\n // Multi-tenant: auth lives on the environment's own kernel.\n const kernelManager = ctx.getService<any>('kernel-manager');\n const kernel = await kernelManager?.getOrCreate?.(environmentId);\n let authSvc: any;\n try { authSvc = await kernel?.getServiceAsync?.('auth'); } catch { /* ignore */ }\n if (!authSvc) { try { authSvc = kernel?.getService?.('auth'); } catch { /* ignore */ } }\n if (!authSvc) return null;\n return await sessionFromAuthService(authSvc, rawReq);\n } catch {\n return null;\n }\n };\n\n // GET /status — is this runtime bound to a cloud account?\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/status`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n const stored = this.store.read();\n const runtimeId = stored?.runtimeId;\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n // A single-env runtime with no env id and no credential is\n // simply not bound yet — valid state, not an error.\n if (!environmentId && !credential()) {\n return c.json({ success: true, data: { environmentId: null, runtimeId: runtimeId ?? null, bound: false, provider: 'objectstack-cloud', connection: null } });\n }\n // Prefer the real sys_cloud_connection from the control plane.\n // The oscc_ bearer self-identifies; service-key callers query\n // by environment_id (cloud-hosted) or runtime_id (claim).\n if (cloudUrl) {\n try {\n const qs = environmentId\n ? `?environment_id=${encodeURIComponent(environmentId)}`\n : runtimeId ? `?runtime_id=${encodeURIComponent(runtimeId)}` : '';\n const resp = await fetch(`${cloudUrl}/api/v1/cloud-connection/status${qs}`, {\n headers: authHeaders(),\n });\n if (resp.ok) {\n const json: any = await resp.json().catch(() => null);\n const data = json?.data ?? {};\n const bound = Boolean(data.bound) || Boolean(credential());\n return c.json({ success: true, data: {\n environmentId: environmentId ?? null,\n runtimeId: data.runtime_id ?? runtimeId ?? null,\n bound,\n provider: 'objectstack-cloud',\n connection: data.connection ?? null,\n } });\n }\n } catch { /* fall through to implicit */ }\n }\n const bound = Boolean(credential());\n return c.json({ success: true, data: { environmentId: environmentId ?? null, runtimeId: runtimeId ?? null, bound, provider: 'objectstack-cloud', connection: null } });\n });\n\n // POST /bind/start — begin a device-code bind. The runtime is the\n // genuine RFC 8628 client: it asks the cloud for a device + user\n // code, returns them to the Setup UI, and the operator approves in\n // the cloud console.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/bind/start`, async (c: any) => {\n let body: any = {};\n try { body = await c.req.json(); } catch { body = {}; }\n // Self-hosted (single-env) runtimes need NO environment id —\n // registration happens cloud-side at approval (ADR\n // runtime-identity-binding). An explicit environment_id in the\n // body is still honored for cloud-hosted-style binds.\n let environmentId = await resolveEnvironmentId(c);\n if (!environmentId && this.cfg.singleEnvironment) {\n environmentId = String(body?.environment_id ?? body?.environmentId ?? '').trim() || undefined;\n }\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment to connect a cloud account.' } }, 401);\n if (!cloudUrl) return c.json({ success: false, error: { code: 'cloud_unconfigured', message: 'No cloud control plane configured.' } }, 503);\n try {\n const resp = await fetch(`${cloudUrl}/api/v1/auth/device/code`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ client_id: deviceClientId, scope: deviceScope }),\n });\n const json: any = await resp.json().catch(() => ({}));\n if (!resp.ok) return c.json({ success: false, error: { code: 'device_code_failed', message: json?.error ?? `device/code ${resp.status}` } }, 502);\n // Device context for the approval page (ADR\n // runtime-identity-binding §2.3): name the requesting\n // runtime in the verification URL so the approver sees\n // WHAT they are authorizing. Display-only — informed\n // consent, not an authenticity proof (the page carries\n // the \"only approve if you started this\" warning).\n const withContext = (uri: unknown): string | undefined => {\n if (typeof uri !== 'string' || !uri) return undefined;\n try {\n const u = new URL(uri);\n try { u.searchParams.set('runtime_name', hostname()); } catch { /* no hostname */ }\n const ver = (process.env.OS_RUNTIME_VERSION ?? this.version) || '';\n if (ver) u.searchParams.set('runtime_version', ver);\n return u.toString();\n } catch { return uri; }\n };\n return c.json({ success: true, data: {\n device_code: json.device_code,\n user_code: json.user_code,\n verification_uri: withContext(json.verification_uri),\n verification_uri_complete: withContext(json.verification_uri_complete),\n interval: json.interval ?? 5,\n expires_in: json.expires_in ?? 600,\n } });\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] bind/start failed', err instanceof Error ? err : new Error(String(err)));\n return c.json({ success: false, error: { code: 'device_code_failed', message: String(err?.message ?? err) } }, 502);\n }\n });\n\n // POST /bind/poll { device_code } — polls the cloud token endpoint.\n // While pending, returns { pending: true }. On success, exchanges\n // the operator token for a persisted sys_cloud_connection via the\n // control plane's /bind.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/bind/poll`, async (c: any) => {\n let body: any = {};\n try { body = await c.req.json(); } catch { body = {}; }\n let environmentId = await resolveEnvironmentId(c);\n if (!environmentId && this.cfg.singleEnvironment) {\n environmentId = String(body?.environment_id ?? body?.environmentId ?? '').trim() || undefined;\n }\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) return c.json({ success: false, error: { code: 'unauthenticated' } }, 401);\n if (!cloudUrl) return c.json({ success: false, error: { code: 'cloud_unconfigured' } }, 503);\n\n const deviceCode = String(body?.device_code ?? body?.deviceCode ?? '').trim();\n if (!deviceCode) return c.json({ success: false, error: { code: 'invalid_request', message: 'device_code is required' } }, 400);\n\n try {\n const tokResp = await fetch(`${cloudUrl}/api/v1/auth/device/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ grant_type: 'urn:ietf:params:oauth:grant-type:device_code', device_code: deviceCode, client_id: deviceClientId }),\n });\n const tok: any = await tokResp.json().catch(() => ({}));\n const accessToken = tok?.access_token;\n if (!accessToken) {\n // RFC 8628 polling errors: authorization_pending / slow_down\n // are non-terminal; everything else is terminal.\n const errCode = String(tok?.error ?? `device/token ${tokResp.status}`);\n const pending = errCode === 'authorization_pending' || errCode === 'slow_down';\n return c.json({ success: pending, data: { pending }, error: pending ? undefined : { code: errCode } }, pending ? 200 : 400);\n }\n // Persist the binding through the control plane. The\n // registration claim rides along (ADR\n // runtime-identity-binding §2.3): hostname + version name\n // the device; a stored runtime_id keeps the identity\n // stable across re-binds (claim verified cloud-side).\n const stored = this.store.read();\n const bindResp = await fetch(`${cloudUrl}/api/v1/cloud-connection/bind`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(cloudApiKey ? { Authorization: `Bearer ${cloudApiKey}` } : {}) },\n body: JSON.stringify({\n ...(environmentId ? { environment_id: environmentId } : {}),\n ...(stored?.runtimeId ? { runtime_id: stored.runtimeId } : {}),\n name: (() => { try { return hostname(); } catch { return undefined; } })(),\n runtime_version: (process.env.OS_RUNTIME_VERSION ?? this.version) || undefined,\n token: accessToken,\n scope: deviceScope,\n }),\n });\n const bindJson: any = await bindResp.json().catch(() => ({ success: false, error: 'bind failed (no body)' }));\n // The bind response carries the one-time runtime bearer.\n // Persist it HERE (server-side, 0600 file) and STRIP it\n // from what goes back to the browser — the SPA never\n // holds the credential.\n const runtimeToken = bindJson?.data?.runtime_token;\n if (bindResp.ok && typeof runtimeToken === 'string' && runtimeToken) {\n try {\n this.store.write({\n runtimeToken,\n runtimeId: bindJson?.data?.runtime_id ?? bindJson?.data?.connection?.runtime_id ?? undefined,\n environmentId: environmentId || undefined,\n controlPlaneUrl: cloudUrl,\n organizationId: bindJson?.data?.connection?.organization_id ?? undefined,\n accountEmail: bindJson?.data?.connection?.account_email ?? undefined,\n boundAt: bindJson?.data?.connection?.bound_at ?? new Date().toISOString(),\n });\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] failed to persist runtime credential', err instanceof Error ? err : new Error(String(err)));\n }\n delete bindJson.data.runtime_token;\n }\n return c.json(bindJson, bindResp.status as any);\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] bind/poll failed', err instanceof Error ? err : new Error(String(err)));\n return c.json({ success: false, error: { code: 'bind_failed', message: String(err?.message ?? err) } }, 502);\n }\n });\n\n // POST /unbind — disconnect this runtime from the control plane.\n // Revokes the connection server-side (best-effort) and clears the\n // local credential. Requires an environment session, mirroring\n // bind/start.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/unbind`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) return c.json({ success: false, error: { code: 'unauthenticated' } }, 401);\n\n // Revoke cloud-side FIRST (the oscc_ bearer self-identifies;\n // env-keyed bindings name the environment), then clear the\n // local credential regardless — a device signing out must not\n // leave a live token behind when the control plane is up.\n let revoked = false;\n if (cloudUrl && credential()) {\n try {\n const resp = await fetch(`${cloudUrl}/api/v1/cloud-connection/revoke`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...authHeaders() },\n body: JSON.stringify(environmentId ? { environment_id: environmentId } : {}),\n });\n revoked = resp.ok;\n } catch { /* control plane unreachable — local clear still proceeds */ }\n }\n // Clear the CREDENTIAL but keep the IDENTITY: a residual\n // {runtimeId} lets a later re-bind to the same org claim the\n // same registration (revive the revoked row) instead of\n // piling up a new device per disconnect cycle — same as an\n // iCloud device record surviving sign-out.\n const residualId = this.store.read()?.runtimeId;\n const cleared = (() => {\n try {\n if (residualId) {\n this.store.write({ runtimeToken: '', runtimeId: residualId });\n return true;\n }\n return this.store.clear();\n } catch { return false; }\n })();\n return c.json({ success: true, data: { environmentId: environmentId ?? null, revoked, cleared } });\n });\n\n // POST /install { package_id, seed_sample_data? } — in-environment\n // marketplace install. Authorizes the caller against the\n // environment's own session (SSO-as-owner only ever admits org\n // owners/admins), then performs the install against the cloud\n // control plane using the env→cloud service credential.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/install`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId) return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n\n // Local authz: require a valid env session. (TODO: tighten to an\n // explicit env-admin role check; today only owners/admins obtain\n // a session via SSO-as-owner.)\n const session = await resolveSession(environmentId, c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment to install apps.' } }, 401);\n }\n\n if (!cloudUrl || !credential()) {\n return c.json({ success: false, error: { code: 'cloud_unconfigured', message: 'This runtime is not connected to a cloud account; install is unavailable.' } }, 503);\n }\n\n let body: any = {};\n try { body = await c.req.json(); } catch { body = {}; }\n const packageId = String(body?.package_id ?? body?.packageId ?? '').trim();\n if (!packageId) return c.json({ success: false, error: { code: 'invalid_request', message: 'package_id is required' } }, 400);\n const seedSampleData = body?.seed_sample_data === true || body?.seedSampleData === true;\n\n // Call the cloud install endpoint in service mode. We do NOT send\n // an active org → package-install treats this as platform/CI and\n // installs unrestricted (we already authorized the env admin above).\n try {\n const resp = await fetch(`${cloudUrl}/api/v1/actions/sys_package/install_package`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...authHeaders(),\n },\n body: JSON.stringify({ recordId: packageId, params: { environment_id: environmentId, seed_sample_data: seedSampleData } }),\n });\n const json = await resp.json().catch(() => ({ success: false, error: 'install failed (no body)' }));\n return c.json(json, resp.status as any);\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] install failed', err instanceof Error ? err : new Error(String(err)));\n return c.json({ success: false, error: { code: 'install_failed', message: String(err?.message ?? err) } }, 502);\n }\n });\n\n // GET /installation?package_id=… — same-origin installed-state\n // probe. Always returns 200 with `{ installed: boolean, … }`;\n // failures to reach the control plane degrade to\n // `{ installed: false }` so the marketplace page renders (worst\n // case it offers an install the control plane upserts idempotently).\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/installation`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId) {\n // Self-hosted v2: cloud-side installation records are\n // env-scoped; a registration-only runtime tracks installs\n // locally (LocalManifestSource). Report not-installed.\n if (this.cfg.singleEnvironment) return c.json({ success: true, data: { installed: false } });\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n\n const session = await resolveSession(environmentId, c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment.' } }, 401);\n }\n\n let packageId = '';\n try {\n const u = new URL(c.req.url);\n packageId = String(u.searchParams.get('package_id') ?? u.searchParams.get('packageId') ?? '').trim();\n } catch { /* malformed URL → empty */ }\n if (!packageId) return c.json({ success: false, error: { code: 'invalid_request', message: 'package_id is required' } }, 400);\n\n // Not connected → can't know; report not-installed so the page\n // still renders (a read should never hard-fail the page).\n if (!cloudUrl || !credential()) return c.json({ success: true, data: { installed: false } });\n\n try {\n // Read installed-state from the control plane's\n // service-authenticated installations route — NOT the generic\n // `/api/v1/data/sys_package_installation` API. That data API\n // resolves identity via better-auth sessions / `sys_api_key`\n // only and rejects the `OS_CLOUD_API_KEY` service bearer (401).\n // This route shares the install route's service-key auth, so\n // the same credential that performed the install can read its\n // result back.\n const resp = await fetch(\n `${cloudUrl}/api/v1/cloud/environments/${encodeURIComponent(environmentId)}/installations/${encodeURIComponent(packageId)}`,\n { headers: { Accept: 'application/json', ...authHeaders() } },\n );\n if (!resp.ok) return c.json({ success: true, data: { installed: false } });\n const json: any = await resp.json().catch(() => ({}));\n const data: any = json?.data ?? json ?? {};\n if (!data.installed) return c.json({ success: true, data: { installed: false } });\n return c.json({ success: true, data: {\n installed: true,\n installationId: String(data.installationId ?? ''),\n version: String(data.version ?? 'installed'),\n withSampleData: data.withSampleData === true,\n } });\n } catch (err: any) {\n ctx.logger?.warn?.(`[CloudConnectionPlugin] installation probe failed: ${String(err?.message ?? err)}`);\n return c.json({ success: true, data: { installed: false } });\n }\n });\n\n // GET /installed — env's FULL installed set from the control\n // plane's `sys_package_installation`, so the Console \"Installed\"\n // view reflects packages installed via ANY path (CLI, marketplace,\n // REST) — ADR-0007 step ①. Degrades to an empty list when the\n // runtime is not cloud-connected or the control plane is\n // unreachable (never hard-fails the page).\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/installed`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId) {\n // Self-hosted v2: no env-scoped cloud install ledger —\n // the Installed view is fed by the local manifest ledger.\n if (this.cfg.singleEnvironment) {\n return c.json({ success: true, data: { packages: [], total: 0, connected: Boolean(credential()) } });\n }\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n\n const session = await resolveSession(environmentId, c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment.' } }, 401);\n }\n\n if (!cloudUrl || !credential()) {\n return c.json({ success: true, data: { packages: [], total: 0, connected: false } });\n }\n\n try {\n const resp = await fetch(\n `${cloudUrl}/api/v1/cloud/environments/${encodeURIComponent(environmentId)}/packages`,\n { headers: { Accept: 'application/json', ...authHeaders() } },\n );\n if (!resp.ok) return c.json({ success: true, data: { packages: [], total: 0, connected: true } });\n const json: any = await resp.json().catch(() => ({}));\n const data: any = json?.data ?? json ?? {};\n const packages = Array.isArray(data.packages) ? data.packages : [];\n return c.json({ success: true, data: { packages, total: packages.length, connected: true } });\n } catch (err: any) {\n ctx.logger?.warn?.(`[CloudConnectionPlugin] installed-list failed: ${String(err?.message ?? err)}`);\n return c.json({ success: true, data: { packages: [], total: 0, connected: true } });\n }\n });\n\n // GET /org-packages — org-scoped catalog for the in-env\n // Marketplace's \"Your organization\" layer (ADR-0007 step ②): the\n // env's owning org's own packages (visibility org/private), so a\n // publisher can discover + install their private apps from inside\n // the environment. Forwards (service-key) to the control plane,\n // which derives the org from environment_id.\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/org-packages`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment.' } }, 401);\n }\n\n if (!cloudUrl || !credential()) {\n return c.json({ success: true, data: { items: [], total: 0, connected: false } });\n }\n\n try {\n // env-keyed callers pass environment_id; a registration-only\n // runtime's oscc_ bearer carries the org by itself.\n const qs = environmentId ? `?environment_id=${encodeURIComponent(environmentId)}` : '';\n const resp = await fetch(\n `${cloudUrl}/api/v1/cloud/org-packages${qs}`,\n { headers: { Accept: 'application/json', ...authHeaders() } },\n );\n if (!resp.ok) return c.json({ success: true, data: { items: [], total: 0, connected: true } });\n const json: any = await resp.json().catch(() => ({}));\n const data: any = json?.data ?? json ?? {};\n const items = Array.isArray(data.items) ? data.items : [];\n return c.json({ success: true, data: { items, total: items.length, connected: true } });\n } catch (err: any) {\n ctx.logger?.warn?.(`[CloudConnectionPlugin] org-packages failed: ${String(err?.message ?? err)}`);\n return c.json({ success: true, data: { items: [], total: 0, connected: true } });\n }\n });\n\n ctx.logger?.info?.(`[CloudConnectionPlugin] mounted ${CLOUD_CONNECTION_PREFIX}/{status,bind/start,bind/poll,install,installation,installed,org-packages} → ${cloudUrl || '(cloud unconfigured)'}`);\n });\n };\n}\n\n/** Factory mirroring the package's other plugins' construction style. */\nexport function createCloudConnectionPlugin(config: CloudConnectionPluginConfig = {}): CloudConnectionPlugin {\n return new CloudConnectionPlugin(config);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Cloud Connection — SDUI surface (metadata, not React).\n *\n * The binding UI ships WITH the plugin as page + navigation metadata\n * (ADR-0029 K2: capability plugins contribute their own Setup entries;\n * cloud ADR-0008 / console-SDUI direction: new console surfaces are\n * metadata-first). The only React involved is the registered\n * `cloud-connection:panel` widget — the device-code state machine — which\n * the console registers once as a reusable primitive; everything else\n * (page shell, nav placement, labels) is server-driven and can evolve\n * without a console release.\n */\n\nimport type { Page } from '@objectstack/spec/ui';\n\n/** Setup page hosting the binding panel widget. */\nexport const CloudConnectionSettingsPage: Page = {\n name: 'cloud_connection_settings',\n label: 'Cloud Connection',\n type: 'app',\n template: 'default',\n kind: 'full',\n isDefault: false,\n regions: [\n {\n name: 'header',\n width: 'full',\n components: [\n {\n type: 'page:header',\n properties: {\n title: 'Cloud Connection',\n subtitle:\n 'Connect this runtime to an ObjectStack control plane to browse your '\n + 'organization\\'s private packages and install them here.',\n icon: 'cloud',\n },\n },\n ],\n },\n {\n name: 'main',\n width: 'large',\n components: [\n {\n // Registered console widget — the RFC 8628 device-code\n // state machine (status → start → user-code display →\n // poll → bound / disconnect). Talks to the same-origin\n // /api/v1/cloud-connection/* routes this plugin mounts.\n type: 'cloud-connection:panel',\n properties: {},\n },\n ],\n },\n ],\n};\n\n/** Setup-nav contribution: System group, after the marketplace entries. */\nexport const CLOUD_CONNECTION_NAV_CONTRIBUTIONS = [\n {\n app: 'setup',\n group: 'group_apps',\n priority: 200,\n items: [\n {\n id: 'nav_cloud_connection',\n type: 'page',\n pageName: 'cloud_connection_settings',\n label: 'Cloud Connection',\n icon: 'cloud',\n },\n ],\n },\n];\n\n/** Manifest bundle the plugin registers so the page + nav reach the kernel. */\nexport const CLOUD_CONNECTION_UI_BUNDLE = {\n id: 'com.objectstack.cloud-connection.ui',\n namespace: 'sys',\n version: '0.1.0',\n type: 'plugin',\n scope: 'system',\n name: 'Cloud Connection UI',\n description: 'Setup page + navigation for binding this runtime to a control plane.',\n pages: [CloudConnectionSettingsPage],\n navigationContributions: CLOUD_CONNECTION_NAV_CONTRIBUTIONS,\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * RuntimeConfigPlugin\n *\n * Serves `GET /api/v1/runtime/config` (and the legacy alias\n * `GET /api/v1/studio/runtime-config`) so the Console / Studio SPA can learn\n * the upstream cloud URL and capability flags **at boot time**, instead of\n * sniffing `window.location.hostname` or reading Vite-time env vars.\n *\n * Response shape:\n *\n * {\n * cloudUrl: string, // base URL of the upstream cloud ('' = same origin)\n * singleEnvironment: boolean,\n * defaultOrgId?, defaultEnvironmentId?, // multi-tenant, per-hostname\n * features: { installLocal, marketplace, aiStudio, autoPublishAiBuilds },\n * branding: { productName, productShortName }\n * }\n *\n * ## Policy seam (ADR-0008 / open-mechanism-closed-intelligence)\n *\n * Which features a *plan* unlocks is distribution policy, not mechanism — it\n * intentionally does NOT live in this open package. Hosts inject it via\n * {@link RuntimeConfigPluginConfig.resolvePlanFeatures}: the cloud\n * distribution passes its plan-entitlement rules there; a self-hosted or\n * vanilla deployment omits it and gets static config-driven flags.\n */\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { resolveCloudUrl } from './cloud-url.js';\n\n/** Capability flags a host's plan policy can derive per request. */\nexport interface RuntimeConfigPlanFeatures {\n /** Whether the SPA should surface AI-driven metadata authoring. */\n aiStudio?: boolean;\n /** Whether AI-built apps auto-publish in the author's own environment. */\n autoPublishAiBuilds?: boolean;\n}\n\nexport interface RuntimeConfigPluginConfig {\n /**\n * Upstream cloud base URL. Falls back to `resolveCloudUrl()` (reads\n * `OS_CLOUD_URL` / built-in default) when omitted. Pass an explicit\n * empty string to declare \"this runtime IS the cloud\" (same-origin\n * for marketplace + install).\n */\n controlPlaneUrl?: string;\n /** Override the `features.installLocal` flag. Default: false. */\n installLocal?: boolean;\n /**\n * Override the `features.aiStudio` flag — whether the SPA should surface\n * AI-driven metadata authoring (\"online development\") affordances.\n * Default: true (the actual authoring capability is still gated\n * server-side; set false to force-hide the authoring UI).\n */\n aiStudio?: boolean;\n /**\n * Report this runtime as a single-environment deployment (CLI\n * `objectstack dev` / `os serve`). Defaults to `false` for\n * multi-tenant deployments.\n */\n singleEnvironment?: boolean;\n /**\n * Product name shown in browser title, splash screen, and other\n * client chrome. Operators can override per-deployment (white-label,\n * regional rebrands). Falls back to `OS_PRODUCT_NAME` env var, then\n * to the default `'ObjectOS'`.\n */\n productName?: string;\n /** Short product name (PWA shortName, compact spots). Defaults to productName. */\n productShortName?: string;\n /**\n * Plan → feature policy hook. Called with `undefined` for the static\n * default (no environment resolved / no plan known) and with the\n * environment's plan string once hostname resolution provides one.\n * Returned flags override the static config defaults; omitted keys keep\n * them. When the hook itself is omitted, flags are purely config-driven.\n */\n resolvePlanFeatures?: (plan: string | undefined) => RuntimeConfigPlanFeatures;\n}\n\nexport class RuntimeConfigPlugin implements Plugin {\n readonly name = 'com.objectstack.runtime.runtime-config';\n readonly version = '1.0.0';\n\n private readonly cloudUrl: string;\n private readonly installLocal: boolean;\n private readonly aiStudio: boolean;\n private readonly singleEnvironment: boolean;\n private readonly productName: string;\n private readonly productShortName: string;\n private readonly resolvePlanFeatures?: (plan: string | undefined) => RuntimeConfigPlanFeatures;\n\n constructor(config: RuntimeConfigPluginConfig = {}) {\n // An explicit empty string means \"stay on this origin\" — bypass the\n // resolver which would otherwise fall back to the default cloud URL.\n this.cloudUrl = config.controlPlaneUrl === ''\n ? ''\n : (resolveCloudUrl(config.controlPlaneUrl) ?? '');\n this.installLocal = !!config.installLocal;\n this.aiStudio = config.aiStudio !== false; // default true (override-to-hide)\n this.singleEnvironment = !!config.singleEnvironment;\n this.resolvePlanFeatures = config.resolvePlanFeatures;\n const envName = (typeof process !== 'undefined' ? process.env?.OS_PRODUCT_NAME : undefined)?.trim();\n const envShort = (typeof process !== 'undefined' ? process.env?.OS_PRODUCT_SHORT_NAME : undefined)?.trim();\n this.productName = (config.productName ?? envName ?? 'ObjectOS').trim() || 'ObjectOS';\n this.productShortName = (config.productShortName ?? envShort ?? this.productName).trim() || this.productName;\n }\n\n init = async (_ctx: PluginContext): Promise<void> => {};\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n let httpServer: any;\n try {\n httpServer = ctx.getService('http-server');\n } catch {\n ctx.logger?.warn?.('[RuntimeConfigPlugin] http-server not available — runtime/config not mounted');\n return;\n }\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[RuntimeConfigPlugin] http-server missing getRawApp() — runtime/config not mounted');\n return;\n }\n const rawApp = httpServer.getRawApp();\n\n // A multi-tenant runtime serves many subdomains, each mapped to\n // one environment. Telling the SPA *which* environment it is\n // attached to (per-request) lets the App Marketplace skip the\n // env-picker dialog and install directly into \"this\" env — the\n // operator's domain already identifies it.\n //\n // Hostname → env is resolved by the same registry the per-env\n // kernel router uses (env-registry). Falls back to the static\n // payload when the host doesn't map to any env (e.g. a marketing\n // root or a CLI-served single-env runtime).\n let envRegistry: any = null;\n try { envRegistry = ctx.getService('env-registry'); } catch { /* not mounted (file/CLI mode) */ }\n\n const featuresFor = (plan: string | undefined, base: { aiStudio: boolean; autoPublishAiBuilds: boolean }) => {\n const derived = this.resolvePlanFeatures?.(plan);\n return {\n aiStudio: derived?.aiStudio ?? base.aiStudio,\n autoPublishAiBuilds: derived?.autoPublishAiBuilds ?? base.autoPublishAiBuilds,\n };\n };\n\n const handler = async (c: any) => {\n const rawHost = c.req.header('host') ?? '';\n const host = rawHost.split(':')[0].toLowerCase().trim();\n let defaultEnvironmentId: string | undefined;\n let defaultOrgId: string | undefined;\n let resolvedSingleEnv = this.singleEnvironment;\n // Static defaults: config-driven, optionally shaped by the\n // host's policy hook for the \"no plan known\" case.\n let features = featuresFor(undefined, { aiStudio: this.aiStudio, autoPublishAiBuilds: false });\n // EnvironmentDriverRegistry exposes `resolveByHostname()`;\n // older code paths used `resolveHostname()` on the client.\n // Accept either so production runtimes don't silently no-op\n // and leave the SPA showing the env picker.\n const resolveFn: ((h: string) => Promise<any>) | null =\n typeof envRegistry?.resolveByHostname === 'function'\n ? envRegistry.resolveByHostname.bind(envRegistry)\n : typeof envRegistry?.resolveHostname === 'function'\n ? envRegistry.resolveHostname.bind(envRegistry)\n : null;\n if (resolveFn && host) {\n try {\n const resolved = await resolveFn(host);\n if (resolved?.environmentId) {\n defaultEnvironmentId = String(resolved.environmentId);\n const orgId = resolved.organizationId ?? resolved.organization_id;\n if (orgId) defaultOrgId = String(orgId);\n // Each subdomain is one environment from the\n // operator's POV: surface as single-environment\n // so the SPA hides multi-env affordances.\n resolvedSingleEnv = true;\n // Plan-derived features — only an explicit\n // non-empty plan re-runs the policy hook.\n if (typeof resolved.plan === 'string' && resolved.plan.trim() !== '') {\n features = featuresFor(resolved.plan, features);\n }\n }\n } catch {\n // Resolver failures are non-fatal — fall through\n // to the static payload so /runtime/config never\n // 500s. Worst case the SPA shows its env picker.\n }\n }\n return c.json({\n cloudUrl: this.cloudUrl,\n singleEnvironment: resolvedSingleEnv,\n defaultOrgId,\n defaultEnvironmentId,\n features: {\n installLocal: this.installLocal,\n marketplace: true,\n aiStudio: features.aiStudio,\n autoPublishAiBuilds: features.autoPublishAiBuilds,\n },\n branding: {\n productName: this.productName,\n productShortName: this.productShortName,\n },\n });\n };\n rawApp.get('/api/v1/runtime/config', handler);\n // Legacy alias for older Studio bundles.\n rawApp.get('/api/v1/studio/runtime-config', handler);\n ctx.logger?.info?.('[RuntimeConfigPlugin] mounted /api/v1/runtime/config', {\n cloudUrl: this.cloudUrl || '(empty)',\n installLocal: this.installLocal,\n perHostEnvResolution: !!envRegistry,\n });\n });\n };\n\n destroy = async (): Promise<void> => {};\n}\n"],"mappings":"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","names":["headers","body","existsSync","mkdirSync","readFileSync","unlinkSync","writeFileSync","resolve","authSvc","bound"]}
1
+ {"version":3,"sources":["../src/cloud-url.ts","../src/marketplace-public-url.ts","../src/marketplace-ui.ts","../src/marketplace-proxy-plugin.ts","../src/marketplace-install-local-plugin.ts","../src/local-manifest-source.ts","../src/connection-credential-store.ts","../src/cloud-connection-plugin.ts","../src/cloud-connection-ui.ts","../src/runtime-config-plugin.ts"],"sourcesContent":["// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Shared marketplace / cloud control-plane defaults.\n *\n * Centralised so every plugin + the CLI auto-inject path agree on\n * \"what cloud URL do we mean when the user didn't set OS_CLOUD_URL?\".\n * Until we have a competing public hosted cloud, this points at the\n * ObjectStack-operated control plane so a vanilla `objectstack dev` can\n * browse the marketplace out of the box.\n */\nexport const DEFAULT_CLOUD_URL = 'https://cloud.objectos.ai';\n\n/**\n * Resolve the effective control-plane URL from an explicit constructor\n * value, the OS_CLOUD_URL env var, or the default. Returns an empty\n * string when the caller explicitly disabled cloud with\n * `OS_CLOUD_URL=off` / `local` — callers should treat that as\n * \"marketplace unavailable on this runtime\".\n */\nexport function resolveCloudUrl(explicit?: string | null): string {\n const raw = (explicit ?? process.env.OS_CLOUD_URL ?? '').trim();\n const lower = raw.toLowerCase();\n if (lower === 'off' || lower === 'none' || lower === 'local' || lower === 'disabled') {\n return '';\n }\n const picked = raw || DEFAULT_CLOUD_URL;\n return picked.replace(/\\/+$/, '');\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Marketplace public R2 base URL — when set, points at a Cloudflare R2\n * bucket (custom domain or `pub-*.r2.dev`) that serves pre-rendered\n * marketplace browse + install JSON snapshots. The snapshots are\n * written by ObjectStack Cloud (`packages/service-cloud/src/marketplace-snapshot.ts`).\n *\n * Architecture: cloud writes, tenants read directly from R2 → CDN.\n * Marketplace browse + install never touch the cloud control plane,\n * so Cloud cold-start (~12s) is bypassed entirely and the read path\n * scales to CF's edge capacity for free.\n *\n * Default: when OS_MARKETPLACE_PUBLIC_BASE_URL is unset we skip the\n * public fast-path and fall back to the legacy cloud proxy. Once the\n * R2 bucket public domain is wired up in operations, set\n * `OS_MARKETPLACE_PUBLIC_BASE_URL=https://marketplace.objectos.ai`\n * (or your own custom domain) to enable. Set to \"off\" / \"none\" to\n * explicitly disable even if a default is configured.\n *\n * Path layout under the base URL (matches the snapshot writer):\n * <base>/packages.json\n * <base>/packages/{id}.json\n * <base>/packages/{id}/versions/{versionId}/manifest.json\n * <base>/packages/{id}/versions/latest/manifest.json\n *\n * Each JSON file is already in the same `{ success: true, data: ... }`\n * shape as the corresponding cloud API endpoint, so callers can\n * substitute one for the other transparently.\n */\n\n/**\n * Resolve the effective public marketplace base URL. Returns an empty\n * string when the public fast-path is disabled — callers should fall\n * back to fetching via the cloud control plane.\n */\nexport function resolveMarketplacePublicBaseUrl(explicit?: string | null): string {\n const raw = (explicit ?? process.env.OS_MARKETPLACE_PUBLIC_BASE_URL ?? '').trim();\n const lower = raw.toLowerCase();\n if (!raw || lower === 'off' || lower === 'none' || lower === 'disabled' || lower === 'false') {\n return '';\n }\n return raw.replace(/\\/+$/, '');\n}\n\n/**\n * Map an incoming `/api/v1/marketplace/...` API path to a public R2\n * object key (relative — caller prepends the base URL).\n *\n * Returns `null` when the path is not snapshot-backed. Today three\n * paths are covered (list, detail, manifest); anything else (search\n * with non-trivial filters, install actions, etc.) routes via cloud.\n *\n * Query strings are NOT included in the returned key — R2 is static.\n * Callers that need filtering must fetch the full snapshot and filter\n * client-side.\n */\nexport function publicMarketplaceKeyForApiPath(pathname: string): string | null {\n const prefix = '/api/v1/marketplace/packages';\n if (pathname === prefix) return 'packages.json';\n if (!pathname.startsWith(`${prefix}/`)) return null;\n const tail = pathname.slice(prefix.length + 1);\n if (!tail) return null;\n const parts = tail.split('/');\n // /packages/{id}\n if (parts.length === 1) {\n const id = decodeURIComponent(parts[0] ?? '');\n if (!id) return null;\n return `packages/${encodeURIComponent(id)}.json`;\n }\n // /packages/{id}/versions/{versionId}/manifest\n if (parts.length === 4 && parts[1] === 'versions' && parts[3] === 'manifest') {\n const id = decodeURIComponent(parts[0] ?? '');\n const versionId = decodeURIComponent(parts[2] ?? '');\n if (!id || !versionId) return null;\n return `packages/${encodeURIComponent(id)}/versions/${encodeURIComponent(versionId)}/manifest.json`;\n }\n return null;\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Marketplace — plugin-owned Setup navigation (cloud ADR-0009: cloud\n * functionality ships as plugins carrying their FULL UI surface).\n *\n * Ownership moved here from `@objectstack/platform-objects`'\n * setup-nav.contributions.ts (ADR-0029 K2's standing direction): the nav\n * entry now lives and dies with the capability —\n *\n * - no MarketplaceProxyPlugin mounted (`OS_CLOUD_URL=off`) → no\n * \"Browse Marketplace\" entry → no dead page.\n * - no MarketplaceInstallLocalPlugin → no \"Installed Apps\" entry.\n *\n * The URLs still point at the console's existing marketplace routes; the\n * pages themselves migrate to plugin-carried metadata in later ADR-0009\n * stages (Installed Apps first).\n */\n\n/** \"Browse Marketplace\" — owned by the browse capability (the proxy). */\nexport const MARKETPLACE_BROWSE_UI_BUNDLE = {\n id: 'com.objectstack.cloud-connection.marketplace-browse-ui',\n namespace: 'sys',\n version: '0.1.0',\n type: 'plugin',\n scope: 'system',\n name: 'Marketplace Browse UI',\n description: 'Setup navigation for the public marketplace catalog (browse).',\n navigationContributions: [\n {\n app: 'setup',\n group: 'group_apps',\n priority: 100,\n items: [\n { id: 'nav_marketplace_browse', type: 'url', label: 'Browse Marketplace', url: '/apps/setup/system/marketplace', icon: 'store' },\n ],\n },\n ],\n};\n\n/** \"Installed Apps\" — owned by the local-install capability (ADR-0009 P2a:\n * the page itself is now metadata; the console provides only the\n * `marketplace:installed-list` widget). */\nexport const MarketplaceInstalledPage = {\n name: 'marketplace_installed',\n label: 'Installed Apps',\n type: 'app' as const,\n template: 'default',\n kind: 'full' as const,\n isDefault: false,\n regions: [\n {\n name: 'header',\n width: 'full' as const,\n components: [\n {\n type: 'page:header',\n properties: {\n title: 'Installed Apps',\n subtitle: 'Marketplace packages currently installed into this runtime\\'s kernel.',\n icon: 'package-check',\n },\n },\n ],\n },\n {\n name: 'main',\n width: 'large' as const,\n components: [\n { type: 'marketplace:installed-list', properties: {} },\n ],\n },\n ],\n};\n\nexport const MARKETPLACE_INSTALLED_UI_BUNDLE = {\n id: 'com.objectstack.cloud-connection.marketplace-installed-ui',\n namespace: 'sys',\n version: '0.2.0',\n type: 'plugin',\n scope: 'system',\n name: 'Marketplace Installed UI',\n description: 'Installed Apps page + Setup navigation for locally-installed marketplace packages.',\n pages: [MarketplaceInstalledPage],\n navigationContributions: [\n {\n app: 'setup',\n group: 'group_apps',\n priority: 110,\n items: [\n { id: 'nav_marketplace_installed', type: 'page', pageName: 'marketplace_installed', label: 'Installed Apps', icon: 'package-check' },\n ],\n },\n ],\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * MarketplaceProxyPlugin\n *\n * Forwards `GET /api/v1/marketplace/*` from a tenant ObjectOS runtime to\n * the configured ObjectStack Cloud control-plane URL. The cloud endpoint\n * is unauthenticated and only exposes packages whose owner has opted in\n * to the public catalog (`sys_package.marketplace_listed = true`) — so the\n * proxy passes through without any credentials.\n *\n * Why proxy instead of direct browser → cloud:\n * - The Console SPA stays on the tenant origin, so no CORS configuration\n * is required on the cloud side.\n * - Local-dev `os serve` works regardless of whether the developer's\n * browser has cookies for cloud.objectos.ai.\n * - Adds a single, easily auditable network seam between tenant and\n * control plane.\n *\n * Install is NOT proxied here. Installing a package mutates control-plane\n * state and requires a cloud session + active organization context — the\n * Console SPA performs install by opening the cloud's install dialog in a\n * new tab so the user authenticates against cloud directly. A future\n * iteration may introduce a delegated install token; until then, browse\n * here and install on cloud.\n */\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { resolveCloudUrl } from './cloud-url.js';\nimport { MARKETPLACE_BROWSE_UI_BUNDLE } from './marketplace-ui.js';\nimport {\n resolveMarketplacePublicBaseUrl,\n publicMarketplaceKeyForApiPath,\n} from './marketplace-public-url.js';\n\nconst MARKETPLACE_PREFIX = '/api/v1/marketplace';\n\n/**\n * In-memory cache for GET/HEAD marketplace responses.\n *\n * Marketplace data changes infrequently (new package versions are\n * audited & published in ~hours, not seconds), so we cache aggressively\n * with conditional revalidation:\n *\n * - listing/search → 30 min hard TTL\n * - package detail → 2 h\n * - version detail /\n * readme / assets → 24 h (versions are immutable once published)\n *\n * After TTL expiry the next request issues an `If-None-Match` /\n * `If-Modified-Since` and, on `304 Not Modified`, simply refreshes the\n * TTL without re-downloading the body.\n *\n * Bypass conditions (always re-fetch, no cache write):\n * - `OS_MARKETPLACE_CACHE=off`\n * - Request header `Cache-Control: no-cache` (the Console SPA's\n * \"Refresh\" button sets this)\n * - Non-2xx upstream responses (avoid pinning transient errors)\n *\n * Every response carries `X-Cache: HIT|REVALIDATED|MISS|BYPASS` to make\n * the layer observable in browser devtools.\n */\nconst DEFAULT_LRU_MAX = 200;\nconst LIST_TTL_MS = 30 * 60 * 1000; // 30 min\nconst PACKAGE_TTL_MS = 2 * 60 * 60 * 1000; // 2 h\nconst VERSION_TTL_MS = 24 * 60 * 60 * 1000; // 24 h\n\ninterface CacheEntry {\n status: number;\n body: ArrayBuffer;\n headers: Record<string, string>;\n etag?: string;\n lastModified?: string;\n expiresAt: number;\n ttlMs: number;\n}\n\nfunction ttlForPath(pathname: string): number {\n // `/api/v1/marketplace/packages/:id/versions/:v(.../...)?` → 24h\n if (/\\/packages\\/[^/]+\\/versions\\//.test(pathname)) return VERSION_TTL_MS;\n // `/api/v1/marketplace/packages/:id(/readme)?` → 2h\n if (/\\/packages\\/[^/]+/.test(pathname)) return PACKAGE_TTL_MS;\n // Listings, search, categories, anything else → 30 min\n return LIST_TTL_MS;\n}\n\nclass LruTtlCache {\n private readonly map = new Map<string, CacheEntry>();\n constructor(private readonly max: number) {}\n\n get(key: string): CacheEntry | undefined {\n const entry = this.map.get(key);\n if (!entry) return undefined;\n // LRU touch: re-insert to move to end.\n this.map.delete(key);\n this.map.set(key, entry);\n return entry;\n }\n\n set(key: string, entry: CacheEntry): void {\n if (this.map.has(key)) this.map.delete(key);\n this.map.set(key, entry);\n while (this.map.size > this.max) {\n const oldest = this.map.keys().next().value;\n if (oldest === undefined) break;\n this.map.delete(oldest);\n }\n }\n\n clear(): void {\n this.map.clear();\n }\n}\n\nexport interface MarketplaceProxyPluginConfig {\n /**\n * Control-plane base URL (e.g. https://cloud.objectos.ai). When the\n * caller passes nothing AND the runtime has no OS_CLOUD_URL set, the\n * plugin falls back to the public ObjectStack-operated cloud so that\n * `objectstack dev` can browse the marketplace out of the box. Set\n * OS_CLOUD_URL=off (or `local`) to opt out — the plugin then mounts\n * a stub that responds 503 and the SPA renders an empty-state\n * explaining marketplace is unavailable in this runtime.\n */\n controlPlaneUrl?: string;\n\n /**\n * Disable the in-memory response cache (testing / debugging).\n * Defaults to the value of `OS_MARKETPLACE_CACHE` (anything in\n * {\"off\",\"false\",\"0\",\"no\"} disables).\n */\n cacheDisabled?: boolean;\n\n /**\n * Override the LRU upper bound. Defaults to 200 entries.\n */\n cacheMaxEntries?: number;\n /**\n * Public R2 base URL for marketplace snapshots. When set, GETs for\n * snapshot-backed paths (`/packages`, `/packages/:id`,\n * `/packages/:id/versions/:vid/manifest`) are fetched directly from\n * R2 (CF edge) — bypassing the cloud control plane entirely.\n * Defaults to the value of OS_MARKETPLACE_PUBLIC_BASE_URL. Empty\n * string disables the public fast-path (legacy cloud-proxy only).\n */\n publicMarketplaceBaseUrl?: string;\n}\n\nexport class MarketplaceProxyPlugin implements Plugin {\n readonly name = 'com.objectstack.runtime.marketplace-proxy';\n readonly version = '1.1.0';\n\n private readonly cloudUrl: string;\n private readonly publicBaseUrl: string;\n private readonly cache: LruTtlCache | null;\n\n constructor(config: MarketplaceProxyPluginConfig = {}) {\n this.cloudUrl = resolveCloudUrl(config.controlPlaneUrl);\n this.publicBaseUrl = resolveMarketplacePublicBaseUrl(config.publicMarketplaceBaseUrl);\n\n const envFlag = (process.env.OS_MARKETPLACE_CACHE ?? '').trim().toLowerCase();\n const envDisabled = ['off', 'false', '0', 'no', 'disable', 'disabled'].includes(envFlag);\n const disabled = config.cacheDisabled ?? envDisabled;\n this.cache = disabled\n ? null\n : new LruTtlCache(Math.max(8, config.cacheMaxEntries ?? DEFAULT_LRU_MAX));\n }\n\n init = async (_ctx: PluginContext): Promise<void> => {\n // No services registered — pure HTTP wiring during start().\n };\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n // Plugin-owned Setup nav (cloud ADR-0009): the \"Browse\n // Marketplace\" entry ships WITH the browse capability — no\n // proxy mounted, no entry. Best-effort: headless kernels\n // simply have no Setup surface.\n try {\n const manifest = ctx.getService<{ register(m: any): void }>('manifest');\n manifest?.register?.(MARKETPLACE_BROWSE_UI_BUNDLE);\n } catch { /* no manifest service */ }\n\n let httpServer: any;\n try {\n httpServer = ctx.getService('http-server');\n } catch {\n ctx.logger?.warn?.('[MarketplaceProxyPlugin] http-server not available — marketplace routes not mounted');\n return;\n }\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[MarketplaceProxyPlugin] http-server missing getRawApp() — marketplace routes not mounted');\n return;\n }\n\n const rawApp = httpServer.getRawApp();\n const cloudUrl = this.cloudUrl;\n const publicBaseUrl = this.publicBaseUrl;\n const cache = this.cache;\n\n if (publicBaseUrl) {\n ctx.logger?.info?.(`[MarketplaceProxyPlugin] public R2 fast-path enabled → ${publicBaseUrl}`);\n }\n\n const handler = async (c: any, next: any) => {\n if (!cloudUrl) {\n return c.json({\n success: false,\n error: {\n code: 'marketplace_unavailable',\n message: 'No control-plane URL configured for this runtime (OS_CLOUD_URL).',\n },\n }, 503);\n }\n try {\n const incomingUrl = new URL(c.req.url);\n // Do NOT proxy install-local — those are owned by\n // MarketplaceInstallLocalPlugin and must hit this\n // runtime, never cloud. Pass through so Hono can match\n // the install-local route registered on the same app.\n if (incomingUrl.pathname.startsWith(`${MARKETPLACE_PREFIX}/install-local`)) {\n return next();\n }\n\n const method = String(c.req.method ?? 'GET').toUpperCase();\n\n // ── Public R2 fast-path ─────────────────────────\n // When OS_MARKETPLACE_PUBLIC_BASE_URL is configured,\n // GETs for snapshot-backed paths fetch directly from\n // R2 → CF edge cache. This skips the cloud control\n // plane entirely so marketplace browse + install\n // work even when cloud is asleep or completely down.\n if (publicBaseUrl && (method === 'GET' || method === 'HEAD')) {\n const r2Resp = await tryPublicMarketplaceFetch(\n publicBaseUrl, incomingUrl, method, c.req.header('accept'),\n ctx.logger,\n );\n if (r2Resp) return r2Resp;\n // Fall through on miss / error to the cloud path.\n }\n\n // Preserve the full /api/v1/marketplace/... path on cloud.\n const target = `${cloudUrl}${incomingUrl.pathname}${incomingUrl.search}`;\n\n // Browse-only mechanism: this plugin forwards only safe,\n // idempotent GET/HEAD (it carries no credentialled cloud\n // auth). It does NOT own install *policy* — that is a host\n // concern (ObjectStack Cloud supplies a credentialled\n // install route via the `extraPlugins` seam; see ADR\n // docs/design/cloud-account-binding-marketplace-install.md\n // §5.2). So instead of dead-ending non-GET with a 405\n // \"install via cloud\", we PASS THROUGH: a host-supplied\n // handler mounted after this plugin can claim the request;\n // if none does, the app returns its normal 404. This\n // removes the browse-only install dead-end (framework#1548)\n // without this plugin pretending to know install policy.\n if (method !== 'GET' && method !== 'HEAD') {\n return next();\n }\n\n // Cache lookup. Key includes accept-language because\n // cloud may serve locale-specific copy in the future;\n // HEAD shares the cache slot with GET (we just elide the\n // body in the response).\n const accept = c.req.header('accept') ?? 'application/json';\n const acceptLang = c.req.header('accept-language') ?? '';\n const cacheKey = `${incomingUrl.pathname}${incomingUrl.search}|al=${acceptLang}|a=${accept}`;\n const reqCacheCtl = (c.req.header('cache-control') ?? '').toLowerCase();\n const bypass = !cache || reqCacheCtl.includes('no-cache') || reqCacheCtl.includes('no-store');\n const now = Date.now();\n\n if (cache && !bypass) {\n const hit = cache.get(cacheKey);\n if (hit && hit.expiresAt > now) {\n return buildCachedResponse(hit, method, 'HIT');\n }\n if (hit) {\n // TTL expired — try conditional revalidate so we\n // don't pay for the body when nothing changed.\n const revalHeaders: Record<string, string> = {\n 'Accept': accept,\n 'User-Agent': `objectos-marketplace-proxy/${MarketplaceProxyPlugin.prototype.version ?? '1.0.0'}`,\n };\n if (acceptLang) revalHeaders['Accept-Language'] = acceptLang;\n if (hit.etag) revalHeaders['If-None-Match'] = hit.etag;\n if (hit.lastModified) revalHeaders['If-Modified-Since'] = hit.lastModified;\n const revalResp = await fetch(target, { method: 'GET', headers: revalHeaders });\n if (revalResp.status === 304) {\n hit.expiresAt = now + hit.ttlMs;\n // Refresh ETag/Last-Modified if the upstream\n // re-issued them on the 304 (per RFC 7232 §4.1).\n const newEtag = revalResp.headers.get('etag');\n const newLm = revalResp.headers.get('last-modified');\n if (newEtag) hit.etag = newEtag;\n if (newLm) hit.lastModified = newLm;\n cache.set(cacheKey, hit);\n return buildCachedResponse(hit, method, 'REVALIDATED');\n }\n // 200 (or anything else): fall through to the\n // normal fetch+store path below, using the\n // revalidation response we already have in hand.\n return await consumeAndMaybeCache(revalResp, cacheKey, incomingUrl.pathname, method, cache);\n }\n }\n\n // MISS (or BYPASS): origin fetch.\n const reqHeaders: Record<string, string> = {\n // Strip the inbound Host header — fetch will set\n // it to the cloud host. Forward only the\n // identifying headers cloud might log.\n 'Accept': accept,\n 'User-Agent': `objectos-marketplace-proxy/${MarketplaceProxyPlugin.prototype.version ?? '1.0.0'}`,\n };\n if (acceptLang) reqHeaders['Accept-Language'] = acceptLang;\n const resp = await fetch(target, { method: 'GET', headers: reqHeaders });\n\n if (bypass || !cache) {\n // Don't write to cache; just stream back.\n return await passthroughResponse(resp, method, bypass ? 'BYPASS' : 'MISS');\n }\n return await consumeAndMaybeCache(resp, cacheKey, incomingUrl.pathname, method, cache);\n } catch (err: any) {\n const errObj = err instanceof Error ? err : new Error(err?.message ?? String(err));\n ctx.logger?.error?.('[MarketplaceProxyPlugin] proxy failed', errObj);\n return c.json({\n success: false,\n error: {\n code: 'marketplace_proxy_failed',\n message: err?.message ?? String(err),\n },\n }, 502);\n }\n };\n\n if (typeof rawApp.all === 'function') {\n rawApp.all(`${MARKETPLACE_PREFIX}/*`, handler);\n } else {\n for (const m of ['get', 'head'] as const) {\n try { rawApp[m]?.(`${MARKETPLACE_PREFIX}/*`, handler); } catch { /* best effort */ }\n }\n }\n\n ctx.logger?.info?.(`[MarketplaceProxyPlugin] mounted at ${MARKETPLACE_PREFIX}/* → ${cloudUrl || '(unconfigured)'} (cache=${this.cache ? 'on' : 'off'})`);\n });\n };\n}\n\n// ---------------------------------------------------------------------------\n// Public R2 fast-path (module-private)\n// ---------------------------------------------------------------------------\n\n/**\n * Fetch a marketplace API path from the public R2 base URL and return\n * the response shaped exactly like the cloud API endpoint would. The\n * snapshots are already in `{ success: true, data: ... }` shape so for\n * direct lookups we stream bytes verbatim. The list endpoint applies\n * query-string filters (q / category / limit / offset) client-side\n * from the full snapshot.\n *\n * Returns `null` for any of:\n * - path is not snapshot-backed (e.g. featured / categories / etc.)\n * - R2 returned 404 (snapshot not yet generated for this id)\n * - network error fetching from R2\n *\n * On `null`, the caller falls back to the cloud proxy path.\n */\nasync function tryPublicMarketplaceFetch(\n publicBaseUrl: string,\n incomingUrl: URL,\n method: string,\n acceptHeader: string | undefined,\n logger: any,\n): Promise<Response | null> {\n const key = publicMarketplaceKeyForApiPath(incomingUrl.pathname);\n if (!key) return null;\n\n const target = `${publicBaseUrl}/${key}`;\n let resp: Response;\n try {\n resp = await fetch(target, {\n method: 'GET',\n headers: {\n 'Accept': acceptHeader || 'application/json',\n 'User-Agent': `objectos-marketplace-proxy/public-r2`,\n },\n });\n } catch (err: any) {\n logger?.warn?.(`[MarketplaceProxyPlugin] public R2 fetch failed (${target}): ${err?.message ?? err}`);\n return null;\n }\n if (resp.status === 404) return null;\n if (!resp.ok) {\n logger?.warn?.(`[MarketplaceProxyPlugin] public R2 ${target} returned ${resp.status} — falling back to cloud`);\n return null;\n }\n\n // List endpoint: apply optional q/category/limit/offset filters on\n // the full snapshot. Detail + manifest snapshots stream verbatim.\n const isList = key === 'packages.json';\n const hasFilters = isList && (\n incomingUrl.searchParams.has('q') ||\n incomingUrl.searchParams.has('category') ||\n incomingUrl.searchParams.has('limit') ||\n incomingUrl.searchParams.has('offset')\n );\n\n if (!hasFilters) {\n // Verbatim passthrough — preserve cache headers from R2 / CF.\n const headers = new Headers();\n const ct = resp.headers.get('content-type') ?? 'application/json; charset=utf-8';\n headers.set('content-type', ct);\n const cc = resp.headers.get('cache-control');\n if (cc) headers.set('cache-control', cc);\n const etag = resp.headers.get('etag');\n if (etag) headers.set('etag', etag);\n headers.set('x-cache', 'PUBLIC-R2');\n const body = method === 'HEAD' ? null : resp.body;\n return new Response(body, { status: 200, headers });\n }\n\n // Filtered list — parse, filter, re-serialize.\n let snapshot: any;\n try { snapshot = await resp.json(); }\n catch (err: any) {\n logger?.warn?.(`[MarketplaceProxyPlugin] public R2 list snapshot parse failed: ${err?.message ?? err}`);\n return null;\n }\n const items: any[] = Array.isArray(snapshot?.data?.items) ? snapshot.data.items : [];\n\n const q = (incomingUrl.searchParams.get('q') ?? '').trim().toLowerCase();\n const category = (incomingUrl.searchParams.get('category') ?? '').trim();\n const limit = Math.min(Math.max(Number(incomingUrl.searchParams.get('limit') ?? 50), 1), 100);\n const offset = Math.max(Number(incomingUrl.searchParams.get('offset') ?? 0), 0);\n\n let filtered = items;\n if (q) {\n filtered = filtered.filter((r) => {\n const dn = String(r?.display_name ?? '').toLowerCase();\n const mid = String(r?.manifest_id ?? '').toLowerCase();\n return dn.includes(q) || mid.includes(q);\n });\n }\n if (category) {\n filtered = filtered.filter((r) => String(r?.category ?? '') === category);\n }\n const total = filtered.length;\n const page = filtered.slice(offset, offset + limit);\n const body = JSON.stringify({ success: true, data: { items: page, total, limit, offset } });\n\n const headers = new Headers({\n 'content-type': 'application/json; charset=utf-8',\n 'cache-control': 'public, max-age=30',\n 'x-cache': 'PUBLIC-R2-FILTERED',\n });\n return new Response(method === 'HEAD' ? null : body, { status: 200, headers });\n}\n\n// ---------------------------------------------------------------------------\n// Cache helpers (module-private)\n// ---------------------------------------------------------------------------\n\nconst PASSTHROUGH_HEADERS = ['content-type', 'cache-control', 'etag', 'last-modified', 'vary'] as const;\n\nfunction collectHeaders(src: Response): Record<string, string> {\n const out: Record<string, string> = {};\n for (const h of PASSTHROUGH_HEADERS) {\n const v = src.headers.get(h);\n if (v) out[h] = v;\n }\n return out;\n}\n\nfunction buildCachedResponse(entry: CacheEntry, method: string, xCache: 'HIT' | 'REVALIDATED'): Response {\n const headers = new Headers(entry.headers);\n headers.set('X-Cache', xCache);\n // Surface remaining freshness so downstream HTTP caches / devtools\n // can reason about it (clamped at 0).\n const ageSec = Math.max(0, Math.floor((entry.expiresAt - entry.ttlMs - Date.now()) / -1000));\n headers.set('Age', String(Math.max(0, ageSec)));\n const body = method === 'HEAD' ? null : entry.body;\n return new Response(body, { status: entry.status, headers });\n}\n\nasync function passthroughResponse(resp: Response, method: string, xCache: 'MISS' | 'BYPASS'): Promise<Response> {\n const headers = new Headers(collectHeaders(resp));\n headers.set('X-Cache', xCache);\n if (method === 'HEAD') {\n // Drain to release the connection.\n try { await resp.arrayBuffer(); } catch { /* ignore */ }\n return new Response(null, { status: resp.status, headers });\n }\n const body = await resp.arrayBuffer();\n return new Response(body, { status: resp.status, headers });\n}\n\nasync function consumeAndMaybeCache(\n resp: Response,\n key: string,\n pathname: string,\n method: string,\n cache: LruTtlCache,\n): Promise<Response> {\n const body = await resp.arrayBuffer();\n const headers = collectHeaders(resp);\n // Only cache success responses — pinning a 404 / 5xx would just\n // amplify a transient failure.\n if (resp.status >= 200 && resp.status < 300) {\n const ttlMs = ttlForPath(pathname);\n const entry: CacheEntry = {\n status: resp.status,\n body,\n headers,\n etag: resp.headers.get('etag') ?? undefined,\n lastModified: resp.headers.get('last-modified') ?? undefined,\n expiresAt: Date.now() + ttlMs,\n ttlMs,\n };\n cache.set(key, entry);\n }\n const respHeaders = new Headers(headers);\n respHeaders.set('X-Cache', 'MISS');\n const outBody = method === 'HEAD' ? null : body;\n return new Response(outBody, { status: resp.status, headers: respHeaders });\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * MarketplaceInstallLocalPlugin\n *\n * Installs marketplace packages into THIS runtime's kernel as opposed to a\n * remote cloud environment. Conceptually different from cloud install in\n * three important ways:\n *\n * 1. Single target — the local kernel is the only install target; there\n * is no `sys_environment` picker.\n * 2. Manifests are cached on disk — once installed, the package is\n * runnable offline. Cloud is only needed during the install action\n * itself (to fetch the manifest snapshot).\n * 3. Coexists with user-authored apps — the local runtime usually has\n * its own `objectstack.config.ts` declared apps. Install refuses to\n * overwrite a manifest_id that's already registered to avoid silently\n * replacing user code.\n *\n * Endpoints (mounted by `start()` on the `kernel:ready` hook):\n *\n * POST /api/v1/marketplace/install-local\n * body: { packageId: string, versionId?: string } (default: \"latest\")\n * → fetches manifest from cloud, caches to disk, registers via\n * the kernel's `manifest` service. Returns the installed entry.\n *\n * GET /api/v1/marketplace/install-local\n * → lists currently installed marketplace packages\n *\n * DELETE /api/v1/marketplace/install-local/:manifestId\n * → removes the cached manifest. Kernel must be restarted to fully\n * unload — `engine.registerApp` is additive only. We document\n * this in the response message.\n *\n * Persistence layout:\n * <cwd>/.objectstack/installed-packages/<safe-manifest-id>.json\n * Each file: { packageId, versionId, manifestId, version, manifest, installedAt, installedBy }\n *\n * On `kernel:ready`, the plugin scans the directory and re-registers each\n * cached manifest so installs survive process restarts without further\n * cloud round-trips.\n */\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { readEnvWithDeprecation } from '@objectstack/types';\nimport { resolveCloudUrl } from './cloud-url.js';\nimport { resolveMarketplacePublicBaseUrl } from './marketplace-public-url.js';\nimport { LocalManifestSource, type InstalledManifestEntry } from './local-manifest-source.js';\nimport { ConnectionCredentialStore } from './connection-credential-store.js';\nimport { MARKETPLACE_INSTALLED_UI_BUNDLE } from './marketplace-ui.js';\n\nconst ROUTE_BASE = '/api/v1/marketplace/install-local';\n\nexport interface MarketplaceInstallLocalPluginConfig {\n /** Cloud control-plane base URL. When unset, falls back to OS_CLOUD_URL\n * and then to the public ObjectStack cloud so a fresh `objectstack dev`\n * can install from the marketplace without configuration. Set\n * OS_CLOUD_URL=off to disable (the install endpoint then returns 503). */\n controlPlaneUrl?: string;\n /** Override the on-disk cache directory. Defaults to\n * `<cwd>/.objectstack/installed-packages`. */\n storageDir?: string;\n}\n\n// Desired-state entry shape — owned by the LocalManifestSource ledger\n// (ADR-0007 step ⑤: the ledger is the named local desired-state owner;\n// this plugin is its HTTP mutation surface).\ntype InstalledEntry = InstalledManifestEntry;\n\nexport class MarketplaceInstallLocalPlugin implements Plugin {\n readonly name = 'com.objectstack.runtime.marketplace-install-local';\n readonly version = '1.0.0';\n\n private readonly cloudUrl: string;\n private readonly ledger: LocalManifestSource;\n private readonly storageDir: string;\n private readonly credentials: ConnectionCredentialStore;\n\n constructor(config: MarketplaceInstallLocalPluginConfig = {}) {\n this.cloudUrl = resolveCloudUrl(config.controlPlaneUrl);\n this.ledger = new LocalManifestSource(config.storageDir);\n this.storageDir = this.ledger.dir;\n this.credentials = new ConnectionCredentialStore();\n }\n\n init = async (_ctx: PluginContext): Promise<void> => {\n // No services registered — pure HTTP wiring during start().\n };\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n // Plugin-owned Setup nav (cloud ADR-0009): \"Installed Apps\"\n // ships WITH the local-install capability.\n try {\n const manifest = ctx.getService<{ register(m: any): void }>('manifest');\n manifest?.register?.(MARKETPLACE_INSTALLED_UI_BUNDLE);\n } catch { /* no manifest service */ }\n\n // 1. Rehydrate previously installed packages so they survive restart.\n await this.rehydrate(ctx);\n\n // 2. Mount HTTP endpoints.\n let httpServer: any;\n try {\n httpServer = ctx.getService('http-server');\n } catch {\n ctx.logger?.warn?.('[MarketplaceInstallLocal] http-server not available — install endpoints not mounted');\n return;\n }\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[MarketplaceInstallLocal] http-server missing getRawApp() — install endpoints not mounted');\n return;\n }\n const rawApp = httpServer.getRawApp();\n\n const postHandler = async (c: any) => this.handleInstall(c, ctx);\n const getHandler = async (c: any) => this.handleList(c);\n const deleteHandler = async (c: any) => this.handleUninstall(c, ctx);\n\n const reseedHandler = async (c: any) => this.handleReseed(c, ctx);\n const purgeHandler = async (c: any) => this.handlePurge(c, ctx);\n\n if (typeof rawApp.post === 'function') rawApp.post(ROUTE_BASE, postHandler);\n if (typeof rawApp.get === 'function') rawApp.get(ROUTE_BASE, getHandler);\n if (typeof rawApp.delete === 'function') rawApp.delete(`${ROUTE_BASE}/:manifestId`, deleteHandler);\n if (typeof rawApp.post === 'function') {\n rawApp.post(`${ROUTE_BASE}/:manifestId/reseed-sample-data`, reseedHandler);\n rawApp.post(`${ROUTE_BASE}/:manifestId/purge-sample-data`, purgeHandler);\n }\n\n ctx.logger?.info?.(`[MarketplaceInstallLocal] mounted at ${ROUTE_BASE} (storage: ${this.storageDir})`);\n });\n };\n\n /**\n * Re-register every cached manifest with the kernel's manifest service.\n * Safe to call on a kernel that already has the same manifest_id (the\n * underlying ObjectQL registry overwrites by id, but we still warn so\n * a developer can spot the dev-time clash between their config.ts and\n * a marketplace package).\n */\n private rehydrate = async (ctx: PluginContext): Promise<void> => {\n const entries = this.readAll();\n if (entries.length === 0) return;\n\n let manifestService: { register(m: any): void } | null = null;\n try {\n manifestService = ctx.getService('manifest') as any;\n } catch {\n ctx.logger?.warn?.('[MarketplaceInstallLocal] no `manifest` service — rehydrate skipped');\n return;\n }\n\n for (const entry of entries) {\n try {\n manifestService!.register(entry.manifest);\n // Sync schemas so the driver creates tables for the newly-\n // registered objects (idempotent — already-synced tables\n // are no-ops).\n try {\n const ql: any = ctx.getService('objectql');\n if (ql && typeof ql.syncSchemas === 'function') await ql.syncSchemas();\n } catch { /* non-fatal */ }\n // Replay translations + register seed datasets, but don't\n // re-run seeding — existing rows are already in the DB from\n // the original install, and multi-tenant orgs will replay\n // via the security middleware on next sys_organization insert.\n await this.applySideEffects(ctx, entry.manifest, { seedNow: false });\n ctx.logger?.info?.(`[MarketplaceInstallLocal] rehydrated ${entry.manifestId}@${entry.version}`);\n } catch (err: any) {\n ctx.logger?.error?.(`[MarketplaceInstallLocal] rehydrate failed for ${entry.manifestId}`, err instanceof Error ? err : new Error(String(err)));\n }\n }\n };\n\n private handleInstall = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required to install packages.' } }, 401);\n }\n\n let body: any = {};\n try { body = await c.req.json(); } catch { /* empty body */ }\n\n // ── Offline path: an inline manifest was supplied (file import). ──\n // Bypass the cloud-fetch entirely; no OS_CLOUD_URL required.\n const inlineManifest = body?.manifest && typeof body.manifest === 'object' ? body.manifest : null;\n\n // A COMPILED stack bundle (`dist/objectstack.json`, what publish\n // uploads as the version payload) nests its meta under `.manifest`:\n // { manifest: { id, namespace, version, … }, objects, views, … }\n // while ObjectQL's registerApp expects the FLAT app shape (top-level\n // id + sections). Flatten when detected — otherwise every install of\n // a published compiled bundle dies with \"Invalid manifest payload\".\n const normalizeBundle = (m: any): any => {\n if (m && !m.id && !m.name && m.manifest && typeof m.manifest === 'object' && (m.manifest.id || m.manifest.name)) {\n const { manifest: meta, ...sections } = m;\n return { ...meta, ...sections };\n }\n return m;\n };\n\n let manifest: any;\n let resolvedVersionId: string;\n let version: string;\n let packageId: string;\n\n if (inlineManifest) {\n manifest = normalizeBundle(inlineManifest);\n packageId = String(manifest.id ?? manifest.name ?? '').trim();\n version = String(manifest.version ?? 'unknown');\n resolvedVersionId = String(body?.versionId ?? version);\n if (!packageId) {\n return c.json({ success: false, error: { code: 'invalid_manifest', message: 'Inline manifest must have an \"id\" or \"name\".' } }, 400);\n }\n } else {\n if (!this.cloudUrl) {\n return c.json({ success: false, error: { code: 'marketplace_unavailable', message: 'OS_CLOUD_URL not configured.' } }, 503);\n }\n packageId = String(body?.packageId ?? '').trim();\n const versionId = String(body?.versionId ?? 'latest').trim() || 'latest';\n if (!packageId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'packageId is required.' } }, 400);\n }\n\n // 1. Fetch manifest snapshot — prefer public R2 fast-path so\n // install works even when cloud is asleep or down. Fall back\n // to cloud on miss/error.\n let payload: any;\n const publicBase = resolveMarketplacePublicBaseUrl();\n const fetchAttempts: { label: string; url: string }[] = [];\n if (publicBase) {\n fetchAttempts.push({\n label: 'public-r2',\n url: `${publicBase}/packages/${encodeURIComponent(packageId)}/versions/${encodeURIComponent(versionId)}/manifest.json`,\n });\n }\n fetchAttempts.push({\n label: 'cloud',\n url: `${this.cloudUrl}/api/v1/marketplace/packages/${encodeURIComponent(packageId)}/versions/${encodeURIComponent(versionId)}/manifest`,\n });\n\n // Credential for the CLOUD attempt: the env→cloud service key\n // (cloud-hosted) or the bound oscc_ bearer (self-hosted). With it\n // the catalog also serves the caller's OWN org/private packages —\n // anonymous fetches keep getting public/listed only. The public\n // R2 fast-path stays anonymous (it only ever holds public).\n const cloudCredential = (process.env.OS_CLOUD_API_KEY ?? '').trim()\n || this.credentials.read()?.runtimeToken\n || '';\n\n let lastErrStatus = 0;\n let lastErrText = '';\n for (const attempt of fetchAttempts) {\n try {\n const headers: Record<string, string> = { Accept: 'application/json' };\n if (attempt.label === 'cloud' && cloudCredential) headers.Authorization = `Bearer ${cloudCredential}`;\n const resp = await fetch(attempt.url, { headers });\n if (!resp.ok) {\n lastErrStatus = resp.status;\n lastErrText = (await resp.text().catch(() => '')).slice(0, 200);\n // 404 from public R2 is not fatal — fall through to cloud.\n if (attempt.label === 'public-r2' && resp.status === 404) {\n ctx.logger?.info?.(`[MarketplaceInstallLocal] public-r2 miss for ${packageId}@${versionId}, falling back to cloud`);\n continue;\n }\n if (attempt.label === 'public-r2' && resp.status >= 500) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] public-r2 ${resp.status}, falling back to cloud`);\n continue;\n }\n break; // cloud non-ok → surface error\n }\n payload = await resp.json();\n lastErrStatus = 0;\n break;\n } catch (err: any) {\n if (attempt.label === 'public-r2') {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] public-r2 fetch error: ${err?.message ?? err}, falling back to cloud`);\n continue;\n }\n return c.json({\n success: false,\n error: { code: 'cloud_fetch_failed', message: err?.message ?? String(err) },\n }, 502);\n }\n }\n if (!payload) {\n return c.json({\n success: false,\n error: { code: 'cloud_fetch_failed', message: `Cloud returned ${lastErrStatus}: ${lastErrText}` },\n }, lastErrStatus === 404 ? 404 : 502);\n }\n\n const data = payload?.data ?? payload;\n manifest = normalizeBundle(data?.manifest);\n resolvedVersionId = String(data?.version_id ?? versionId);\n version = String(data?.version ?? 'unknown');\n }\n\n const manifestId = String(manifest?.id ?? manifest?.name ?? '');\n if (!manifest || !manifestId) {\n return c.json({ success: false, error: { code: 'invalid_manifest', message: 'Invalid manifest payload.' } }, inlineManifest ? 400 : 502);\n }\n\n // 2. Conflict check — refuse to overwrite user-authored apps\n const conflict = this.findConflict(ctx, manifestId);\n if (conflict === 'user-code') {\n return c.json({\n success: false,\n error: {\n code: 'manifest_conflict',\n message: `manifest_id \"${manifestId}\" is already defined by this runtime's local code. Refusing to overwrite. Uninstall the local definition first.`,\n },\n }, 409);\n }\n\n // 3. Hot-register FIRST so a malformed inline manifest fails the\n // install loudly rather than persisting a broken record that\n // would also fail on every subsequent rehydrate.\n try {\n const manifestService = ctx.getService('manifest') as any;\n manifestService.register(manifest);\n } catch (err: any) {\n // For offline file imports we treat a register failure as a hard\n // failure (don't persist). Cloud installs historically tolerated\n // this (the on-disk record survives a restart), so keep that path\n // lenient for backwards compatibility.\n if (inlineManifest) {\n return c.json({\n success: false,\n error: { code: 'register_failed', message: `Failed to register imported manifest: ${err?.message ?? err}` },\n }, 422);\n }\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] hot-register failed for ${manifestId} (will load on next restart): ${err?.message ?? err}`);\n }\n\n // 4. Persist on disk\n const entry: InstalledEntry = {\n packageId,\n versionId: resolvedVersionId,\n manifestId,\n version,\n manifest,\n installedAt: new Date().toISOString(),\n installedBy: userId,\n withSampleData: false,\n };\n try {\n this.ledger.write(entry);\n } catch (err: any) {\n return c.json({\n success: false,\n error: { code: 'storage_failed', message: `Failed to persist manifest: ${err?.message ?? err}` },\n }, 500);\n }\n\n // 4b. Sync schemas to physical tables — registerApp only adds the\n // object definitions to the in-memory registry; the driver\n // must be asked to materialize tables/columns before any seed\n // insert (or user write) succeeds.\n try {\n const ql: any = ctx.getService('objectql');\n if (ql && typeof ql.syncSchemas === 'function') {\n await ql.syncSchemas();\n ctx.logger?.info?.(`[MarketplaceInstallLocal] syncSchemas() ran after registering ${manifestId}`);\n }\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] syncSchemas failed for ${manifestId}: ${err?.message ?? err}`);\n }\n\n // 5. Replicate the AppPlugin start-time side-effects that the\n // `manifest` service does NOT do on its own:\n // • load translation bundles into the i18n service\n // • stash seed datasets on the kernel + run them now so the\n // installed app has demo data on first paint.\n const seededSummary = await this.applySideEffects(ctx, manifest, { seedNow: true, c });\n if (seededSummary.seeded.mode === 'inline' && (seededSummary.seeded.inserted ?? 0) + (seededSummary.seeded.updated ?? 0) > 0) {\n entry.withSampleData = true;\n try {\n this.ledger.write(entry);\n } catch { /* non-fatal — entry already on disk */ }\n }\n\n return c.json({\n success: true,\n data: {\n manifestId,\n version,\n versionId: resolvedVersionId,\n installedAt: entry.installedAt,\n hotLoaded: true,\n upgradedFrom: conflict === 'marketplace' ? 'previous-marketplace-version' : null,\n translationsLoaded: seededSummary.translationsLoaded,\n seeded: seededSummary.seeded,\n note: 'App is now available in this runtime. Refresh the console to see it in the app switcher.',\n },\n }, 200);\n };\n\n private handleList = async (c: any): Promise<Response> => {\n const entries = this.readAll();\n return c.json({\n success: true,\n data: {\n items: entries.map(e => ({\n packageId: e.packageId,\n versionId: e.versionId,\n manifestId: e.manifestId,\n version: e.version,\n installedAt: e.installedAt,\n installedBy: e.installedBy,\n withSampleData: e.withSampleData ?? false,\n })),\n total: entries.length,\n storageDir: this.storageDir,\n },\n }, 200);\n };\n\n private handleUninstall = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required.' } }, 401);\n }\n const manifestId = String(c.req.param?.('manifestId') ?? c.req.params?.manifestId ?? '').trim();\n if (!manifestId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'manifestId path param required.' } }, 400);\n }\n if (!this.ledger.has(manifestId)) {\n return c.json({ success: false, error: { code: 'not_found', message: `No marketplace install for ${manifestId}.` } }, 404);\n }\n try {\n this.ledger.remove(manifestId);\n } catch (err: any) {\n return c.json({ success: false, error: { code: 'storage_failed', message: err?.message ?? String(err) } }, 500);\n }\n ctx.logger?.info?.(`[MarketplaceInstallLocal] uninstalled ${manifestId} (cached manifest removed; restart runtime to unload from running kernel)`);\n return c.json({\n success: true,\n data: {\n manifestId,\n note: 'Cached manifest removed. The app remains loaded in the running kernel until the next restart (the kernel API does not support unregistering apps in-place).',\n },\n }, 200);\n };\n\n /**\n * Detect whether `manifestId` is already known to the kernel and classify\n * the source so we can refuse vs upgrade gracefully.\n *\n * 'none' — fresh install\n * 'marketplace' — previously installed by this plugin (allow upgrade)\n * 'user-code' — defined by AppPlugin from objectstack.config.ts\n * (refuse to avoid silently overwriting authored code)\n */\n private findConflict = (ctx: PluginContext, manifestId: string): 'none' | 'marketplace' | 'user-code' => {\n // First check: do we already have a marketplace install entry?\n if (this.ledger.has(manifestId)) {\n return 'marketplace';\n }\n // Then check: is the manifest_id already in the engine's registry?\n try {\n const ql: any = ctx.getService('objectql');\n const packages: any[] = ql?.registry?.getAllPackages?.() ?? [];\n const hit = packages.find((p: any) =>\n (p?.manifest?.id ?? p?.id ?? p?.manifest?.name) === manifestId,\n );\n if (hit) return 'user-code';\n } catch { /* objectql not registered yet — treat as fresh */ }\n return 'none';\n };\n\n /**\n * Pull a userId out of the request's better-auth session, if any.\n * Returns null when there is no signed-in user. v1 does not check\n * admin role — UI gating + the auth requirement is sufficient for\n * dev / single-tenant runtimes. Stricter checks can be layered on\n * via a middleware in cloud-hosted multi-tenant deployments.\n */\n /**\n * POST /api/v1/marketplace/install-local/:manifestId/reseed-sample-data\n *\n * Re-runs SeedLoaderService against the cached manifest's `data` arrays.\n * Idempotent (upsert by id). Useful when:\n * • The user installed an app and skipped sample data\n * • A purge was undone\n * • The user wants a clean baseline back after editing demo rows\n *\n * Multi-tenant: requires an active organization on the session (same\n * rule as install seed path).\n */\n private handleReseed = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required.' } }, 401);\n }\n const manifestId = String(c.req.param?.('manifestId') ?? c.req.params?.manifestId ?? '').trim();\n if (!manifestId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'manifestId path param required.' } }, 400);\n }\n if (!this.ledger.has(manifestId)) {\n return c.json({ success: false, error: { code: 'not_found', message: `No marketplace install for ${manifestId}.` } }, 404);\n }\n const entry: InstalledEntry | null = this.ledger.read(manifestId);\n if (!entry) {\n return c.json({ success: false, error: { code: 'storage_failed', message: 'Failed to read manifest cache.' } }, 500);\n }\n\n const summary = await this.applySideEffects(ctx, entry.manifest, { seedNow: true, c });\n if (summary.seeded.mode === 'skipped') {\n return c.json({\n success: false,\n error: {\n code: 'reseed_skipped',\n message: `Reseed did not run: ${summary.seeded.reason ?? 'unknown reason'}`,\n },\n }, 400);\n }\n\n // Persist flag flip\n try {\n entry.withSampleData = true;\n this.ledger.write(entry);\n } catch { /* non-fatal */ }\n\n return c.json({\n success: true,\n data: {\n manifestId,\n inserted: summary.seeded.inserted ?? 0,\n updated: summary.seeded.updated ?? 0,\n errors: summary.seeded.errors ?? 0,\n withSampleData: true,\n },\n }, 200);\n };\n\n /**\n * POST /api/v1/marketplace/install-local/:manifestId/purge-sample-data\n *\n * Deletes every record whose id is declared in the cached manifest's\n * seed datasets. Uses the `driver` service directly to bypass ACL /\n * lifecycle hooks (same pattern as cloud purge). User-created records\n * are never touched — only ids declared in the package's bundled\n * datasets are removed. Already-deleted rows count as `skipped`.\n */\n private handlePurge = async (c: any, ctx: PluginContext): Promise<Response> => {\n const userId = await this.requireAuthenticatedUser(c, ctx);\n if (!userId) {\n return c.json({ success: false, error: { code: 'unauthorized', message: 'Authentication required.' } }, 401);\n }\n const manifestId = String(c.req.param?.('manifestId') ?? c.req.params?.manifestId ?? '').trim();\n if (!manifestId) {\n return c.json({ success: false, error: { code: 'bad_request', message: 'manifestId path param required.' } }, 400);\n }\n if (!this.ledger.has(manifestId)) {\n return c.json({ success: false, error: { code: 'not_found', message: `No marketplace install for ${manifestId}.` } }, 404);\n }\n const entry: InstalledEntry | null = this.ledger.read(manifestId);\n if (!entry) {\n return c.json({ success: false, error: { code: 'storage_failed', message: 'Failed to read manifest cache.' } }, 500);\n }\n\n const datasets = Array.isArray(entry.manifest?.data)\n ? entry.manifest.data.filter((d: any) => d && d.object && Array.isArray(d.records))\n : [];\n\n if (datasets.length === 0) {\n return c.json({\n success: false,\n error: { code: 'nothing_to_purge', message: 'This package declares no seed datasets.' },\n }, 400);\n }\n\n let driver: any;\n try { driver = ctx.getService('driver'); } catch { /* none */ }\n if (!driver || typeof driver.delete !== 'function') {\n return c.json({\n success: false,\n error: { code: 'driver_missing', message: 'driver service unavailable — cannot purge.' },\n }, 500);\n }\n\n let deleted = 0;\n let skipped = 0;\n let errors = 0;\n for (const ds of datasets) {\n const object = String(ds.object);\n for (const rec of ds.records as any[]) {\n const id = rec?.id;\n if (id === undefined || id === null || id === '') { skipped++; continue; }\n try {\n const r = await driver.delete(object, id);\n if (r === false || r === 0 || r?.deleted === 0) skipped++;\n else deleted++;\n } catch (err: any) {\n // Treat \"not found\" as skipped; anything else as error.\n const msg = String(err?.message ?? err);\n if (/not.?found|no row/i.test(msg)) skipped++;\n else { errors++; ctx.logger?.warn?.(`[MarketplaceInstallLocal] purge ${object}#${id}: ${msg}`); }\n }\n }\n }\n\n // Flip flag so UI reflects the empty baseline\n try {\n entry.withSampleData = false;\n this.ledger.write(entry);\n } catch { /* non-fatal */ }\n\n ctx.logger?.info?.(`[MarketplaceInstallLocal] purged ${manifestId}: deleted=${deleted} skipped=${skipped} errors=${errors}`);\n return c.json({\n success: true,\n data: { manifestId, deleted, skipped, errors, withSampleData: false },\n }, 200);\n };\n\n /**\n * Replicate the start-time side-effects that AppPlugin runs for\n * statically-declared apps but the `manifest` service does NOT:\n *\n * 1. Load `manifest.translations` (array of `Record<locale, data>`)\n * into the i18n service — auto-creating an in-memory fallback if\n * none is registered, matching AppPlugin's behaviour.\n *\n * 2. Merge `manifest.data` (an array of seed datasets) into the\n * kernel's `seed-datasets` service so SecurityPlugin's per-org\n * replay middleware picks them up on every future\n * sys_organization insert.\n *\n * 3. When `seedNow=true`, also run the seed immediately so the user\n * sees demo data without having to create a new org:\n * • single-tenant: run SeedLoaderService inline (mirrors\n * AppPlugin single-tenant branch)\n * • multi-tenant: invoke `seed-replayer` for the caller's\n * active org (resolved from the request session)\n *\n * Errors are logged but never thrown — install succeeds even if\n * post-register side-effects partially fail (the manifest itself is\n * already registered + cached). Returns a small summary for the\n * response envelope.\n */\n private applySideEffects = async (\n ctx: PluginContext,\n manifest: any,\n opts: { seedNow: boolean; c?: any },\n ): Promise<{ translationsLoaded: number; seeded: { mode: 'inline' | 'replayer' | 'skipped'; inserted?: number; updated?: number; errors?: number; reason?: string } }> => {\n const appId = String(manifest?.id ?? 'unknown');\n let translationsLoaded = 0;\n let seedSummary: any = { mode: 'skipped', reason: 'no-datasets' };\n\n // ── 1. i18n bundles ─────────────────────────────────────────────\n try {\n const bundles: Array<Record<string, unknown>> = [];\n if (Array.isArray(manifest?.translations)) bundles.push(...manifest.translations);\n if (Array.isArray(manifest?.i18n)) bundles.push(...manifest.i18n);\n\n if (bundles.length > 0) {\n let i18nService: any;\n try { i18nService = ctx.getService('i18n'); } catch { /* not registered */ }\n if (!i18nService) {\n try {\n const mod = await import('@objectstack/core');\n const createMemoryI18n = (mod as any).createMemoryI18n;\n if (typeof createMemoryI18n === 'function') {\n i18nService = createMemoryI18n();\n (ctx as any).registerService?.('i18n', i18nService);\n ctx.logger?.info?.(`[MarketplaceInstallLocal] auto-registered in-memory i18n fallback for \"${appId}\"`);\n }\n } catch { /* fallback unavailable */ }\n }\n if (i18nService?.loadTranslations) {\n for (const bundle of bundles) {\n for (const [locale, data] of Object.entries(bundle)) {\n if (data && typeof data === 'object') {\n try {\n i18nService.loadTranslations(locale, data as Record<string, unknown>);\n translationsLoaded++;\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] failed to load ${appId} translations for ${locale}: ${err?.message ?? err}`);\n }\n }\n }\n }\n ctx.logger?.info?.(`[MarketplaceInstallLocal] loaded ${translationsLoaded} locale bundle(s) for ${appId}`);\n }\n }\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] i18n side-effect failed for ${appId}: ${err?.message ?? err}`);\n }\n\n // ── 2. Seed datasets — merge into kernel service ─────────────────\n const datasets = Array.isArray(manifest?.data)\n ? manifest.data.filter((d: any) => d && d.object && Array.isArray(d.records))\n : [];\n\n if (datasets.length > 0) {\n try {\n const kernel: any = (ctx as any).kernel;\n let existing: any[] = [];\n try {\n const v = kernel?.getService?.('seed-datasets');\n if (Array.isArray(v)) existing = v;\n } catch { /* unset */ }\n const merged = [...existing, ...datasets];\n if (kernel?.registerService) kernel.registerService('seed-datasets', merged);\n else (ctx as any).registerService?.('seed-datasets', merged);\n ctx.logger?.info?.(`[MarketplaceInstallLocal] merged ${datasets.length} seed dataset(s) into kernel (total: ${merged.length})`);\n } catch (err: any) {\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] failed to merge seed-datasets: ${err?.message ?? err}`);\n }\n }\n\n // ── 3. Optional immediate seed ───────────────────────────────────\n // Always seed inline via SeedLoaderService — don't rely on the\n // `seed-replayer` registered by AppPlugin since (a) it isn't\n // registered when the host runtime has no AppPlugin app with\n // seed data, and (b) its closure may use stale datasets. In\n // multi-tenant mode we pass `organizationId` so the loader\n // writes tenant-scoped rows the same way AppPlugin's\n // single-tenant branch + SecurityPlugin's per-org replay do.\n if (opts.seedNow && datasets.length > 0) {\n const multiTenant = String(readEnvWithDeprecation('OS_MULTI_ORG_ENABLED', 'OS_MULTI_TENANT') ?? 'false').toLowerCase() !== 'false';\n try {\n const ql: any = ctx.getService('objectql');\n let metadata: any;\n try { metadata = ctx.getService('metadata'); } catch { /* none */ }\n if (!ql || !metadata) {\n seedSummary = { mode: 'skipped', reason: 'objectql-or-metadata-missing' };\n } else {\n let organizationId: string | undefined;\n if (multiTenant) {\n const resolved = await this.resolveActiveOrgId(opts.c, ctx);\n if (resolved) organizationId = resolved;\n else {\n seedSummary = { mode: 'skipped', reason: 'multi-tenant-no-active-org' };\n ctx.logger?.warn?.('[MarketplaceInstallLocal] multi-tenant: no active org on request — data not seeded');\n }\n }\n if (!multiTenant || organizationId) {\n const [{ SeedLoaderService }, { SeedLoaderRequestSchema }] = await Promise.all([\n import('@objectstack/runtime'),\n import('@objectstack/spec/data'),\n ]);\n const seedLoader = new (SeedLoaderService as any)(ql, metadata, ctx.logger);\n const request = (SeedLoaderRequestSchema as any).parse({\n // ADR-0036 / seed rename: the field is `seeds` (was `datasets`).\n seeds: datasets,\n config: {\n defaultMode: 'upsert',\n multiPass: true,\n ...(organizationId ? { organizationId } : {}),\n },\n });\n const result = await seedLoader.load(request);\n seedSummary = {\n mode: 'inline',\n inserted: result.summary.totalInserted,\n updated: result.summary.totalUpdated,\n errors: result.errors.length,\n };\n ctx.logger?.info?.(`[MarketplaceInstallLocal] inline seed for ${appId}${organizationId ? ` (org=${organizationId})` : ''}: inserted=${seedSummary.inserted} updated=${seedSummary.updated} errors=${seedSummary.errors}`);\n }\n }\n } catch (err: any) {\n seedSummary = { mode: 'skipped', reason: `seed-error: ${err?.message ?? err}` };\n ctx.logger?.warn?.(`[MarketplaceInstallLocal] seed run failed for ${appId}: ${err?.message ?? err}`);\n }\n }\n\n return { translationsLoaded, seeded: seedSummary };\n };\n\n /**\n * Best-effort active-org resolution. Reads the better-auth session\n * (same path as requireAuthenticatedUser) and returns\n * `session.activeOrganizationId`, falling back to the user's first\n * org membership.\n */\n private resolveActiveOrgId = async (c: any, ctx: PluginContext): Promise<string | null> => {\n if (!c?.req?.raw?.headers) return null;\n try {\n const authService: any = ctx.getService('auth');\n let api: any = authService?.api;\n if (!api && typeof authService?.getApi === 'function') api = await authService.getApi();\n if (!api?.getSession) return null;\n const session = await api.getSession({ headers: c.req.raw.headers });\n const direct = session?.session?.activeOrganizationId ?? session?.activeOrganizationId ?? null;\n if (direct) return String(direct);\n // Fall back to the user's first membership row.\n const userId = session?.user?.id;\n if (!userId) return null;\n try {\n const ql: any = ctx.getService('objectql');\n if (ql?.find) {\n const rows = await ql.find('sys_organization_member', { where: { user_id: userId }, limit: 1, context: { isSystem: true } } as any);\n const row = Array.isArray(rows) ? rows[0] : (rows?.items?.[0] ?? null);\n return row?.organization_id ? String(row.organization_id) : null;\n }\n } catch { /* ignore */ }\n } catch { /* ignore */ }\n return null;\n };\n\n private requireAuthenticatedUser = async (c: any, ctx: PluginContext): Promise<string | null> => {\n try {\n // Mirror `hono-plugin.ts` resolveCtx: pull the better-auth `api`\n // off the auth service and call `getSession({ headers })`. The\n // earlier guess `c.get('auth').session` is wrong — AuthPlugin\n // does not pre-populate the Hono context.\n const authService: any = ctx.getService('auth');\n let api: any = authService?.api;\n if (!api && typeof authService?.getApi === 'function') {\n api = await authService.getApi();\n }\n if (api?.getSession && c?.req?.raw?.headers) {\n const session = await api.getSession({ headers: c.req.raw.headers });\n const userId = session?.user?.id ?? null;\n if (userId) return String(userId);\n }\n } catch { /* ignore — fall through */ }\n // Header fallback for cases where auth is disabled (e.g. test stubs)\n const xUserId = c?.req?.header?.('x-user-id');\n if (xUserId) return String(xUserId);\n return null;\n };\n\n private readAll = (): InstalledEntry[] => this.ledger.list();\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * LocalManifestSource — the local desired-state ledger for package installs\n * (cloud ADR-0007 step ⑤).\n *\n * A self-hosted / single-environment runtime OWNS its desired state: the\n * answer to \"which packages should this runtime load\" lives on the runtime's\n * own disk, one JSON file per installed manifest under\n * `<cwd>/.objectstack/installed-packages/`. This class is that ledger,\n * promoted to a first-class named seam.\n *\n * It is the LOCAL isomorph of what a cloud control plane does for managed\n * environments (`sys_package_installation` desired rows → compiled\n * artifact): same role — desired-state owner — different authority:\n *\n * | Deployment | Desired-state owner | Runtime truth |\n * |-------------------|--------------------------------------|----------------------|\n * | Cloud-managed env | control plane (sys_package_installation → artifact) | env-local artifact cache |\n * | Self-hosted env | THIS ledger (LocalManifestSource) | the same ledger (rehydrated at boot) |\n *\n * Nothing here talks to a network: reads and writes are synchronous local\n * file operations, so a runtime boots and serves its installed packages\n * with zero cloud dependency (\"云崩环境不崩\").\n *\n * Consumed by {@link MarketplaceInstallLocalPlugin} (the HTTP surface that\n * mutates the ledger) — exported so hosts and future reconcilers can read\n * the same ledger without going through HTTP.\n */\n\nimport { existsSync, mkdirSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { join, resolve } from 'node:path';\n\n/** One installed-package entry — desired state + provenance. */\nexport interface InstalledManifestEntry {\n packageId: string;\n versionId: string;\n manifestId: string;\n version: string;\n manifest: any;\n installedAt: string;\n installedBy: string | null;\n /** Whether the bundled seed datasets have been loaded into the kernel\n * database. True after install (seedNow=true) or an explicit reseed;\n * false after a purge. Persisted so the UI can show \"Add\" vs \"Re-seed\". */\n withSampleData?: boolean;\n}\n\n/** Default ledger location, relative to the runtime's working directory. */\nexport const DEFAULT_INSTALLED_PACKAGES_DIR = '.objectstack/installed-packages';\n\nfunction safeFilename(manifestId: string): string {\n return manifestId.replace(/[^a-zA-Z0-9._-]/g, '_') + '.json';\n}\n\nexport class LocalManifestSource {\n /** Resolved ledger directory. */\n readonly dir: string;\n\n constructor(storageDir?: string) {\n this.dir = storageDir\n ? resolve(storageDir)\n : resolve(process.cwd(), DEFAULT_INSTALLED_PACKAGES_DIR);\n }\n\n /** Every valid entry in the ledger (corrupt files are skipped). */\n list(): InstalledManifestEntry[] {\n if (!existsSync(this.dir)) return [];\n const out: InstalledManifestEntry[] = [];\n for (const name of readdirSync(this.dir)) {\n if (!name.endsWith('.json')) continue;\n try {\n const raw = readFileSync(join(this.dir, name), 'utf8');\n out.push(JSON.parse(raw));\n } catch { /* skip corrupt files */ }\n }\n return out;\n }\n\n /** Read one entry; null when absent or unreadable. */\n read(manifestId: string): InstalledManifestEntry | null {\n const file = this.fileFor(manifestId);\n if (!existsSync(file)) return null;\n try {\n return JSON.parse(readFileSync(file, 'utf8'));\n } catch {\n return null;\n }\n }\n\n /** Whether the ledger holds an entry for this manifest id. */\n has(manifestId: string): boolean {\n return existsSync(this.fileFor(manifestId));\n }\n\n /** Create or replace an entry (upsert by manifestId). */\n write(entry: InstalledManifestEntry): void {\n mkdirSync(this.dir, { recursive: true });\n writeFileSync(this.fileFor(entry.manifestId), JSON.stringify(entry, null, 2), 'utf8');\n }\n\n /** Remove an entry. Returns false when it was not present. */\n remove(manifestId: string): boolean {\n const file = this.fileFor(manifestId);\n if (!existsSync(file)) return false;\n unlinkSync(file);\n return true;\n }\n\n private fileFor(manifestId: string): string {\n return join(this.dir, safeFilename(manifestId));\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * ConnectionCredentialStore — where a SELF-HOSTED runtime keeps the\n * credential it received at bind time (cloud ADR-0008 consumption side).\n *\n * Cloud-hosted runtimes authenticate to the control plane with an\n * env→cloud service key (`OS_CLOUD_API_KEY`, injected by the cloud).\n * Self-hosted runtimes have no such key: their identity ceremony is the\n * RFC 8628 device-code bind, whose response carries a one-time\n * `runtime_token` (`oscc_…`). This store persists that bearer — plus the\n * environment id the binding established — under the runtime's own\n * working directory, next to the LocalManifestSource ledger:\n *\n * <cwd>/.objectstack/cloud-connection.json\n *\n * Like everything on the runtime's serving path, reads are local file\n * operations: presenting the credential is how the runtime reaches the\n * control plane for org-scoped catalog/install calls, but nothing at\n * boot or serve time DEPENDS on those calls succeeding.\n *\n * Treat the file as a secret (it is written 0600).\n */\n\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\n\n/** Persisted binding credential + context. */\nexport interface StoredConnectionCredential {\n /** The `oscc_…` runtime bearer returned ONCE by the bind route. */\n runtimeToken: string;\n /**\n * Cloud-minted durable runtime identity (ADR runtime-identity-binding).\n * Presented as a claim on re-bind so the registration survives token\n * rotation. Absent on stores written before v2.\n */\n runtimeId?: string;\n /**\n * Control-plane environment id — set only when the binding targeted a\n * cloud-hosted environment. Self-hosted v2 registrations have none.\n */\n environmentId?: string;\n /** Control-plane base URL the binding was made against. */\n controlPlaneUrl?: string;\n organizationId?: string;\n accountEmail?: string;\n boundAt?: string;\n}\n\n/** Default store location, relative to the runtime's working directory. */\nexport const DEFAULT_CONNECTION_CREDENTIAL_PATH = '.objectstack/cloud-connection.json';\n\nexport class ConnectionCredentialStore {\n /** Resolved file path. */\n readonly path: string;\n\n constructor(path?: string) {\n this.path = path\n ? resolve(path)\n : resolve(process.cwd(), DEFAULT_CONNECTION_CREDENTIAL_PATH);\n }\n\n /**\n * Read the stored credential; null when absent or unreadable.\n *\n * An IDENTITY RESIDUAL — `runtimeToken: ''` with a `runtimeId` — is a\n * valid record: unbind leaves one behind so a later re-bind to the same\n * org claims the same registration (ADR runtime-identity-binding §2.1).\n * Callers already treat the empty token as \"no credential\".\n */\n read(): StoredConnectionCredential | null {\n if (!existsSync(this.path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(this.path, 'utf8'));\n if (!parsed || typeof parsed.runtimeToken !== 'string') return null;\n if (!parsed.runtimeToken && !(typeof parsed.runtimeId === 'string' && parsed.runtimeId)) return null;\n return parsed as StoredConnectionCredential;\n } catch {\n return null;\n }\n }\n\n /** Persist (replace) the credential. Written 0600 — it is a secret. */\n write(credential: StoredConnectionCredential): void {\n mkdirSync(dirname(this.path), { recursive: true });\n writeFileSync(this.path, JSON.stringify(credential, null, 2), { encoding: 'utf8', mode: 0o600 });\n }\n\n /** Remove the credential (unbind). Returns false when nothing was stored. */\n clear(): boolean {\n if (!existsSync(this.path)) return false;\n unlinkSync(this.path);\n return true;\n }\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * CloudConnectionPlugin — the runtime-side client surface for a cloud\n * control plane (ADR-0008 Phase 1).\n *\n * Mounts the same-origin `/api/v1/cloud-connection/*` routes the Console\n * marketplace depends on:\n *\n * GET /api/v1/cloud-connection/status — is this env bound to a cloud account?\n * POST /api/v1/cloud-connection/bind/start — begin an RFC 8628 device-code bind\n * POST /api/v1/cloud-connection/bind/poll — poll device token + persist the binding\n * POST /api/v1/cloud-connection/install — install a package via the control plane\n * GET /api/v1/cloud-connection/installation — single-package installed-state probe\n * GET /api/v1/cloud-connection/installed — env's full installed list (Installed view)\n * GET /api/v1/cloud-connection/org-packages — owning org's own catalog (\"Your organization\")\n *\n * History: these routes started as app-level wiring in\n * `apps/objectos/cloud-runtime-plugins.ts` (two ad-hoc plugins). ADR-0008\n * Phase 1 consolidates them here as ONE plugin so both deployment shapes —\n * `apps/objectos` (multi-tenant) and `apps/objectos-ee` (single-environment)\n * — wire the same canonical implementation. ADR-0008 Phase 2 moves this\n * surface into the open `@objectstack/cloud-connection` package; keep this\n * file dependency-light (structural Plugin types, no @objectstack/core) so\n * the move is mechanical.\n *\n * ## Environment & session resolution — two modes\n *\n * Multi-tenant (default): the request hostname is resolved to an environment\n * via the host kernel's `env-registry` service, and the caller's session is\n * validated against that environment's OWN per-env kernel (via\n * `kernel-manager`) — auth is per-environment (ADR-0006).\n *\n * Single-environment (`singleEnvironment: true`, e.g. objectos-ee): there is\n * no registry/manager; the environment id comes from config\n * (`environmentId` / `OS_ENVIRONMENT_ID`, typically assigned when the\n * runtime is bound to a control plane) and sessions are validated against\n * the host kernel's own `auth` service. Routes degrade gracefully when the\n * id is not (yet) configured: status reports `bound:false`; the others 404.\n *\n * ## Why a same-origin proxy at all\n *\n * The SPA cannot call the control plane from a tenant subdomain — that is a\n * cross-origin, cross-site-cookie request the browser blocks. So the runtime\n * answers on its own origin, authorizes against the environment's session,\n * and talks to the control plane server-to-server (env→cloud service\n * credential today; the device-code-bound `sys_cloud_connection` token for\n * self-hosted runtimes).\n */\n\n// Minimal structural plugin contract — keep this module independent of\n// @objectstack/core so the ADR-0008 Phase 2 move to the open package stays\n// mechanical (mirrors the other plugins in this package).\ninterface PluginContext {\n hook(event: string, handler: (...args: any[]) => any): void;\n getService<T = any>(name: string): T;\n logger?: {\n info?: (msg: string) => void;\n warn?: (msg: string) => void;\n error?: (msg: string, err?: unknown) => void;\n };\n}\ninterface Plugin {\n readonly name: string;\n readonly version: string;\n init(ctx: PluginContext): Promise<void>;\n start(ctx: PluginContext): Promise<void>;\n}\n\nimport { hostname } from 'node:os';\nimport { ConnectionCredentialStore } from './connection-credential-store.js';\nimport { CLOUD_CONNECTION_UI_BUNDLE } from './cloud-connection-ui.js';\n\nconst CLOUD_CONNECTION_PREFIX = '/api/v1/cloud-connection';\n\nexport interface CloudConnectionPluginConfig {\n /** Control-plane base URL. Default: `OS_CLOUD_URL` (read lazily at kernel:ready). */\n controlPlaneUrl?: string;\n /** env→cloud service credential. Default: `OS_CLOUD_API_KEY`. */\n controlPlaneApiKey?: string;\n /** OAuth device-flow client id. Default: `OS_CLI_CLIENT_ID` → `objectstack-cli`. */\n deviceClientId?: string;\n /**\n * Fixed environment id (single-environment runtimes). Default:\n * `OS_ENVIRONMENT_ID`. In multi-tenant mode leave unset — the id is\n * resolved per-request from the hostname via `env-registry`.\n */\n environmentId?: string;\n /**\n * Single-environment mode (objectos-ee shipped shape): skip the\n * env-registry/kernel-manager lookups and validate sessions against the\n * host kernel's own `auth` service.\n */\n singleEnvironment?: boolean;\n /**\n * Override the on-disk credential store location. Defaults to\n * `<cwd>/.objectstack/cloud-connection.json` — where the bind flow\n * persists the `oscc_…` runtime bearer for self-hosted runtimes.\n */\n credentialPath?: string;\n}\n\nexport class CloudConnectionPlugin implements Plugin {\n readonly name = 'com.objectstack.cloud.connection';\n readonly version = '0.3.0';\n\n private readonly cfg: CloudConnectionPluginConfig;\n private readonly store: ConnectionCredentialStore;\n\n constructor(config: CloudConnectionPluginConfig = {}) {\n this.cfg = config;\n this.store = new ConnectionCredentialStore(config.credentialPath);\n }\n\n init = async (_ctx: PluginContext): Promise<void> => { /* HTTP wiring on kernel:ready */ };\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n const httpServer: any = (() => { try { return ctx.getService('http-server'); } catch { return undefined; } })();\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[CloudConnectionPlugin] http-server unavailable — routes not mounted');\n return;\n }\n const rawApp = httpServer.getRawApp();\n // Env vars are read here (not at construction) so a host can set\n // them between config load and kernel boot — preserves the\n // behavior of the original app-level wiring.\n const cloudUrl = (this.cfg.controlPlaneUrl ?? process.env.OS_CLOUD_URL ?? '').trim().replace(/\\/+$/, '');\n const cloudApiKey = (this.cfg.controlPlaneApiKey ?? process.env.OS_CLOUD_API_KEY ?? '').trim();\n const deviceClientId = (this.cfg.deviceClientId ?? process.env.OS_CLI_CLIENT_ID ?? 'objectstack-cli').trim();\n const deviceScope = 'openid profile email';\n\n // Effective control-plane credential, resolved PER REQUEST:\n // cloud-hosted runtimes carry the env→cloud service key; a\n // self-hosted runtime presents the `oscc_…` bearer the bind flow\n // persisted. Lazy so a bind that completes while the runtime is\n // up takes effect without a restart.\n const credential = (): string => cloudApiKey || this.store.read()?.runtimeToken || '';\n const authHeaders = (): Record<string, string> => {\n const cred = credential();\n return cred ? { Authorization: `Bearer ${cred}` } : {};\n };\n\n const hostOf = (c: any): string => {\n try { return new URL(c.req.url).hostname; } catch { return ''; }\n };\n\n const resolveEnvironmentId = async (c: any): Promise<string | undefined> => {\n const fixed = (this.cfg.environmentId ?? process.env.OS_ENVIRONMENT_ID ?? '').trim();\n // The CLI's local-dev defaults ('env_local' / 'proj_local')\n // identify the LOCAL kernel, not a cloud environment — never\n // present them to the control plane as one (they would 404\n // the bind and resurrect the phantom-environment confusion\n // ADR runtime-identity-binding removes).\n if (fixed && fixed !== 'env_local' && fixed !== 'proj_local') return fixed;\n if (this.cfg.singleEnvironment) {\n // A completed bind persisted the environment id — a\n // self-hosted runtime needs no OS_ENVIRONMENT_ID after it.\n return this.store.read()?.environmentId || undefined;\n }\n try {\n const envRegistry = ctx.getService<any>('env-registry');\n const env = await envRegistry?.resolveByHostname?.(hostOf(c));\n return env?.environmentId;\n } catch {\n return undefined;\n }\n };\n\n // SDUI surface: the binding page + Setup-nav entry ship with the\n // plugin as metadata (ADR-0029 K2); the console only provides the\n // registered `cloud-connection:panel` widget. Best-effort — a\n // kernel without a manifest service simply has no Setup entry.\n try {\n const manifest = ctx.getService<{ register(m: any): void }>('manifest');\n manifest?.register?.(CLOUD_CONNECTION_UI_BUNDLE);\n } catch { /* no manifest service — headless kernel */ }\n\n const sessionFromAuthService = async (authSvc: any, rawReq: Request): Promise<{ userId?: string } | null> => {\n const api = typeof authSvc?.getApi === 'function' ? await authSvc.getApi() : authSvc?.api ?? authSvc;\n const session = await api?.getSession?.({ headers: rawReq.headers });\n const userId = session?.user?.id ? String(session.user.id) : undefined;\n return userId ? { userId } : null;\n };\n\n const resolveSession = async (environmentId: string, rawReq: Request): Promise<{ userId?: string } | null> => {\n try {\n if (this.cfg.singleEnvironment) {\n // Single-env: the host kernel owns auth.\n let authSvc: any;\n try { authSvc = ctx.getService('auth'); } catch { /* ignore */ }\n if (!authSvc) return null;\n return await sessionFromAuthService(authSvc, rawReq);\n }\n // Multi-tenant: auth lives on the environment's own kernel.\n const kernelManager = ctx.getService<any>('kernel-manager');\n const kernel = await kernelManager?.getOrCreate?.(environmentId);\n let authSvc: any;\n try { authSvc = await kernel?.getServiceAsync?.('auth'); } catch { /* ignore */ }\n if (!authSvc) { try { authSvc = kernel?.getService?.('auth'); } catch { /* ignore */ } }\n if (!authSvc) return null;\n return await sessionFromAuthService(authSvc, rawReq);\n } catch {\n return null;\n }\n };\n\n // GET /status — is this runtime bound to a cloud account?\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/status`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n const stored = this.store.read();\n const runtimeId = stored?.runtimeId;\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n // A single-env runtime with no env id and no credential is\n // simply not bound yet — valid state, not an error.\n if (!environmentId && !credential()) {\n return c.json({ success: true, data: { environmentId: null, runtimeId: runtimeId ?? null, bound: false, provider: 'objectstack-cloud', connection: null } });\n }\n // Prefer the real sys_cloud_connection from the control plane.\n // The oscc_ bearer self-identifies; service-key callers query\n // by environment_id (cloud-hosted) or runtime_id (claim).\n if (cloudUrl) {\n try {\n const qs = environmentId\n ? `?environment_id=${encodeURIComponent(environmentId)}`\n : runtimeId ? `?runtime_id=${encodeURIComponent(runtimeId)}` : '';\n const resp = await fetch(`${cloudUrl}/api/v1/cloud-connection/status${qs}`, {\n headers: authHeaders(),\n });\n if (resp.ok) {\n const json: any = await resp.json().catch(() => null);\n const data = json?.data ?? {};\n const bound = Boolean(data.bound) || Boolean(credential());\n return c.json({ success: true, data: {\n environmentId: environmentId ?? null,\n runtimeId: data.runtime_id ?? runtimeId ?? null,\n bound,\n provider: 'objectstack-cloud',\n connection: data.connection ?? null,\n } });\n }\n } catch { /* fall through to implicit */ }\n }\n const bound = Boolean(credential());\n return c.json({ success: true, data: { environmentId: environmentId ?? null, runtimeId: runtimeId ?? null, bound, provider: 'objectstack-cloud', connection: null } });\n });\n\n // POST /bind/start — begin a device-code bind. The runtime is the\n // genuine RFC 8628 client: it asks the cloud for a device + user\n // code, returns them to the Setup UI, and the operator approves in\n // the cloud console.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/bind/start`, async (c: any) => {\n let body: any = {};\n try { body = await c.req.json(); } catch { body = {}; }\n // Self-hosted (single-env) runtimes need NO environment id —\n // registration happens cloud-side at approval (ADR\n // runtime-identity-binding). An explicit environment_id in the\n // body is still honored for cloud-hosted-style binds.\n let environmentId = await resolveEnvironmentId(c);\n if (!environmentId && this.cfg.singleEnvironment) {\n environmentId = String(body?.environment_id ?? body?.environmentId ?? '').trim() || undefined;\n }\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment to connect a cloud account.' } }, 401);\n if (!cloudUrl) return c.json({ success: false, error: { code: 'cloud_unconfigured', message: 'No cloud control plane configured.' } }, 503);\n try {\n const resp = await fetch(`${cloudUrl}/api/v1/auth/device/code`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ client_id: deviceClientId, scope: deviceScope }),\n });\n const json: any = await resp.json().catch(() => ({}));\n if (!resp.ok) return c.json({ success: false, error: { code: 'device_code_failed', message: json?.error ?? `device/code ${resp.status}` } }, 502);\n // Device context for the approval page (ADR\n // runtime-identity-binding §2.3): name the requesting\n // runtime in the verification URL so the approver sees\n // WHAT they are authorizing. Display-only — informed\n // consent, not an authenticity proof (the page carries\n // the \"only approve if you started this\" warning).\n const withContext = (uri: unknown): string | undefined => {\n if (typeof uri !== 'string' || !uri) return undefined;\n try {\n const u = new URL(uri);\n try { u.searchParams.set('runtime_name', hostname()); } catch { /* no hostname */ }\n const ver = (process.env.OS_RUNTIME_VERSION ?? this.version) || '';\n if (ver) u.searchParams.set('runtime_version', ver);\n return u.toString();\n } catch { return uri; }\n };\n return c.json({ success: true, data: {\n device_code: json.device_code,\n user_code: json.user_code,\n verification_uri: withContext(json.verification_uri),\n verification_uri_complete: withContext(json.verification_uri_complete),\n interval: json.interval ?? 5,\n expires_in: json.expires_in ?? 600,\n } });\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] bind/start failed', err instanceof Error ? err : new Error(String(err)));\n return c.json({ success: false, error: { code: 'device_code_failed', message: String(err?.message ?? err) } }, 502);\n }\n });\n\n // POST /bind/poll { device_code } — polls the cloud token endpoint.\n // While pending, returns { pending: true }. On success, exchanges\n // the operator token for a persisted sys_cloud_connection via the\n // control plane's /bind.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/bind/poll`, async (c: any) => {\n let body: any = {};\n try { body = await c.req.json(); } catch { body = {}; }\n let environmentId = await resolveEnvironmentId(c);\n if (!environmentId && this.cfg.singleEnvironment) {\n environmentId = String(body?.environment_id ?? body?.environmentId ?? '').trim() || undefined;\n }\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) return c.json({ success: false, error: { code: 'unauthenticated' } }, 401);\n if (!cloudUrl) return c.json({ success: false, error: { code: 'cloud_unconfigured' } }, 503);\n\n const deviceCode = String(body?.device_code ?? body?.deviceCode ?? '').trim();\n if (!deviceCode) return c.json({ success: false, error: { code: 'invalid_request', message: 'device_code is required' } }, 400);\n\n try {\n const tokResp = await fetch(`${cloudUrl}/api/v1/auth/device/token`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ grant_type: 'urn:ietf:params:oauth:grant-type:device_code', device_code: deviceCode, client_id: deviceClientId }),\n });\n const tok: any = await tokResp.json().catch(() => ({}));\n const accessToken = tok?.access_token;\n if (!accessToken) {\n // RFC 8628 polling errors: authorization_pending / slow_down\n // are non-terminal; everything else is terminal.\n const errCode = String(tok?.error ?? `device/token ${tokResp.status}`);\n const pending = errCode === 'authorization_pending' || errCode === 'slow_down';\n return c.json({ success: pending, data: { pending }, error: pending ? undefined : { code: errCode } }, pending ? 200 : 400);\n }\n // Persist the binding through the control plane. The\n // registration claim rides along (ADR\n // runtime-identity-binding §2.3): hostname + version name\n // the device; a stored runtime_id keeps the identity\n // stable across re-binds (claim verified cloud-side).\n const stored = this.store.read();\n const bindResp = await fetch(`${cloudUrl}/api/v1/cloud-connection/bind`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...(cloudApiKey ? { Authorization: `Bearer ${cloudApiKey}` } : {}) },\n body: JSON.stringify({\n ...(environmentId ? { environment_id: environmentId } : {}),\n ...(stored?.runtimeId ? { runtime_id: stored.runtimeId } : {}),\n name: (() => { try { return hostname(); } catch { return undefined; } })(),\n runtime_version: (process.env.OS_RUNTIME_VERSION ?? this.version) || undefined,\n token: accessToken,\n scope: deviceScope,\n }),\n });\n const bindJson: any = await bindResp.json().catch(() => ({ success: false, error: 'bind failed (no body)' }));\n // The bind response carries the one-time runtime bearer.\n // Persist it HERE (server-side, 0600 file) and STRIP it\n // from what goes back to the browser — the SPA never\n // holds the credential.\n const runtimeToken = bindJson?.data?.runtime_token;\n if (bindResp.ok && typeof runtimeToken === 'string' && runtimeToken) {\n try {\n this.store.write({\n runtimeToken,\n runtimeId: bindJson?.data?.runtime_id ?? bindJson?.data?.connection?.runtime_id ?? undefined,\n environmentId: environmentId || undefined,\n controlPlaneUrl: cloudUrl,\n organizationId: bindJson?.data?.connection?.organization_id ?? undefined,\n accountEmail: bindJson?.data?.connection?.account_email ?? undefined,\n boundAt: bindJson?.data?.connection?.bound_at ?? new Date().toISOString(),\n });\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] failed to persist runtime credential', err instanceof Error ? err : new Error(String(err)));\n }\n delete bindJson.data.runtime_token;\n }\n return c.json(bindJson, bindResp.status as any);\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] bind/poll failed', err instanceof Error ? err : new Error(String(err)));\n return c.json({ success: false, error: { code: 'bind_failed', message: String(err?.message ?? err) } }, 502);\n }\n });\n\n // POST /unbind — disconnect this runtime from the control plane.\n // Revokes the connection server-side (best-effort) and clears the\n // local credential. Requires an environment session, mirroring\n // bind/start.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/unbind`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) return c.json({ success: false, error: { code: 'unauthenticated' } }, 401);\n\n // Revoke cloud-side FIRST (the oscc_ bearer self-identifies;\n // env-keyed bindings name the environment), then clear the\n // local credential regardless — a device signing out must not\n // leave a live token behind when the control plane is up.\n let revoked = false;\n if (cloudUrl && credential()) {\n try {\n const resp = await fetch(`${cloudUrl}/api/v1/cloud-connection/revoke`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', ...authHeaders() },\n body: JSON.stringify(environmentId ? { environment_id: environmentId } : {}),\n });\n revoked = resp.ok;\n } catch { /* control plane unreachable — local clear still proceeds */ }\n }\n // Clear the CREDENTIAL but keep the IDENTITY: a residual\n // {runtimeId} lets a later re-bind to the same org claim the\n // same registration (revive the revoked row) instead of\n // piling up a new device per disconnect cycle — same as an\n // iCloud device record surviving sign-out.\n const residualId = this.store.read()?.runtimeId;\n const cleared = (() => {\n try {\n if (residualId) {\n this.store.write({ runtimeToken: '', runtimeId: residualId });\n return true;\n }\n return this.store.clear();\n } catch { return false; }\n })();\n return c.json({ success: true, data: { environmentId: environmentId ?? null, revoked, cleared } });\n });\n\n // POST /install { package_id, seed_sample_data? } — in-environment\n // marketplace install. Authorizes the caller against the\n // environment's own session (SSO-as-owner only ever admits org\n // owners/admins), then performs the install against the cloud\n // control plane using the env→cloud service credential.\n rawApp.post(`${CLOUD_CONNECTION_PREFIX}/install`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId) return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n\n // Local authz: require a valid env session. (TODO: tighten to an\n // explicit env-admin role check; today only owners/admins obtain\n // a session via SSO-as-owner.)\n const session = await resolveSession(environmentId, c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment to install apps.' } }, 401);\n }\n\n if (!cloudUrl || !credential()) {\n return c.json({ success: false, error: { code: 'cloud_unconfigured', message: 'This runtime is not connected to a cloud account; install is unavailable.' } }, 503);\n }\n\n let body: any = {};\n try { body = await c.req.json(); } catch { body = {}; }\n const packageId = String(body?.package_id ?? body?.packageId ?? '').trim();\n if (!packageId) return c.json({ success: false, error: { code: 'invalid_request', message: 'package_id is required' } }, 400);\n const seedSampleData = body?.seed_sample_data === true || body?.seedSampleData === true;\n\n // Call the cloud install endpoint in service mode. We do NOT send\n // an active org → package-install treats this as platform/CI and\n // installs unrestricted (we already authorized the env admin above).\n try {\n const resp = await fetch(`${cloudUrl}/api/v1/actions/sys_package/install_package`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...authHeaders(),\n },\n body: JSON.stringify({ recordId: packageId, params: { environment_id: environmentId, seed_sample_data: seedSampleData } }),\n });\n const json = await resp.json().catch(() => ({ success: false, error: 'install failed (no body)' }));\n return c.json(json, resp.status as any);\n } catch (err: any) {\n ctx.logger?.error?.('[CloudConnectionPlugin] install failed', err instanceof Error ? err : new Error(String(err)));\n return c.json({ success: false, error: { code: 'install_failed', message: String(err?.message ?? err) } }, 502);\n }\n });\n\n // GET /installation?package_id=… — same-origin installed-state\n // probe. Always returns 200 with `{ installed: boolean, … }`;\n // failures to reach the control plane degrade to\n // `{ installed: false }` so the marketplace page renders (worst\n // case it offers an install the control plane upserts idempotently).\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/installation`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId) {\n // Self-hosted v2: cloud-side installation records are\n // env-scoped; a registration-only runtime tracks installs\n // locally (LocalManifestSource). Report not-installed.\n if (this.cfg.singleEnvironment) return c.json({ success: true, data: { installed: false } });\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n\n const session = await resolveSession(environmentId, c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment.' } }, 401);\n }\n\n let packageId = '';\n try {\n const u = new URL(c.req.url);\n packageId = String(u.searchParams.get('package_id') ?? u.searchParams.get('packageId') ?? '').trim();\n } catch { /* malformed URL → empty */ }\n if (!packageId) return c.json({ success: false, error: { code: 'invalid_request', message: 'package_id is required' } }, 400);\n\n // Not connected → can't know; report not-installed so the page\n // still renders (a read should never hard-fail the page).\n if (!cloudUrl || !credential()) return c.json({ success: true, data: { installed: false } });\n\n try {\n // Read installed-state from the control plane's\n // service-authenticated installations route — NOT the generic\n // `/api/v1/data/sys_package_installation` API. That data API\n // resolves identity via better-auth sessions / `sys_api_key`\n // only and rejects the `OS_CLOUD_API_KEY` service bearer (401).\n // This route shares the install route's service-key auth, so\n // the same credential that performed the install can read its\n // result back.\n const resp = await fetch(\n `${cloudUrl}/api/v1/cloud/environments/${encodeURIComponent(environmentId)}/installations/${encodeURIComponent(packageId)}`,\n { headers: { Accept: 'application/json', ...authHeaders() } },\n );\n if (!resp.ok) return c.json({ success: true, data: { installed: false } });\n const json: any = await resp.json().catch(() => ({}));\n const data: any = json?.data ?? json ?? {};\n if (!data.installed) return c.json({ success: true, data: { installed: false } });\n return c.json({ success: true, data: {\n installed: true,\n installationId: String(data.installationId ?? ''),\n version: String(data.version ?? 'installed'),\n withSampleData: data.withSampleData === true,\n } });\n } catch (err: any) {\n ctx.logger?.warn?.(`[CloudConnectionPlugin] installation probe failed: ${String(err?.message ?? err)}`);\n return c.json({ success: true, data: { installed: false } });\n }\n });\n\n // GET /installed — env's FULL installed set from the control\n // plane's `sys_package_installation`, so the Console \"Installed\"\n // view reflects packages installed via ANY path (CLI, marketplace,\n // REST) — ADR-0007 step ①. Degrades to an empty list when the\n // runtime is not cloud-connected or the control plane is\n // unreachable (never hard-fails the page).\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/installed`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId) {\n // Self-hosted v2: no env-scoped cloud install ledger —\n // the Installed view is fed by the local manifest ledger.\n if (this.cfg.singleEnvironment) {\n return c.json({ success: true, data: { packages: [], total: 0, connected: Boolean(credential()) } });\n }\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n\n const session = await resolveSession(environmentId, c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment.' } }, 401);\n }\n\n if (!cloudUrl || !credential()) {\n return c.json({ success: true, data: { packages: [], total: 0, connected: false } });\n }\n\n try {\n const resp = await fetch(\n `${cloudUrl}/api/v1/cloud/environments/${encodeURIComponent(environmentId)}/packages`,\n { headers: { Accept: 'application/json', ...authHeaders() } },\n );\n if (!resp.ok) return c.json({ success: true, data: { packages: [], total: 0, connected: true } });\n const json: any = await resp.json().catch(() => ({}));\n const data: any = json?.data ?? json ?? {};\n const packages = Array.isArray(data.packages) ? data.packages : [];\n return c.json({ success: true, data: { packages, total: packages.length, connected: true } });\n } catch (err: any) {\n ctx.logger?.warn?.(`[CloudConnectionPlugin] installed-list failed: ${String(err?.message ?? err)}`);\n return c.json({ success: true, data: { packages: [], total: 0, connected: true } });\n }\n });\n\n // GET /org-packages — org-scoped catalog for the in-env\n // Marketplace's \"Your organization\" layer (ADR-0007 step ②): the\n // env's owning org's own packages (visibility org/private), so a\n // publisher can discover + install their private apps from inside\n // the environment. Forwards (service-key) to the control plane,\n // which derives the org from environment_id.\n rawApp.get(`${CLOUD_CONNECTION_PREFIX}/org-packages`, async (c: any) => {\n const environmentId = await resolveEnvironmentId(c);\n if (!environmentId && !this.cfg.singleEnvironment) {\n return c.json({ success: false, error: { code: 'environment_not_found' } }, 404);\n }\n\n const session = await resolveSession(environmentId ?? '', c.req.raw);\n if (!session?.userId) {\n return c.json({ success: false, error: { code: 'unauthenticated', message: 'Sign in to this environment.' } }, 401);\n }\n\n if (!cloudUrl || !credential()) {\n return c.json({ success: true, data: { items: [], total: 0, connected: false } });\n }\n\n try {\n // env-keyed callers pass environment_id; a registration-only\n // runtime's oscc_ bearer carries the org by itself.\n const qs = environmentId ? `?environment_id=${encodeURIComponent(environmentId)}` : '';\n const resp = await fetch(\n `${cloudUrl}/api/v1/cloud/org-packages${qs}`,\n { headers: { Accept: 'application/json', ...authHeaders() } },\n );\n if (!resp.ok) return c.json({ success: true, data: { items: [], total: 0, connected: true } });\n const json: any = await resp.json().catch(() => ({}));\n const data: any = json?.data ?? json ?? {};\n const items = Array.isArray(data.items) ? data.items : [];\n return c.json({ success: true, data: { items, total: items.length, connected: true } });\n } catch (err: any) {\n ctx.logger?.warn?.(`[CloudConnectionPlugin] org-packages failed: ${String(err?.message ?? err)}`);\n return c.json({ success: true, data: { items: [], total: 0, connected: true } });\n }\n });\n\n ctx.logger?.info?.(`[CloudConnectionPlugin] mounted ${CLOUD_CONNECTION_PREFIX}/{status,bind/start,bind/poll,install,installation,installed,org-packages} → ${cloudUrl || '(cloud unconfigured)'}`);\n });\n };\n}\n\n/** Factory mirroring the package's other plugins' construction style. */\nexport function createCloudConnectionPlugin(config: CloudConnectionPluginConfig = {}): CloudConnectionPlugin {\n return new CloudConnectionPlugin(config);\n}\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * Cloud Connection — SDUI surface (metadata, not React).\n *\n * The binding UI ships WITH the plugin as page + navigation metadata\n * (ADR-0029 K2: capability plugins contribute their own Setup entries;\n * cloud ADR-0008 / console-SDUI direction: new console surfaces are\n * metadata-first). The only React involved is the registered\n * `cloud-connection:panel` widget — the device-code state machine — which\n * the console registers once as a reusable primitive; everything else\n * (page shell, nav placement, labels) is server-driven and can evolve\n * without a console release.\n */\n\nimport type { Page } from '@objectstack/spec/ui';\n\n/** Setup page hosting the binding panel widget. */\nexport const CloudConnectionSettingsPage: Page = {\n name: 'cloud_connection_settings',\n label: 'Cloud Connection',\n type: 'app',\n template: 'default',\n kind: 'full',\n isDefault: false,\n regions: [\n {\n name: 'header',\n width: 'full',\n components: [\n {\n type: 'page:header',\n properties: {\n title: 'Cloud Connection',\n subtitle:\n 'Connect this runtime to an ObjectStack control plane to browse your '\n + 'organization\\'s private packages and install them here.',\n icon: 'cloud',\n },\n },\n ],\n },\n {\n name: 'main',\n width: 'large',\n components: [\n {\n // Registered console widget — the RFC 8628 device-code\n // state machine (status → start → user-code display →\n // poll → bound / disconnect). Talks to the same-origin\n // /api/v1/cloud-connection/* routes this plugin mounts.\n type: 'cloud-connection:panel',\n properties: {},\n },\n ],\n },\n ],\n};\n\n/** Setup-nav contribution: System group, after the marketplace entries. */\nexport const CLOUD_CONNECTION_NAV_CONTRIBUTIONS = [\n {\n app: 'setup',\n group: 'group_apps',\n priority: 200,\n items: [\n {\n id: 'nav_cloud_connection',\n type: 'page',\n pageName: 'cloud_connection_settings',\n label: 'Cloud Connection',\n icon: 'cloud',\n },\n ],\n },\n];\n\n/** Manifest bundle the plugin registers so the page + nav reach the kernel. */\nexport const CLOUD_CONNECTION_UI_BUNDLE = {\n id: 'com.objectstack.cloud-connection.ui',\n namespace: 'sys',\n version: '0.1.0',\n type: 'plugin',\n scope: 'system',\n name: 'Cloud Connection UI',\n description: 'Setup page + navigation for binding this runtime to a control plane.',\n pages: [CloudConnectionSettingsPage],\n navigationContributions: CLOUD_CONNECTION_NAV_CONTRIBUTIONS,\n};\n","// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.\n\n/**\n * RuntimeConfigPlugin\n *\n * Serves `GET /api/v1/runtime/config` (and the legacy alias\n * `GET /api/v1/studio/runtime-config`) so the Console / Studio SPA can learn\n * the upstream cloud URL and capability flags **at boot time**, instead of\n * sniffing `window.location.hostname` or reading Vite-time env vars.\n *\n * Response shape:\n *\n * {\n * cloudUrl: string, // base URL of the upstream cloud ('' = same origin)\n * singleEnvironment: boolean,\n * defaultOrgId?, defaultEnvironmentId?, // multi-tenant, per-hostname\n * features: { installLocal, marketplace, aiStudio, autoPublishAiBuilds, ... },\n * branding: { productName, productShortName }\n * }\n *\n * ## Feature seam (open-core boundary — cloud ADR-0012)\n *\n * This open package owns the **mechanism**: serve a per-request `features`\n * map to the SPA. It does NOT own the **catalog or policy** — which feature\n * keys exist and which billing plan unlocks them is a distribution concern\n * and must never be enumerated here (that would bleed commercial/pricing\n * policy into the open framework).\n *\n * Hosts inject policy via {@link RuntimeConfigPluginConfig.resolveFeatures}: it\n * receives an opaque environment token (the cloud distribution passes the plan\n * string) and returns an **open-ended** map of feature flags that is merged\n * verbatim into `features`. The framework neither names nor knows those keys —\n * e.g. the cloud distribution returns `customDomain` / `sso` from its plan\n * entitlements without any framework change. A self-hosted / vanilla\n * deployment omits the hook and gets static, config-driven flags.\n *\n * `aiStudio` / `autoPublishAiBuilds` are the framework's own non-commercial\n * mechanism defaults (ADR-0005: AI authoring is an all-plan capability gated\n * by cost, not a paid tier), so they keep first-class config knobs here.\n */\n\nimport type { Plugin, PluginContext } from '@objectstack/core';\nimport { resolveCloudUrl } from './cloud-url.js';\n\n/**\n * Feature-flag overrides a host's distribution policy can derive per request.\n *\n * Open-ended on purpose: the framework's own flags (`aiStudio`,\n * `autoPublishAiBuilds`) are named, but a distribution may return **any**\n * additional boolean keys (commercial tiering, white-label toggles, …) and\n * they pass through to the SPA untouched. The framework does not enumerate\n * the distribution's feature catalog.\n */\nexport interface RuntimeFeatureOverrides {\n /** Whether the SPA should surface AI-driven metadata authoring. */\n aiStudio?: boolean;\n /** Whether AI-built apps auto-publish in the author's own environment. */\n autoPublishAiBuilds?: boolean;\n /** Distribution-specific flags pass through opaquely (e.g. customDomain, sso). */\n [feature: string]: boolean | undefined;\n}\n\n/** @deprecated billing-vocab name; use {@link RuntimeFeatureOverrides}. */\nexport type RuntimeConfigPlanFeatures = RuntimeFeatureOverrides;\n\nexport interface RuntimeConfigPluginConfig {\n /**\n * Upstream cloud base URL. Falls back to `resolveCloudUrl()` (reads\n * `OS_CLOUD_URL` / built-in default) when omitted. Pass an explicit\n * empty string to declare \"this runtime IS the cloud\" (same-origin\n * for marketplace + install).\n */\n controlPlaneUrl?: string;\n /** Override the `features.installLocal` flag. Default: false. */\n installLocal?: boolean;\n /**\n * Override the `features.aiStudio` flag — whether the SPA should surface\n * AI-driven metadata authoring (\"online development\") affordances.\n * Default: true (the actual authoring capability is still gated\n * server-side; set false to force-hide the authoring UI).\n */\n aiStudio?: boolean;\n /**\n * Report this runtime as a single-environment deployment (CLI\n * `objectstack dev` / `os serve`). Defaults to `false` for\n * multi-tenant deployments.\n */\n singleEnvironment?: boolean;\n /**\n * Product name shown in browser title, splash screen, and other\n * client chrome. Operators can override per-deployment (white-label,\n * regional rebrands). Falls back to `OS_PRODUCT_NAME` env var, then\n * to the default `'ObjectOS'`.\n */\n productName?: string;\n /** Short product name (PWA shortName, compact spots). Defaults to productName. */\n productShortName?: string;\n /**\n * Distribution feature-policy hook (open-core seam — cloud ADR-0012).\n * Called with `undefined` for the static default (no environment resolved\n * / no token known) and with an opaque environment token (the cloud\n * distribution passes the plan string) once hostname resolution provides\n * one. Returned flags are merged verbatim into `features` — arbitrary keys\n * pass through. Omitted keys keep the static config defaults; when the hook\n * itself is omitted, flags are purely config-driven. The framework does NOT\n * know the distribution's feature catalog or pricing.\n */\n resolveFeatures?: (token: string | undefined) => RuntimeFeatureOverrides;\n /**\n * @deprecated billing-vocab name; use {@link resolveFeatures}. Still\n * honoured when `resolveFeatures` is absent so existing hosts keep working.\n */\n resolvePlanFeatures?: (plan: string | undefined) => RuntimeFeatureOverrides;\n}\n\nexport class RuntimeConfigPlugin implements Plugin {\n readonly name = 'com.objectstack.runtime.runtime-config';\n readonly version = '1.0.0';\n\n private readonly cloudUrl: string;\n private readonly installLocal: boolean;\n private readonly aiStudio: boolean;\n private readonly singleEnvironment: boolean;\n private readonly productName: string;\n private readonly productShortName: string;\n private readonly resolveFeatures?: (token: string | undefined) => RuntimeFeatureOverrides;\n\n constructor(config: RuntimeConfigPluginConfig = {}) {\n // An explicit empty string means \"stay on this origin\" — bypass the\n // resolver which would otherwise fall back to the default cloud URL.\n this.cloudUrl = config.controlPlaneUrl === ''\n ? ''\n : (resolveCloudUrl(config.controlPlaneUrl) ?? '');\n this.installLocal = !!config.installLocal;\n this.aiStudio = config.aiStudio !== false; // default true (override-to-hide)\n this.singleEnvironment = !!config.singleEnvironment;\n // Prefer the plan-agnostic seam; fall back to the deprecated alias.\n this.resolveFeatures = config.resolveFeatures ?? config.resolvePlanFeatures;\n const envName = (typeof process !== 'undefined' ? process.env?.OS_PRODUCT_NAME : undefined)?.trim();\n const envShort = (typeof process !== 'undefined' ? process.env?.OS_PRODUCT_SHORT_NAME : undefined)?.trim();\n this.productName = (config.productName ?? envName ?? 'ObjectOS').trim() || 'ObjectOS';\n this.productShortName = (config.productShortName ?? envShort ?? this.productName).trim() || this.productName;\n }\n\n init = async (_ctx: PluginContext): Promise<void> => {};\n\n start = async (ctx: PluginContext): Promise<void> => {\n ctx.hook('kernel:ready', async () => {\n let httpServer: any;\n try {\n httpServer = ctx.getService('http-server');\n } catch {\n ctx.logger?.warn?.('[RuntimeConfigPlugin] http-server not available — runtime/config not mounted');\n return;\n }\n if (!httpServer || typeof httpServer.getRawApp !== 'function') {\n ctx.logger?.warn?.('[RuntimeConfigPlugin] http-server missing getRawApp() — runtime/config not mounted');\n return;\n }\n const rawApp = httpServer.getRawApp();\n\n // A multi-tenant runtime serves many subdomains, each mapped to\n // one environment. Telling the SPA *which* environment it is\n // attached to (per-request) lets the App Marketplace skip the\n // env-picker dialog and install directly into \"this\" env — the\n // operator's domain already identifies it.\n //\n // Hostname → env is resolved by the same registry the per-env\n // kernel router uses (env-registry). Falls back to the static\n // payload when the host doesn't map to any env (e.g. a marketing\n // root or a CLI-served single-env runtime).\n let envRegistry: any = null;\n try { envRegistry = ctx.getService('env-registry'); } catch { /* not mounted (file/CLI mode) */ }\n\n // Merge the distribution's feature overrides over the static base.\n // Arbitrary keys returned by the host pass through verbatim — the\n // framework does not enumerate the distribution's feature catalog.\n const featuresFor = (\n token: string | undefined,\n base: Record<string, boolean>,\n ): Record<string, boolean> => {\n const derived = this.resolveFeatures?.(token);\n if (!derived) return { ...base };\n const out: Record<string, boolean> = { ...base };\n for (const [k, v] of Object.entries(derived)) {\n if (typeof v === 'boolean') out[k] = v;\n }\n return out;\n };\n\n const handler = async (c: any) => {\n const rawHost = c.req.header('host') ?? '';\n const host = rawHost.split(':')[0].toLowerCase().trim();\n let defaultEnvironmentId: string | undefined;\n let defaultOrgId: string | undefined;\n let resolvedSingleEnv = this.singleEnvironment;\n // Static defaults: config-driven, optionally shaped by the\n // host's policy hook for the \"no token known\" case.\n let features = featuresFor(undefined, { aiStudio: this.aiStudio, autoPublishAiBuilds: false });\n // EnvironmentDriverRegistry exposes `resolveByHostname()`;\n // older code paths used `resolveHostname()` on the client.\n // Accept either so production runtimes don't silently no-op\n // and leave the SPA showing the env picker.\n const resolveFn: ((h: string) => Promise<any>) | null =\n typeof envRegistry?.resolveByHostname === 'function'\n ? envRegistry.resolveByHostname.bind(envRegistry)\n : typeof envRegistry?.resolveHostname === 'function'\n ? envRegistry.resolveHostname.bind(envRegistry)\n : null;\n if (resolveFn && host) {\n try {\n const resolved = await resolveFn(host);\n if (resolved?.environmentId) {\n defaultEnvironmentId = String(resolved.environmentId);\n const orgId = resolved.organizationId ?? resolved.organization_id;\n if (orgId) defaultOrgId = String(orgId);\n // Each subdomain is one environment from the\n // operator's POV: surface as single-environment\n // so the SPA hides multi-env affordances.\n resolvedSingleEnv = true;\n // Distribution-derived features — only an explicit\n // non-empty token re-runs the policy hook.\n if (typeof resolved.plan === 'string' && resolved.plan.trim() !== '') {\n features = featuresFor(resolved.plan, features);\n }\n }\n } catch {\n // Resolver failures are non-fatal — fall through\n // to the static payload so /runtime/config never\n // 500s. Worst case the SPA shows its env picker.\n }\n }\n return c.json({\n cloudUrl: this.cloudUrl,\n singleEnvironment: resolvedSingleEnv,\n defaultOrgId,\n defaultEnvironmentId,\n features: {\n installLocal: this.installLocal,\n marketplace: true,\n // aiStudio + autoPublishAiBuilds + any distribution keys.\n ...features,\n },\n branding: {\n productName: this.productName,\n productShortName: this.productShortName,\n },\n });\n };\n rawApp.get('/api/v1/runtime/config', handler);\n // Legacy alias for older Studio bundles.\n rawApp.get('/api/v1/studio/runtime-config', handler);\n });\n };\n}\n"],"mappings":"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","names":["headers","body","existsSync","mkdirSync","readFileSync","unlinkSync","writeFileSync","resolve","authSvc","bound"]}