{"version":3,"sources":["../src/mounts.ts"],"sourcesContent":["import { APP_ROOT } from '@immediately-run/platform-constants';\nimport { throwOnRefusal } from './protocolRefusal';\n\nimport { useEffect, useState } from 'react';\nimport { protocolRequest, sendMessage, addListener } from './sandboxUtils';\nimport { createPushChannel } from './pushChannel';\nimport { getHostRuntime } from './hostRuntime';\nimport { mountMatches } from './mountMatch';\n// R3-166 — the `spaces:*` family is GENERATED from the capability descriptor set\n// (`scripts/codegen-prototype/descriptors.spaces.mjs`) rather than hand-written here.\n// Re-exported from this module so every existing import path keeps working: the\n// swap is a no-op to consumers (SDK_SIMPLIFICATION_SPEC §7 step 3), which is\n// asserted by the emitted-`.d.ts` before/after comparison, not assumed. The five\n// invite-inbox verbs joined the generated family with their `Invite` type (the\n// declared \"next migration increment\" after #85); the mount verbs and the live\n// inbox channel trio below stay hand-written — they are not request wrappers.\n//\n// The invite channel's parse below uses `Invite`, so it is imported (not only\n// re-exported).\nimport type { Invite } from './generated/spaces';\nexport type { Role, SpaceInfo, Member, ResolvedUser, GrantRecord, Invite } from './generated/spaces';\nexport {\n  listSpaces,\n  listAllSpaces,\n  getSpaceMembers,\n  inviteToSpace,\n  unshareSpace,\n  setSpaceRole,\n  lookupUser,\n  listGrants,\n  revokeGrant,\n  listPendingInvites,\n  revokeInvite,\n  listMyInvites,\n  acceptInvite,\n  declineInvite,\n  // R3-723 — the space lifecycle verbs (FILE_SHARING_SPEC §6.2/§9.7): soft\n  // delete + undo, leave, rename, and the named one-way conversion.\n  deleteSpace,\n  restoreSpace,\n  leaveSpace,\n  renameSpace,\n  convertSpaceToShared,\n} from './generated/spaces';\nexport type {\n  DeleteSpaceError,\n  RestoreSpaceError,\n  LeaveSpaceError,\n  RenameSpaceError,\n  ConvertSpaceToSharedError,\n} from './generated/spaces';\n// Type-only: `tasks.ts` registers a host listener at module load, so we reuse the\n// FileCap SHAPE without pulling that side effect into every `mounts` importer.\nimport type { FileCap } from './tasks';\nimport {\n  INVITATIONS,\n  MOUNT_ADD,\n  MOUNT_REMOVE,\n  PROTOCOL_LOCALSTORE,\n  PROTOCOL_SETTINGS,\n  PROTOCOL_SPACES,\n  REQUEST_INVITATIONS,\n  REQUEST_MOUNTS,\n  REQUEST_SESSION_MOUNTS,\n  SESSION_MOUNTS,\n} from './generated/protocol';\nimport { SCHEMES } from './protocolSchemes';\nimport { invoke } from './catalog';\n// Re-exported here so an app needs ONE import for a federated mount's bundle facts\n// (`SandboxMount.bundle` + the layout type it carries) — the same root-export\n// convention `linkSpace.ts` applies to the mdx-plugins link types.\nimport type { BundleLayout } from '@immediately-run/mdx-plugins';\nexport type { BundleLayout };\n\n/**\n * The absolute path where this app's own repository filesystem is mounted\n * (FILE_SHARING_SPEC §11.2). Prefer this over hardcoding `/app`: the repo is\n * dual-mounted at both `/app` (back-compat) and its canonical `/mnt/{hash}`\n * address, and this returns the canonical one the host reports. Falls back to\n * `/app` when the host hasn't reported a canonical path (older host / before the\n * report arrives) — both paths are live, so either resolves the same files.\n */\nexport const getAppMountPath = (): string => getHostRuntime()?.appMountPath ?? APP_ROOT;\n\n/**\n * A filesystem mount available to the sandbox, mirrored from the host window.\n *\n * Mounts appear on demand — call {@link openSettings} for this app's own settings,\n * or {@link mountSpace} / {@link requestMount} to mount a Firestore-backed \"space\".\n * Read or subscribe to the set, then access the files through the `fs` module at\n * the mount's `path`.\n */\nexport interface SandboxMount {\n  /** Absolute path where the mount is reachable (e.g. `/spaces/{id}`). */\n  path: string;\n  /** Backend kind, e.g. `'firestore'`. */\n  type: string;\n  /** Optional stable identifier (the spaceId, for spaces). */\n  id?: string;\n  /**\n   * Access mode of the granted view: `'rw'` (read-write) or `'ro'` (read-only).\n   * A live role downgrade re-announces the same mount with `mode: 'ro'`; apps\n   * observing `onMountsChange` see the change and writes start failing `EROFS`.\n   * Absent on the primary repo mount (treated as read-write).\n   */\n  mode?: 'ro' | 'rw';\n  /**\n   * Human-readable label for the mount — the space's display name, or the repo\n   * label for the primary working-tree mount (R3-69). Use this to show users and\n   * agents *what* a mount is: the `path` (`/mnt/{hash}`) and `id` (the spaceId)\n   * are opaque, and space names are not unique, so neither alone tells you which\n   * filesystem you're looking at. Absent when the host can't resolve a name\n   * (older host, or a name it never learned) — fall back to `id`/`path`.\n   */\n  name?: string;\n  /**\n   * The granted scopes of this mount (plan 12 §8.7 / §F): each `{subtree, mode}`\n   * is a path prefix you hold and at what access, at the mount's backend-natural\n   * paths. Use it to reason about per-path writability — which subtree is `rw` —\n   * WITHOUT probing `EROFS`. A single whole-mount grant is `[{ subtree: '/', mode }]`.\n   * Absent on the primary repo mount and on an older host that doesn't report it.\n   */\n  rules?: MountRule[];\n  /**\n   * R3-546 (BUNDLE_EMBEDDING §4a.3, gate G-BE-19): bundle facts, when this mount is a\n   * federated `bundle:` view over another bundle. The host parses the target bundle's\n   * marker and hands the consumer its `kind` and its LAYOUT **pruned to this mount's\n   * subtree view** — a record set, `tree` entry or `unique` reference the view cannot\n   * reach is absent, so the description is never an existence map of what the chroot\n   * answers `ENOENT` for. Pure data: nothing in it is authority, and the consumer\n   * could have read it if it held the target's root. Absent on every non-bundle mount\n   * and on older hosts.\n   */\n  bundle?: SandboxMountBundle;\n  /**\n   * R3-876 (APP_CUSTOMIZATION_SPEC §5a): the host's advisory reading of whether the\n   * READER can edit this delegation's source — computed from the reader's own\n   * authority (their role on the source space, or sign-in for a working tree), NOT\n   * from anything about your own mount. Gate an Edit affordance on it\n   * (`requestEdit({ bundleFile })` is the call it hints at): offer the control when\n   * `true`, hide it when `false`, and treat an absent hint (older host, non-delegation\n   * mount) as \"unknown — offer and let the refusal tell you\". Display-only: it is\n   * never an authority input, and the host re-announces the mount when a role change\n   * flips it.\n   */\n  readerCanEdit?: boolean;\n}\n\n/** The bundle facts a federated mount descriptor carries (§4a.3). */\nexport interface SandboxMountBundle {\n  /** The target bundle's declared `kind`, when it declares one. */\n  kind?: string;\n  /**\n   * R3-184 (PERSISTENCE_SPEC §8.0/§8.5) — the DECLARED in-bundle mount name\n   * (`requests.mounts[].at`, e.g. `/items`): the alias the declaring bundle's own\n   * documents address this view by, carried beside the mount's `path` (the\n   * host-assigned task slot, §8.3). Pure data — it is never authority and never a\n   * second mount point; a bundle-carrying app matches the alias back to the\n   * declaration that minted the view. Absent on older hosts.\n   */\n  at?: string;\n  /** The target's layout, pruned to this mount's view (`pruneLayoutToView`). */\n  layout?: BundleLayout;\n  /**\n   * Why a refused or `forbidden` `bundle:` mount degraded the DECLARING bundle's\n   * render (PERSISTENCE §8.0 containment: the carrying filesystem stays mounted).\n   * Mount-resolution refusal codes (`escapes-filesystem`, `not-a-bundle`,\n   * `unsafe-subtree`, `subtree-in-nested-bundle`, …), surfaced so the callee can\n   * read them — the declaring bundle always renders, degraded wherever a\n   * declaration did not resolve.\n   */\n  diagnostics?: readonly string[];\n}\n\n/** One granted scope of a mount (plan 12 §F): a backend-natural path prefix and\n *  the access mode there. The most specific (longest) matching rule governs a path. */\nexport interface MountRule {\n  subtree: string;\n  mode: 'ro' | 'rw';\n}\n\n/**\n * Why a mounted filesystem was removed, surfaced on the removed descriptor so an\n * app can say *why* it vanished instead of failing mutely (auth-mount §\"mount-remove\"\n * / AM2-4):\n * - `revoked` — a durable grant was revoked (revokeGrant / consent withdrawal);\n * - `unshared` — the granting user's membership was removed (or downgraded out);\n * - `signed-out` — sign-out tore down every mount;\n * - `unmounted` — the app's own `unmountSpace` (or region teardown);\n * - `deleted` — the space was soft-deleted.\n * An older host that sends no reason is read as `'revoked'` (most conservative).\n */\nexport type MountRemoveReason = 'revoked' | 'unshared' | 'signed-out' | 'unmounted' | 'deleted';\n\n/** A descriptor delivered as REMOVED to a mounts-change listener: the mount that\n *  went away, plus the `reason` it did. */\nexport interface RemovedMount extends SandboxMount {\n  reason: MountRemoveReason;\n}\n\ninterface MountService {\n  getMounts(): SandboxMount[];\n  onChange(listener: (mounts: SandboxMount[], removed: RemovedMount[]) => void): { dispose(): void };\n}\n\n// The stable key of a mount: its `id` (spaceId) when present, else its `path`.\n// Matches the sandbox `MountService.mountKey` so add/replace/remove agree on both\n// sides of the wire (a role downgrade re-announces the SAME key with `mode: 'ro'`).\nconst mountKey = (m: SandboxMount): string => m.id ?? m.path;\n\nconst MOUNT_REMOVE_REASONS: ReadonlySet<string> = new Set<MountRemoveReason>([\n  'revoked',\n  'unshared',\n  'signed-out',\n  'unmounted',\n  'deleted',\n]);\n\n// Normalize an over-the-wire `mount-remove` reason; an absent/unknown value (older\n// host) reads as `'revoked'`, the most conservative reading (mirrors the sandbox).\nconst asMountRemoveReason = (value: unknown): MountRemoveReason =>\n  typeof value === 'string' && MOUNT_REMOVE_REASONS.has(value) ? (value as MountRemoveReason) : 'revoked';\n\n// The injected sandbox-bundler mount service (`module.evaluation.module.bundler.mounts`),\n// or null when the SDK is npm-fetched with no injection — same dual-mode shape as\n// `sandboxUtils.transport()` and the metadata emitter (SDK_PACKAGING_SPEC §4/§8).\n/** @deprecated-path The injected `bundler.mounts` read — window opened 2026-08-25\n *  (R3-278). The protocol equivalent is `transportMountService()` below (the\n *  `mount-add`/`mount-remove` mirror + `request-mounts` replay), which the dual-mode\n *  chooser already falls back to. Injection stays preferred for byte-compat through\n *  the window; see DEPRECATION_CANDIDATES.md.\n */\nconst injectedMountService = (): MountService | null => {\n  try {\n    // @ts-ignore - injected by the sandbox runtime\n    const svc = module?.evaluation?.module?.bundler?.mounts;\n    return svc && typeof svc.getMounts === 'function' ? svc : null;\n  } catch {\n    return null;\n  }\n};\n\n// Transport-backed descriptor cache (R3-51b): the npm-fetched fallback that builds\n// the same `getMounts()`/`onChange()` view the injected `bundler.mounts` provides,\n// directly from the host's `mount-add`/`mount-remove` messages over the §4 transport.\n// The host already posts these (it's how the in-iframe bundler service is populated);\n// the `MessagePort` a `mount-add` transfers is consumed by the sandbox runtime to wire\n// ZenFS and is irrelevant here — the SDK only mirrors the *descriptors*. A lazy\n// singleton so `getMounts`/`onMountsChange` share one cache, one subscription, and one\n// `request-mounts` replay (the host re-announces every current mount, like a poll).\nlet transportSvc: MountService | null = null;\n\nconst transportMountService = (): MountService => {\n  if (transportSvc) return transportSvc;\n  let mounts: SandboxMount[] = [];\n  const listeners = new Set<(m: SandboxMount[], r: RemovedMount[]) => void>();\n  const fire = (removed: RemovedMount[]) => {\n    for (const l of [...listeners]) l(mounts, removed);\n  };\n\n  addListener(MOUNT_ADD, (msg: Record<string, any>) => {\n    const mount: SandboxMount | undefined = msg.mount;\n    if (!mount) return;\n    const key = mountKey(mount);\n    mounts = [...mounts.filter((m) => mountKey(m) !== key), mount];\n    fire([]);\n  });\n  addListener(MOUNT_REMOVE, (msg: Record<string, any>) => {\n    const key: string | undefined = msg.id ?? msg.path;\n    if (key == null) return;\n    const reason = asMountRemoveReason(msg.reason);\n    const removed = mounts.filter((m) => mountKey(m) === key).map((m) => ({ ...m, reason }));\n    if (removed.length === 0) return;\n    mounts = mounts.filter((m) => mountKey(m) !== key);\n    fire(removed);\n  });\n\n  // Ask the host to replay the current set (the matching `mount-add`s may have been\n  // sent before this SDK subscribed). Best-effort: a transport not yet ready throws.\n  try {\n    sendMessage(REQUEST_MOUNTS);\n  } catch {\n    /* transport not ready — the live mount-add stream still populates the cache */\n  }\n\n  transportSvc = {\n    getMounts: () => mounts,\n    onChange: (listener) => {\n      listeners.add(listener);\n      listener(mounts, []); // immediate replay to the new subscriber\n      return { dispose: () => listeners.delete(listener) };\n    },\n  };\n  return transportSvc;\n};\n\n// Phase-5 dual mode: prefer the injected bundler service (the live path, behaviour\n// byte-for-byte unchanged); fall back to the transport-built cache when npm-fetched.\nconst mountService = (): MountService => injectedMountService() ?? transportMountService();\n\n/** A predicate-style matcher for {@link findMount} / {@link waitForMount}. Any\n *  combination of coordinates; `name` matches the human-readable mount label. */\nexport type MountQuery = { type?: string; id?: string; path?: string; name?: string };\n\nconst matches = (mount: SandboxMount, query: MountQuery): boolean => mountMatches(mount, query);\n\n/**\n * Returns the mounts currently available. Poll this whenever you need a one-off\n * read; use {@link onMountsChange} or {@link useMounts} to react to changes.\n * Each descriptor carries its `id` (the spaceId), `path` (`/mnt/{hash}`) and —\n * when the host can resolve it — a human-readable `name` (R3-69), so this doubles\n * as a queryable mount→space mapping for showing or locating a mount by name.\n */\nexport const getMounts = (): SandboxMount[] => mountService().getMounts();\n\n/** Returns the first mount matching `query`, or `undefined`. */\nexport const findMount = (query: MountQuery): SandboxMount | undefined => getMounts().find((m) => matches(m, query));\n\n/**\n * Subscribe to mount changes. The listener is invoked immediately with the\n * current mounts (and an empty `removed`), then again on every change. The second\n * argument carries the descriptors REMOVED by that change, each with its `reason`\n * (AM2-4) — so an app can react to *why* a mount vanished (e.g. tell the user a\n * shared space was `unshared` vs `deleted`). It is empty on adds and on the\n * initial replay. Returns an unsubscribe fn.\n */\nexport const onMountsChange = (listener: (mounts: SandboxMount[], removed: RemovedMount[]) => void): (() => void) => {\n  const disposable = mountService().onChange(listener);\n  return () => disposable.dispose();\n};\n\n/**\n * Resolves once a mount matching `query` is present (immediately if it already\n * is). Handy for \"use it when it appears\" — e.g.\n * `await waitForMount({ type: 'firestore' })` before reading `/firestore`.\n *\n * `timeoutMs` (optional, additive) rejects with a `timeout`-coded error instead of\n * waiting forever. Omit it to keep the original unbounded behaviour — but prefer\n * setting it on any path whose caller would otherwise hang silently: a mount that\n * never arrives is indistinguishable from one that is merely slow, and an awaited\n * promise that never settles surfaces to the user as a feature that quietly does\n * nothing.\n *\n * **Hazard — `onMountsChange` calls its listener SYNCHRONOUSLY on subscribe** (the\n * documented initial replay). So when the mount is already present — the common\n * case, since callers typically `await` the host request that creates it first —\n * the callback below runs *during* the `onMountsChange(...)` call, before the\n * assignment to `unsubscribe` completes. `unsubscribe` is therefore declared with\n * `let` ABOVE the subscription and read only inside a deferred closure: writing\n * `const unsubscribe = onMountsChange(...)` and referencing it in the callback\n * throws `ReferenceError: Cannot access 'unsubscribe' before initialization` (a\n * temporal-dead-zone read) on exactly that path. That bug silently broke\n * `openSettings()` — and with it the agent's conversation memory.\n */\nexport const waitForMount = (query: MountQuery, timeoutMs?: number): Promise<SandboxMount> =>\n  awaitMatchingMount(onMountsChange, query, timeoutMs);\n\n/** The framework-free core of {@link waitForMount}, with the subscription injected\n *  so a test can drive the synchronous-initial-replay case that broke it. */\nexport const awaitMatchingMount = (\n  subscribe: (listener: (mounts: SandboxMount[]) => void) => () => void,\n  query: MountQuery,\n  timeoutMs?: number,\n): Promise<SandboxMount> =>\n  new Promise((resolve, reject) => {\n    // `let`, declared BEFORE `subscribe(...)` — see the hazard note above. A\n    // `const` bound to the subscribe call is in its temporal dead zone while the\n    // synchronous initial replay runs, and any read of it from the listener\n    // throws.\n    let unsubscribe: (() => void) | undefined;\n    let settled = false;\n    let timer: ReturnType<typeof setTimeout> | undefined;\n    // Deferred so we never dispose the subscription from inside its own initial\n    // replay, and late enough that `unsubscribe` is always assigned.\n    const stop = (): void => {\n      settled = true;\n      if (timer !== undefined) clearTimeout(timer);\n      void Promise.resolve().then(() => unsubscribe?.());\n    };\n    unsubscribe = subscribe((mounts) => {\n      if (settled) return;\n      const found = mounts.find((m) => matches(m, query));\n      if (found) {\n        stop();\n        resolve(found);\n      }\n    });\n    // The initial replay may have settled us above, before `unsubscribe` existed;\n    // `stop()`'s deferred read picks it up, so nothing more is needed here.\n    if (!settled && timeoutMs !== undefined) {\n      timer = setTimeout(() => {\n        if (settled) return;\n        stop();\n        const err = new Error(\n          `waitForMount timed out after ${timeoutMs}ms waiting for ${JSON.stringify(query)}`,\n        ) as SpaceError;\n        err.code = 'timeout';\n        reject(err);\n      }, timeoutMs);\n    }\n  });\n\n/** React hook returning the mounts currently available, re-rendering on change. */\nexport const useMounts = (): SandboxMount[] => {\n  const [mounts, setMounts] = useState<SandboxMount[]>(getMounts);\n  useEffect(() => onMountsChange(setMounts), []);\n  return mounts;\n};\n\n// ---------------------------------------------------------------------------\n// Session-scope mounts — the first-party \"App | Session\" lens (PRINCIPALS §9 B2).\n// ---------------------------------------------------------------------------\n\n/** A mount as seen through the first-party **Session** lens (PRINCIPALS_SPEC §9 B2):\n *  the session's mounts BEYOND this app's own (the editor/agent session's). This is\n *  a metadata view — no filesystem port — so it extends {@link SandboxMount} with only\n *  {@link forwardedToApp}. */\nexport interface SessionMount extends SandboxMount {\n  /** True iff this mount is ALSO in the app's own {@link useMounts} (the App lens);\n   *  `false` for a session-export-only mount visible only to the editor/agent + the\n   *  Session lens. */\n  forwardedToApp: boolean;\n}\n\n// The host pushes the session mount list ONLY to a FIRST-PARTY frame — the channel\n// is gated by the first-party-only `mounts:registry` capability (§8.9.1 / D-PRIN-4).\n// A URL-loaded/previewed app (or a fork of the File Explorer) never holds it, so the\n// push never arrives and `initial: []` stands — the Session lens is simply absent,\n// fail-closed. Mirrors the host's `session-mounts`/`request-session-mounts` wiring.\nconst sessionMountsChannel = createPushChannel<SessionMount[]>({\n  pushType: SESSION_MOUNTS,\n  requestType: REQUEST_SESSION_MOUNTS,\n  initial: [],\n  parse: (msg) => (Array.isArray(msg.mounts) ? (msg.mounts as SessionMount[]) : undefined),\n});\n\n/** The session's mounts (the \"Session\" lens superset), or `[]` when this frame is\n *  not first-party. One-off read; use {@link onSessionMountsChange}/{@link useSessionMounts}\n *  to react live. First-party only (`mounts:registry`) — a fork always sees `[]`. */\nexport const getSessionMounts = (): SessionMount[] => sessionMountsChannel.get();\n\n/** Subscribe to Session-lens mount changes. Invoked immediately with the current\n *  list (`[]` for a non-first-party frame), then on every change. Returns an\n *  unsubscribe. */\nexport const onSessionMountsChange = (listener: (mounts: SessionMount[]) => void): (() => void) =>\n  sessionMountsChannel.onChange(listener);\n\n/** React hook returning the live \"Session\" lens mount list, re-rendering on change.\n *  Empty for any non-first-party frame (the host withholds the channel), so a URL-\n *  loaded File Explorer fork renders no Session lens. */\nexport const useSessionMounts = (): SessionMount[] => sessionMountsChannel.use();\n\n// ---------------------------------------------------------------------------\n// Spaces — on-demand, shareable Firestore-backed filesystems.\n// The host owns all UX: if you aren't signed in, or the space doesn't exist or\n// isn't accessible, the parent window presents sign-in / create / request-access\n// and only then resolves these calls. See docs/specs/FILE_SHARING_SPEC.md.\n// ---------------------------------------------------------------------------\n\n/** An error from a space operation, carrying a machine-readable `code`.\n *\n *  **What you actually catch.** The SDK throws a plain `Error` with `.code` assigned — a\n *  `CodedRefusalError` from `protocolRefusal.ts` — never a distinct class. This interface\n *  documents the `.code` VALUES the host sends. Nothing enforces the union at runtime —\n *  `.code` is whatever string arrived — so treat an unlisted code as possible and\n *  `instanceof Error` as the only reliable test.\n */\nexport interface SpaceError extends Error {\n  code:\n    | 'auth-required'\n    | 'cancelled'\n    | 'forbidden'\n    | 'not-found'\n    | 'unsupported-scheme'\n    // Client-side, never from the host: a bounded `waitForMount` gave up.\n    | 'timeout'\n    | 'unknown';\n}\n\ntype SpaceResult = { ok: true; data: unknown } | { ok: false; code: string; message: string };\n\n// Issue a spaces protocol request, unwrapping the host's {ok,data} envelope and throwing\n// a coded refusal on failure — `throwOnRefusal` raises a `CodedRefusalError` whose `code`\n// is whatever string the host sent, NOT a `SpaceError` (nothing enforces that union, and\n// this helper no longer performs the throw). See `protocolRefusal.ts`.\nconst request = async <T = unknown>(method: string, query: Record<string, unknown> = {}): Promise<T> => {\n  const res = (await protocolRequest(SCHEMES[PROTOCOL_SPACES], method, [query])) as SpaceResult;\n  throwOnRefusal(res, 'space request failed');\n  return res.data as T;\n};\n\n// Request a space mount, then wait until the host actually registers it. The\n// host announces the mount (`mount-add`) separately from the protocol reply, so\n// an immediate read could otherwise race the mount.\nconst requestMountInternal = async (method: string, query: Record<string, unknown>): Promise<SandboxMount> => {\n  const mount = await request<SandboxMount>(method, query);\n  return waitForMount({ id: mount.id ?? mount.path });\n};\n\n/**\n * Mount a filesystem by its **universal mount id** (UI_AS_APPS_SPEC §3.5) —\n * `scheme:locator`, e.g. `space:{spaceId}` or `github:owner/repo@ref`. Backend-blind:\n * the host resolves the scheme. A scheme with no resolver rejects with\n * {@link SpaceError} `unsupported-scheme`.\n */\nexport const mount = (mountId: string): Promise<SandboxMount> => requestMountInternal('mount', { mount: mountId });\n\n/** Mount a specific space by id (e.g. one shared with you, or from a link). A thin\n *  shim over {@link mount} with the `space:` scheme. */\nexport const mountSpace = (query: { spaceId: string }): Promise<SandboxMount> => mount(`space:${query.spaceId}`);\n\n/**\n * Ask the user to grant a filesystem to this app — the §8.6 powerbox. The app\n * asks; the HOST shows the user their spaces and, for the chosen one, its PROJECT\n * FOLDERS (§8.7). The user picks ONE project — so a shared space opens scoped to\n * just that project, never the whole space — and makes an EXPLICIT read-only vs\n * read-write decision (there is no default). The app never sees the list; it\n * resolves with the single granted mount, or rejects with a {@link SpaceError}\n * (`cancelled`) if declined. The granted scope is enforced host-side: the mount\n * is chroot'd to the project folder and `ro`-limited accordingly, so paths\n * outside the project are unnameable and writes on a `ro` grant fail `EROFS`.\n *\n * A project folder is the macOS-bundle-like unit an app works in inside a space;\n * the host records which app a folder belongs to (a `.immediately.run/` sidecar),\n * so the picker can surface the app's own projects or let the user create a new\n * one. Observe the granted access via {@link SandboxMount.mode}.\n *\n * Backend-general (§3.5): the picker offers whatever mounts the user has (today,\n * their spaces). Returns the granted mount by its universal id.\n */\nexport const requestMount = (): Promise<SandboxMount> => requestMountInternal('request', {});\n\n/** Prompt the user to grant a mount, returning the granted {@link SandboxMount}.\n *  @deprecated renamed to {@link requestMount} (backend-general, §3.5). */\nexport const requestSpace = requestMount;\n\n// ── content references (plan 12 §E / FILE_SHARING §7) ────────────────────────\n\n/**\n * Build a persisted CONTENT REFERENCE to a file in a mount — a `{mountId, relPath}`\n * pointer your app serializes into ITS OWN content (a board's JSON, an MDX file's\n * frontmatter, an album manifest — the platform doesn't dictate the container) so a\n * later viewer can resolve it. It is exactly the §5.7 {@link capFile} shape: ONE\n * capability, two delivery modes — runtime delegation (a task param, authorized by\n * the caller) vs a durable reference (authorized per-viewer by {@link resolveContentRef}).\n * `relPath` is BACKEND-NATURAL, so the reference resolves to the SAME path for every\n * viewer. Cross-app/cross-project references default to `ro`.\n *\n *   const ref = makeContentRef({ mountId: 'space:ACME', relPath: 'office-seating/desk.mdx' }, { mode: 'ro' });\n *\n * The body repeats {@link capFile} rather than calling it, and that is deliberate:\n * `tasks.ts` registers a host listener at module load, so a VALUE import of it here\n * would run that side effect in every importer of `mounts` (which is why the\n * `FileCap` import above is type-only). The shape the two share is the spec's, and\n * the `FileCap` type is what holds them to it.\n */\nexport const makeContentRef = (ref: { mountId: string; relPath: string }, opts: { mode: 'ro' | 'rw' }): FileCap => ({\n  $cap: 'file',\n  mountId: ref.mountId,\n  relPath: ref.relPath,\n  mode: opts.mode,\n});\n\n/**\n * Resolve a content reference your app found in content it ALREADY holds\n * (FILE_SHARING §7 / UI_AS_APPS §8.7; \"plan 12 §E\"). This is a RELAY, not a\n * fabrication: the host honors it ONLY when your app\n * already holds a grant to `ref.mountId` (else `forbidden`) — apps follow\n * writer-authored links inside granted content; they cannot name a space from\n * nothing (T27). The host runs a per-VIEWER consent prompt (named via the owning\n * app's project sidecar), and existence is never leaked — a decline and a\n * non-existent path are indistinguishable.\n *\n * On allow, the host APPENDS a read scope for the referenced path to your grant\n * (durable; same §8.15 lifecycle) and returns the STABLE absolute `path` the file\n * is mounted at — identical for every viewer, so a path the author stored resolves\n * the same for you. Read it through the `fs` module at that path. Rejects with a\n * {@link SpaceError}: `forbidden` (you don't hold the referenced mount) or\n * `cancelled` (the viewer declined / the path doesn't exist — no oracle).\n *\n *   const { path } = await resolveContentRef(ref);\n *   const text = await fs.promises.readFile(path, 'utf8');\n */\nexport const resolveContentRef = async (ref: FileCap): Promise<{ path: string }> => {\n  const path = await request<string>('resolveRef', { ref });\n  return { path };\n};\n\n/**\n * Resolve a BATCH of content references in ONE consent round (FILE_SHARING §7 /\n * UI_AS_APPS §8.7; \"plan 12 §E\"). When a\n * board opens with several embedded references, pass them all here: the host\n * coalesces them into a SINGLE consent prompt listing every target, instead of one\n * prompt per reference. Same relay gate and per-viewer semantics as\n * {@link resolveContentRef} (each ref's mount must already be held), applied to the\n * whole set — it is all-or-nothing: the user allows the batch or declines it.\n *\n * Resolves `{ paths }` with the STABLE absolute path of each ref, in input order.\n * Rejects with a {@link SpaceError}: `forbidden` (a referenced mount isn't held) or\n * `cancelled` (the viewer declined).\n *\n *   const { paths } = await resolveContentRefs(board.references);\n */\nexport const resolveContentRefs = async (refs: FileCap[]): Promise<{ paths: string[] }> => {\n  const paths = await request<string[]>('resolveRefs', { refs });\n  return { paths };\n};\n\n// ---------------------------------------------------------------------------\n// Settings — the per-user \"~/.config\"-style space (UI_AS_APPS_SPEC §3.3/§3.5/§8.2).\n// Each app gets its OWN settings subdir, auto-provisioned and chroot'd by the host\n// (no dialog, no powerbox). Read/write it through the returned mount's filesystem\n// port — there is deliberately no key/value get/set API; settings are just files.\n// ---------------------------------------------------------------------------\n\n// Issue a `protocol-settings` request, unwrapping {ok,data} and throwing a coded refusal\n// on failure (mirrors `request`; the thrown value is a `CodedRefusalError`, not a\n// `SpaceError` — see `protocolRefusal.ts`).\nconst settingsRequest = async <T = unknown>(method: string, query: Record<string, unknown> = {}): Promise<T> => {\n  const res = (await protocolRequest(SCHEMES[PROTOCOL_SETTINGS], method, [query])) as SpaceResult;\n  throwOnRefusal(res, 'settings request failed');\n  return res.data as T;\n};\n\n/**\n * Mount this app's per-user settings — a private `~/.config`-style filesystem,\n * auto-provisioned for the signed-in user and isolated to THIS app (the host\n * chroots it; a different app can never name it). Read/write config files through\n * the returned mount. Rejects with a {@link SpaceError} (`auth-required`) when\n * signed out. Capability: baseline `settings:app`.\n *\n * **Which filesystem you get, and when that can change** (R3-413): for an\n * ordinary app — including one holding space grants, powerbox-picked or\n * declared — this is the app-level store (same mount id every call, so \"which\n * space did I pick\" style state survives later grants; no need to open early and\n * keep the handle). An instance the host has **floored** below its app tier (the\n * generic-viewer containment, `TRUST_MODES_SPEC` §5) keeps that app-level store\n * unless exactly one origin it opened at runtime is less trusted than the app; in\n * that one case it gets a per-origin partition instead — a DIFFERENT filesystem,\n * chosen by the host, that changes when the loaded origin changes. That\n * partition is normally writable: it is tiered by that origin's own trust.\n *\n * **A floored instance's settings mount may open read-only; the call still\n * resolves.** A floor below the app's tier can make the store you get read-only,\n * and that is most often the app's own app-level store above, not the per-origin\n * partition. An ordinary app that holds a space shared more widely than itself is\n * floored this way, so \"my app is ordinary\" does not mean \"my settings mount is\n * writable\".\n *\n * The open is not refused when writing is forbidden. You get a mount whose\n * descriptor is `mode: 'ro'`; any write through it fails with `EROFS`; and the\n * host shows its own notice explaining why. So check `mount.mode` on resolution\n * rather than treating this call as always-writable. A refloor mid-session ends\n * the app's realm and restarts it, so checking on each resolution covers that too.\n * Never surface an `EROFS` from a write as a fatal error: the app can still read,\n * and the remedy is the user's — revoking the widely-shared space in Settings →\n * App permissions.\n *\n * Which partition you get is still host-chosen and still changes with the loaded\n * origin. If your app can run floored and needs continuity across origins, keep\n * state per-mount (the returned `SandboxMount.id` tells you which partition you\n * are in).\n */\nexport const openSettings = async (): Promise<SandboxMount> => {\n  const mount = await settingsRequest<SandboxMount>('open');\n  // The host has already accepted the request and announced the mount, so this\n  // normally resolves on the initial replay. Bounded anyway: an unbounded wait\n  // here turns any delivery failure into a promise that never settles, and every\n  // caller of `openSettings()` is doing it to reach durable state — so the app\n  // just quietly loses that state with nothing to report.\n  return waitForMount({ id: mount.id ?? mount.path }, SETTINGS_MOUNT_TIMEOUT_MS);\n};\n\n/** How long `openSettings()` waits for the host to deliver the mount it just\n *  agreed to create. Generous — this is a hang-breaker, not a latency budget. */\nconst SETTINGS_MOUNT_TIMEOUT_MS = 15_000;\n\n/**\n * One-time SEED of this app's settings from the parent it declares as `forkOf`\n * (its `package.json` `immediately.run.forkOf`) — so a fork inherits your\n * preferences from the original app (UI_AS_APPS_SPEC §3.4). The host asks the user\n * to confirm (a full consent when the apps have different owners, a light confirm\n * when the same owner publishes both) and copies the parent's settings into this\n * app's own subdir, skipping any file you already have. Non-throwing: resolves\n * `{ ok:false, code }` on decline (`cancelled`), no declared parent (`forbidden`),\n * or signed-out (`auth-required`). After `{ ok:true }`, read {@link openSettings}.\n * Capability: baseline `settings:fork`.\n */\nexport const importSettingsFromParent = async (): Promise<\n  { ok: true; copied: number } | { ok: false; code: string }\n> => {\n  try {\n    const data = await settingsRequest<{ copied: number }>('importFromParent');\n    return { ok: true, copied: data.copied };\n  } catch (e) {\n    return { ok: false, code: (e as SpaceError).code ?? 'unknown' };\n  }\n};\n\n/**\n * Mount ANOTHER app's per-user settings by its `appKey` — the elevated \"file\n * commander\" surface. Rejects `forbidden` unless this app holds the first-party-\n * only `settings:all` capability. Most apps want {@link openSettings} instead.\n */\nexport const openSettingsOf = async (appKey: string): Promise<SandboxMount> => {\n  const mount = await settingsRequest<SandboxMount>('openOf', { appKey });\n  return waitForMount({ id: mount.id ?? mount.path });\n};\n\n/**\n * List every app that has per-user settings — the elevated \"file commander\"\n * enumeration. Pair with {@link openSettingsOf} to mount any of them. Rejects\n * `forbidden` unless this app holds the first-party-only `settings:all`.\n */\nexport const listSettingsApps = (): Promise<string[]> => settingsRequest<string[]>('list');\n\n// ---------------------------------------------------------------------------\n// Device-local store — the per-app, device-local, IndexedDB-backed filesystem\n// (FILESYSTEM_SPEC §2.8). The distinction from `settings:` is durability, stated\n// to the app via the mount's `type: 'localstore'`, never a guess.\n// ---------------------------------------------------------------------------\n\n// Issue a `protocol-localstore` request, unwrapping {ok,data} and throwing a coded refusal\n// on failure (mirrors `settingsRequest`; a `CodedRefusalError`, not a `SpaceError`).\nconst localStoreRequest = async <T = unknown>(method: string, query: Record<string, unknown> = {}): Promise<T> => {\n  const res = (await protocolRequest(SCHEMES[PROTOCOL_LOCALSTORE], method, [query])) as SpaceResult;\n  throwOnRefusal(res, 'localstore request failed');\n  return res.data as T;\n};\n\n/**\n * Mount this app's **device-local** store — a private, per-device, IndexedDB-backed\n * filesystem, NOT synced (unlike {@link openSettings}). The cheap, throwaway-able\n * home for a cache, a draft, a scroll position, a checkpoint; the wrong home for\n * anything the user would mourn (the browser may evict it under storage pressure,\n * and the docs say so). Read/write it through `fs` at the returned mount's `path`,\n * with `type: 'localstore'`.\n *\n * Isolation is the store itself, keyed on the app's `appKey` — an app can never\n * name another app's local store, there is deliberately no `openOf` sibling, and\n * nothing written here is synced. Capability: baseline `storage:local` (no consent\n * prompt). Rejects with a {@link SpaceError}: `auth-required` when signed out,\n * `forbidden` when the capability is absent. A quota/external failure surfaces the\n * underlying error unchanged, so an app can tell \"the browser evicted me\" from\n * \"I never wrote anything\".\n *\n * **A floored instance's local store may open read-only; the call still\n * resolves.** The same degrade {@link openSettings} documents applies here: when\n * the host has floored the instance below its app tier, the store may be announced\n * `mode: 'ro'`, writes through it fail `EROFS`, and the host shows its own notice.\n * Check the mount's `mode` as you would a settings mount, and never surface that\n * `EROFS` as fatal — but do not treat a failed write as harmless: this store holds\n * drafts and checkpoints too, so tell the user their save did not happen rather\n * than swallowing it.\n */\nexport const openLocalStore = async (): Promise<SandboxMount> => {\n  const mount = await localStoreRequest<SandboxMount>('open');\n  // The host has already accepted the request and announced the mount, so this\n  // normally resolves on the initial replay. Bounded anyway, for the same reason\n  // `openSettings()` bounds its wait: an unbounded wait turns any delivery failure\n  // into a promise that never settles, and the caller reached for durable state.\n  return waitForMount({ id: mount.id ?? mount.path }, LOCALSTORE_MOUNT_TIMEOUT_MS);\n};\n\n/** How long `openLocalStore()` waits for the host to deliver the mount it just\n *  agreed to create. Generous — this is a hang-breaker, not a latency budget. */\nconst LOCALSTORE_MOUNT_TIMEOUT_MS = 15_000;\n\n/** Create a brand-new, empty platform-hosted space, granted to THIS app in full\n *  (read-write) — the user's create consent is consent for the app to create\n *  storage for itself, and the host records the same durable grant the\n *  {@link requestMount} powerbox would. So the returned mount can be re-opened\n *  later with {@link mountSpace} / {@link mount} (`space:<id>`) with no prompt —\n *  on the next load, in another tab, after sign-out/sign-in — until the user\n *  revokes the grant in their grants surface, after which `mount` answers\n *  `forbidden`. Other apps get nothing: they still reach the space only through\n *  the powerbox. (Before site-main R3-406 no grant was recorded and the space\n *  could only be re-found via the powerbox.) */\nexport const createSpace = (opts: { name?: string } = {}): Promise<SandboxMount> =>\n  requestMountInternal('create', opts);\n\n/** Release a mounted space (stops its listener on the host). */\nexport const unmountSpace = async (query: { spaceId: string }): Promise<void> => {\n  await request('unmount', query);\n};\n\n// ---------------------------------------------------------------------------\n// Space management (the space-manager app) — UI_AS_APPS_SPEC §5.2. These are\n// ELEVATED: enumerating all the user's spaces is `spaces:user`; mutating\n// membership (share/unshare/setRole) and resolving handles is `spaces:admin`.\n// The host enforces the owner-lockout invariant (a space always keeps an owner,\n// T41) and rate-limits handle lookups (L1); the OAuth/identity token never\n// crosses to the app.\n//\n// The request verbs above (invite inbox included) are generated from the\n// descriptor set; what remains hand-written here is the live invitations\n// channel (FILE_SHARING §6.4/§9.8): the host pushes the caller's current\n// invitations on change and replays on register-frame; gated `spaces:user`.\n// So an invite that arrives (or an accepted/declined one leaving) reflects\n// within one snapshot — no poll. Mirrors the host's\n// `invitations`/`request-invitations` wiring.\nconst invitesChannel = createPushChannel<Invite[]>({\n  pushType: INVITATIONS,\n  requestType: REQUEST_INVITATIONS,\n  initial: [],\n  parse: (msg) => (Array.isArray(msg.invites) ? (msg.invites as Invite[]) : undefined),\n});\n\n/** The caller's current invitations (`spaces:user`). One-off read; use\n *  {@link onInvitesChange}/{@link useInvites} to react live. */\nexport const getInvites = (): Invite[] => invitesChannel.get();\n\n/** Subscribe to invitation-inbox changes (arrived / accepted / declined). Invoked\n *  immediately with the current list, then on every change. Returns an unsubscribe. */\nexport const onInvitesChange = (listener: (invites: Invite[]) => void): (() => void) =>\n  invitesChannel.onChange(listener);\n\n/** React hook returning the caller's live invitation inbox, re-rendering on change\n *  (the space-manager Invitations inbox, §9.8). */\nexport const useInvites = (): Invite[] => invitesChannel.use();\n\n// ---------------------------------------------------------------------------\n// The space keyring (REALTIME_MESSAGING_SPEC §6.1, R3-633f). Hand-written on\n// purpose, and NOT moved into the generated family: the generated wrappers\n// return the wire payload as typed, while this boundary must PROJECT — a host\n// reply that (wrongly) carried a private half (a `d` field) is never\n// propagated, because the type is the boundary and the projection is the\n// proof (§16's must-establish row: \"a member's space private key is never\n// returned to an app sandbox\"). Both calls are `spaces:user` (§6.5(d): public\n// halves only — no new capability).\n\n/** One member's published space key — the PUBLIC half only. The ECDH P-256\n *  public JWK carries exactly `kty`/`crv`/`x`/`y`; there is no field for the\n *  private scalar anywhere in this type (and none named `d`), so the shape\n *  cannot carry one. */\nexport interface PublishedSpaceKey {\n  /** The member the key belongs to. */\n  uid: string;\n  /** The key id (write-once; rotation appends a new kid). */\n  kid: string;\n  /** The public JWK (four fields, no `d`). */\n  pub: { kty: string; crv: string; x: string; y: string };\n  /** The algorithm label (see the host's SPACE_KEY_ALG_LABEL). */\n  alg: string;\n  /** Epoch milliseconds when the key was published. */\n  addedAt: number;\n}\n\n/** Publish the caller's own space key (REALTIME_MESSAGING §6.1) — minted at join\n *  time by the host already; this call is the explicit retry/self-heal an app can\n *  offer. Idempotent: a member who has published resolves the existing kid with\n *  `created: false`. The private half is sealed under the member's passkey-derived\n *  KEK host-side and never crosses this boundary. Rejects with a typed refusal:\n *  `cancelled` (the passkey prompt was dismissed), `unsupported` (the platform\n *  cannot seal here), `forbidden` (not a member), `auth-required` when signed out. */\nexport const publishSpaceKey = async (spaceId: string): Promise<{ kid: string; created: boolean }> => {\n  // `invoke`, not the local `request` helper: the wire-shape gate\n  // (check-protocol-snapshot) extracts the catalog front door's call sites, and\n  // a helper call is invisible to it — the published contract and this source\n  // must agree byte-for-byte. Same envelope unwrap + coded refusal, with one\n  // recorded difference: `request`'s throwOnRefusal coerces a NON-STRING refusal\n  // code/message to 'unknown'/a fallback, while catalog.ts's invoke assigns\n  // `res?.code ?? 'unknown'` unchecked (its pre-fold shape — protocolRefusal.ts's\n  // census). The wire sends strings; the difference is unreachable today.\n  const r = await invoke<{ ok: true; kid: string; created: boolean }>('spaces:publishSpaceKey', { spaceId });\n  return { kid: r.kid, created: r.created };\n};\n\n/** The published public halves of a space's members (REALTIME_MESSAGING §6.1) —\n *  readable by every member, refused `forbidden` for a non-member (the store read\n *  is the membership gate). Members who have not published are simply ABSENT\n *  (§6.2's fail-closed create reads that absence; the targeted probe is the\n *  optional `uid` form, which answers `not-found` for an unpublished member).\n *  The returned rows are PROJECTED to {@link PublishedSpaceKey}: a wire row\n *  carrying anything more (e.g. a `d` field) is not propagated. */\nexport const listSpaceKeys = async (spaceId: string, uid?: string): Promise<PublishedSpaceKey[]> => {\n  // One declared params type (never a conditional literal) so the wire-shape\n  // gate fingerprints `uid` as `string | undefined` — the published snapshot's\n  // recorded shape (sandbox-protocol 0.15.0). `invoke` here for the same reason\n  // as publishSpaceKey above (the gate extracts the catalog front door's call\n  // sites); the same invoke-vs-throwOnRefusal coercion note applies.\n  const params: { spaceId: string; uid?: string } = { spaceId };\n  if (uid !== undefined) params.uid = uid;\n  const rows = await invoke<Array<Record<string, unknown>>>('spaces:listSpaceKeys', params);\n  // Project, never coerce (the host store's own doctrine): the four public JWK\n  // fields are copied verbatim and EVERYTHING else is dropped — a row carrying a\n  // private half (`d`) does not propagate; a malformed row is the host's to\n  // reject upstream (its project() refuses one), never this layer's to repair.\n  return rows.map((row) => {\n    const pub = row.pub as PublishedSpaceKey['pub'];\n    return {\n      uid: row.uid as string,\n      kid: row.kid as string,\n      pub: { kty: pub.kty, crv: pub.crv, x: pub.x, y: pub.y },\n      alg: row.alg as string,\n      addedAt: row.addedAt as number,\n    };\n  });\n};\n"],"mappings":"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","names":["mount"]}