{
  "schemaVersion": 1,
  "frameworkVersion": "0.55.8",
  "features": [
    {
      "id": "file-routing",
      "category": "web-framework",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Page, layout, loading, error, not-found, route-group, single dynamic segments, and catch-all/optional catch-all page segments ([...slug], [[...slug]]) ship today.",
        "The router is client-side and does not provide the full Next.js App Router or React Server Components runtime."
      ],
      "apiSymbols": [
        "AppRouter",
        "Link",
        "useRouter",
        "usePathname",
        "useParams",
        "useSearchParams"
      ],
      "testEvidence": [
        "packages/murasaki/test/routing-catchall.test.mjs",
        "packages/murasaki/test/router-searchparams.test.mjs"
      ],
      "docsSlug": "/docs/guides/routing"
    },
    {
      "id": "server-actions",
      "category": "web-framework",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Actions execute in the bundled local Node runtime; they are not Next.js Server Actions and are not a remotely hosted RPC service.",
        "The versioned wire format is frozen at wire version 1: 1.x decoders always accept v1, explicit value and payload limits are contractual, and any future extension negotiates a higher version with v1 fallback."
      ],
      "apiSymbols": [
        "defineAction",
        "callAction",
        "useAction",
        "ActionState"
      ],
      "testEvidence": [
        "packages/murasaki/test/server-actions-wire.test.mjs",
        "packages/murasaki/test/wire.test.mjs"
      ],
      "docsSlug": "/docs/guides/server-actions"
    },
    {
      "id": "api-routes",
      "category": "web-framework",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Routes are served by the app-local Node process and are not intended to expose a public network service.",
        "The API surface follows Web Request and Response primitives but is not the complete Next.js Route Handler runtime."
      ],
      "apiSymbols": [
        "RouteHandler"
      ],
      "testEvidence": [
        "packages/murasaki/test/api-routes.test.mjs",
        "packages/murasaki/test/prod-server-http.test.mjs"
      ],
      "docsSlug": "/docs/guides/api-routes"
    },
    {
      "id": "navigation-middleware",
      "category": "web-framework",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Middleware runs in the renderer before client navigation and only receives the pathname and query string being navigated to.",
        "Request headers, response headers, cookies, edge execution, and matcher configuration are not available."
      ],
      "apiSymbols": [
        "Middleware",
        "MiddlewareContext",
        "MiddlewareResult"
      ],
      "testEvidence": [
        "packages/murasaki/test/router-searchparams.test.mjs"
      ],
      "docsSlug": "/docs/guides/middleware"
    },
    {
      "id": "route-metadata",
      "category": "web-framework",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Document title, description, favicon, and a small Open Graph subset are applied in the renderer; the title is additionally mirrored onto the native window title (best-effort, requires the window:setTitle capability).",
        "The metadata shape is not Next.js-compatible in full."
      ],
      "apiSymbols": [
        "Metadata",
        "GenerateMetadata",
        "applyMetadata"
      ],
      "testEvidence": [
        "packages/murasaki/test/react-metadata.test.mjs"
      ],
      "docsSlug": "/docs/guides/metadata"
    },
    {
      "id": "node-main-lifecycle",
      "category": "application-model",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "The src/main.ts lifecycle covers ready, cancellable beforeQuit, bounded shutdown, second-launch delivery, app paths, an AbortSignal, typed live events to renderers, and declared-window management in development and packaged apps.",
        "Configured secondary windows can be created and destroyed at runtime, and packaged hosts detect an unexpected bundled Node exit, discard unconfirmed update handoffs, tear down the backend process tree, and exit non-zero instead of leaving dead WebViews. Replayable lifecycle events, a public crash-restart policy, and health-check APIs are not implemented. On macOS, external Dock Quit and OS logout cannot guarantee cancellable beforeQuit through tao."
      ],
      "apiSymbols": [
        "murasaki/main",
        "defineMain",
        "emitMainEvent",
        "murasaki/main-client.subscribeMainEvent",
        "MainContext",
        "MainDefinition"
      ],
      "testEvidence": [
        "packages/murasaki/test/main-runtime.test.mjs",
        "packages/murasaki/test/main-events.test.mjs",
        "packages/murasaki/test/main-windows.test.mjs",
        "packages/murasaki/test/prod-server-http.test.mjs",
        "crates/native/src/launcher.rs"
      ],
      "docsSlug": "/docs/guides/node-main"
    },
    {
      "id": "native-window",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Configured secondary templates can be created, destroyed, and recreated from trusted Node Main, with generation-scoped lifecycle events; renderers remain limited to showing and managing live declared windows and cannot supply runtime URLs or capability policies.",
        "macOS hud, sidebar, and popover vibrancy materials are applied natively with transparent window/WebView composition; Windows and Linux ignore the macOS-only option.",
        "No parent/child or modal window relationship — tao has no cross-platform support for it, so every declared window is an independent top-level window.",
        "Only borderless fullscreen is supported; there is no exclusive/dedicated-video-mode fullscreen.",
        "titleBarStyle: 'hidden' is macOS only (transparent titlebar + hidden title + full-size content view); Windows and Linux accept and ignore it.",
        "getMonitors() geometry (position, size) is reported in physical pixels, not logical/CSS pixels."
      ],
      "apiSymbols": [
        "App",
        "WindowConfig",
        "SecondaryWindowConfig",
        "MainWindowState",
        "MainWindowLifecycleEvent",
        "murasaki/main.windows",
        "murasaki/native.appWindow",
        "murasaki/native.windows",
        "useWindowDrag"
      ],
      "testEvidence": [
        "packages/murasaki/test/native-api.test.mjs",
        "packages/murasaki/test/windows.test.mjs",
        "crates/native/src/window.rs"
      ],
      "docsSlug": "/docs/guides/windows"
    },
    {
      "id": "application-menu",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Native application menus ship on macOS, Windows, and Linux (GTK, via muda); replacement is process-global, restricted to the primary renderer, and requires menu:application plus the capabilities of privileged roles.",
        "Linux/Windows menus are a plain File/Edit/Window bar with no macOS-style bold app-name submenu; Edit items dispatch document.execCommand into the focused webview rather than riding a native responder chain. Missing role capabilities reject the whole replacement and keep the current menu."
      ],
      "apiSymbols": [
        "useAppMenu",
        "AppMenu",
        "AppMenuItemSpec"
      ],
      "testEvidence": [
        "crates/native/src/webview.rs",
        "crates/native/src/menu.rs"
      ],
      "docsSlug": "/docs/guides/app-menu"
    },
    {
      "id": "context-menu",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Native whole-window and scoped context menus ship on macOS, Windows, and Linux (GTK) behind menu:context; privileged native roles additionally require their matching capability.",
        "Menu IPC is bounded by payload, item-count, depth, and string limits. On Linux, undo/redo context-menu role items are silently omitted (an upstream muda/GTK limitation), and cut/copy/paste/selectAll are delivered by synthesizing X11 key events (requires libxdo; not available under Wayland without XWayland)."
      ],
      "apiSymbols": [
        "useContextMenu",
        "ContextMenuTrigger",
        "Action",
        "createActions"
      ],
      "testEvidence": [
        "crates/native/src/webview.rs",
        "crates/native/src/menu.rs"
      ],
      "docsSlug": "/docs/guides/context-menu"
    },
    {
      "id": "native-utilities",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Dialogs, clipboard, notifications, shell helpers, secure storage, and window controls are exposed to trusted renderer code through the same-origin native bridge and a per-window allowlist.",
        "Selected target-bearing commands support inline allow/deny scopes; other arguments remain command-level, and the native renderer API is not available directly inside src/main.ts.",
        "dialog.showMessage shows a native OS message box; clipboard also supports PNG image and HTML read/write, each bounded and independently permissioned; shell.trashItem and shell.openPath are path-scoped like shell.showItemInFolder, and shell.openPath rejects URLs and UNC/device paths.",
        "notification.show returns a generated id for local bookkeeping only; upstream notify-rust cannot deliver click/action callbacks on macOS or Windows, so the id never correlates with a later event.",
        "app.isElevated() is a read-only, capability-gated self-query on every platform (Windows: process token elevation state; macOS/Linux: effective root) and never fails.",
        "shell.runElevated({ executable, args? }) launches an existing absolute, non-traversing executable through the Windows UAC \"runas\" prompt: Windows-only, path-scoped like shell.openPath, never routed through a shell, and fire-and-forget (resolves once launched, not on exit). A user-declined prompt rejects with the distinct message \"elevation was cancelled by the user\"; every other platform rejects with an unsupported error."
      ],
      "apiSymbols": [
        "murasaki/native.dialog",
        "murasaki/native.clipboard",
        "murasaki/native.notification",
        "murasaki/native.shell",
        "murasaki/native.secureStorage",
        "murasaki/native.appWindow",
        "murasaki/native.app",
        "murasaki/native.windows"
      ],
      "testEvidence": [
        "packages/murasaki/test/native-api.test.mjs",
        "packages/murasaki/test/native-utilities.test.mjs",
        ".github/workflows/native-release.yml"
      ],
      "docsSlug": "/docs/guides/native-apis"
    },
    {
      "id": "login-autostart",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Per-user login startup is exposed as autostart.status/enable/disable behind separate read/write renderer capabilities and is rejected under murasaki dev so the Node development executable can never be registered accidentally.",
        "macOS uses a user LaunchAgent, Windows uses the current-user Run registry key, and Linux uses XDG Autostart. status reports enabled only when the stored registration exactly matches the current packaged executable; users and OS policy may still disable or remove a registration outside the app.",
        "The macOS LaunchAgent implementation is incompatible with App Sandbox builds; a separately signed login-item helper is not implemented yet."
      ],
      "apiSymbols": [
        "murasaki/native.autostart",
        "AutostartStatus"
      ],
      "testEvidence": [
        "crates/native/src/autostart.rs",
        "packages/murasaki/test/native-api.test.mjs",
        ".github/workflows/ci.yml"
      ],
      "docsSlug": "/docs/guides/native-apis"
    },
    {
      "id": "secure-storage",
      "category": "security",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "String values are stored in macOS Keychain, Windows Credential Manager, or (Linux) the freedesktop.org Secret Service D-Bus API under a SHA-256-derived appId/key namespace; missing keys return null, inputs and IPC are bounded, and there is no plaintext fallback on any platform.",
        "Linux stores values through the freedesktop.org Secret Service D-Bus API, provided by default on GNOME (gnome-keyring) and KDE (KWallet); if no provider is reachable every operation fails closed with a structured error — there is never a plaintext fallback.",
        "get, set, and delete have independent deny-by-default per-window capabilities, and grants support per-key allow/deny scoping (exact keys and trailing-prefix patterns) in addition to command-level grants; an unscoped grant still exposes every key in the app namespace to that window."
      ],
      "apiSymbols": [
        "murasaki/native.secureStorage"
      ],
      "testEvidence": [
        "crates/native/src/secure_storage.rs",
        "crates/native/src/webview.rs",
        "packages/murasaki/test/native-api.test.mjs",
        "packages/murasaki/test/windows.test.mjs"
      ],
      "docsSlug": "/docs/guides/native-apis"
    },
    {
      "id": "auto-update",
      "category": "distribution",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Signed manifests (with pinned-key rotation and a keyId hint), bounded downloads, SHA-256 payload verification, manifest freshness/anti-replay checks, staged percentage rollout, and staged handoff/relaunch are implemented for packaged macOS, Windows (x64 and arm64), and Linux AppImage apps.",
        "Windows self-update requires a per-user NSIS install; updater-enabled builds reject installMode=perMachine and skip MSI. MSI is available with the built-in updater disabled for system-managed major upgrades.",
        "A custom self-hosted endpoint must be https (loopback http is allowed for local testing only); delta/differential updates are not implemented. Linux self-update only works for the AppImage packaging format (the running .AppImage file is journal-swapped in place, relaunched with --appimage-extract-and-run); a .deb install or a manually-extracted AppDir has no file to swap, so check() reports a structured not-available reason (updates are managed by the system package manager) instead of an error."
      ],
      "apiSymbols": [
        "useUpdate",
        "UpdateButton",
        "UpdaterConfig",
        "UpdateState"
      ],
      "testEvidence": [
        "packages/murasaki/test/updater-hardening.test.mjs",
        "crates/native/src/updater.rs",
        ".github/workflows/app-package-win.yml",
        ".github/workflows/app-package-linux.yml"
      ],
      "docsSlug": "/docs/guides/auto-update"
    },
    {
      "id": "application-packaging",
      "category": "distribution",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "macOS .app/.dmg and Windows portable .zip, NSIS .exe, and WiX .msi outputs ship today. Installer creation fails closed when no platform installer is produced. Windows updater builds require per-user NSIS and skip MSI; MSI is generated only with the built-in updater disabled.",
        "Linux AppDir/AppImage/deb artifact assembly is implemented (murasaki bundle/installer --target linux-x64|linux-arm64), built from the same resource layout as the macOS/Windows bundles and requiring mksquashfs (squashfs-tools) on the build host; the native launcher now runs the produced AppImage/.deb end to end (window, webview, single-instance, deep links, self-update for AppImage). rpm packaging and repository metadata are not implemented; code signing is available via detached GPG signatures (see the code-signing feature). WiX is required for MSI and only runs on Windows."
      ],
      "apiSymbols": [
        "murasaki bundle",
        "murasaki installer"
      ],
      "testEvidence": [
        ".github/workflows/app-package-win.yml",
        ".github/workflows/app-package-linux.yml",
        ".github/workflows/ci.yml",
        "packages/murasaki/test/linux-bundle.test.mjs",
        "packages/murasaki/test/linux-deb.test.mjs"
      ],
      "docsSlug": "/docs/building/distribution"
    },
    {
      "id": "code-signing",
      "category": "distribution",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "partial"
      },
      "limitations": [
        "Developer ID signing and Apple notarization are wired for macOS when the developer supplies credentials.",
        "Windows Authenticode signs and verifies the application executable, portable ZIP payload, NSIS setup, and MSI through a developer-supplied PFX/store certificate or Microsoft Artifact Signing provider. Ad-hoc macOS signatures do not establish user trust.",
        "Linux: `murasaki installer --sign` produces detached, armored GPG signatures (<artifact>.sig) for the .AppImage, the .deb, and a combined SHA256SUMS, and opportunistically embeds a Debian-native signature via dpkg-sig when it is on PATH. The signing key is selected via $MURASAKI_GPG_KEY or sign.linux.gpgKey; the passphrase comes only from $MURASAKI_GPG_PASSPHRASE or the gpg-agent. There is no distro-repository trust-store or apt/dnf keyring integration, and no rpm."
      ],
      "apiSymbols": [
        "MurasakiConfig.sign",
        "WindowsSigningConfig",
        "murasaki bundle --sign",
        "murasaki installer --sign",
        "murasaki installer --notarize"
      ],
      "testEvidence": [
        "packages/murasaki/test/windows-signing.test.mjs"
      ],
      "docsSlug": "/docs/building/distribution"
    },
    {
      "id": "loopback-endpoint-protection",
      "category": "security",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Development and packaged privileged endpoints validate loopback Host, Origin, and Fetch Metadata, then require an HMAC-derived identity bound to the exact native window label and its deny-by-default backendCapabilities. Packaged identities also bind the native window generation: close revokes the live generation and recreate rotates the HMAC. The document-start bootstrap exits before defining credentials in subframes or documents outside the exact app loopback origin, including on Windows where WebView2 injects main-only scripts into frames. Static document responses expose no bearer credential; native-only lifecycle endpoints use a separate token unavailable to renderer JavaScript.",
        "The app server still binds a predictable loopback port range, so a local process can cause startup denial of service. On first launch Murasaki selects and persists one free private-range port; later collisions fail closed instead of moving the HTTP origin and stranding localStorage, IndexedDB, or cookies. Browser profiles are isolated by native window so same-origin Service Workers and shared storage cannot cross the label-bound backend authority boundary; XSS retains every grant belonging to its own window."
      ],
      "apiSymbols": [
        "MurasakiConfig.backendCapabilities",
        "WindowConfig.backendCapabilities",
        "BackendCapability"
      ],
      "testEvidence": [
        "packages/murasaki/src/runtime/window-auth.ts",
        "packages/murasaki/test/runtime-security.test.mjs",
        "packages/murasaki/test/prod-server-http.test.mjs",
        "crates/native/src/launcher.rs"
      ],
      "docsSlug": "/docs/building/security"
    },
    {
      "id": "content-security-policy",
      "category": "security",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Murasaki injects environment-specific default CSP into framework and user-owned HTML, supports a complete security.csp override or explicit opt-out, and normalizes a user-owned CSP tag to the beginning of head.",
        "The resolved policy is delivered by both the Content-Security-Policy response header (dev middleware and the packaged production server) and a meta tag from a single resolver, so header-only directives such as frame-ancestors 'none' are enforced; the meta tag carries the shareable subset with header-only directives (frame-ancestors, sandbox, report-uri, report-to) stripped. security.csp: false opts out of both delivery paths. CSP does not sanitize HTML or authorize Node functions, reporting endpoints are not configured by default, and inline styles remain enabled for compatibility."
      ],
      "apiSymbols": [
        "MurasakiConfig.security",
        "security.csp"
      ],
      "testEvidence": [
        "packages/murasaki/test/csp.test.mjs",
        "packages/murasaki/test/runtime-security.test.mjs",
        "packages/murasaki/test/prod-server-http.test.mjs",
        "packages/murasaki/src/vite-plugin/shell.ts"
      ],
      "docsSlug": "/docs/building/security"
    },
    {
      "id": "multi-window",
      "category": "application-model",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Windows must be declared in configuration. Secondary templates may opt out of launch-time creation and trusted Node Main can create, destroy, and recreate them; arbitrary runtime URLs, native policies, and undeclared labels are rejected.",
        "Secondary OS/self close hides for later reopening, while Node Main destroy releases native resources and increments the generation when recreated; the application menu remains process-global and primary-owned.",
        "Each native window has an isolated browser profile so Service Workers, SharedWorkers, cookies, and storage cannot inherit another window's backend authority. Secondary profiles persist on Windows/Linux and macOS 14+; macOS 11-13 uses a separate non-persistent WebKit store."
      ],
      "apiSymbols": [
        "MurasakiConfig.windows",
        "SecondaryWindowConfig",
        "WindowInfo",
        "murasaki/native.appWindow.getLabel",
        "murasaki/native.windows"
      ],
      "testEvidence": [
        "packages/murasaki/test/windows.test.mjs",
        "packages/murasaki/test/native-api.test.mjs",
        "crates/native/src/window.rs",
        "crates/native/src/launcher.rs",
        ".github/workflows/ci.yml"
      ],
      "docsSlug": "/docs/guides/windows"
    },
    {
      "id": "tray-and-global-shortcuts",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "partial"
      },
      "limitations": [
        "One process-wide macOS status item / Windows system-tray icon ships with tooltip, click events, native nested menus, menu-item events, and dynamic icon/menu replacement; the latest successful create replaces the previous owner.",
        "Linux trays use libappindicator and need an AppIndicator host (on GNOME, the AppIndicator/KStatusNotifierItem Shell extension); tray-menu clicks and dynamic icon/menu replacement work the same as macOS/Windows, but tray icon click/double-click events never fire — AppIndicator exposes no such signal, only \"show the attached menu\".",
        "macOS and Windows global shortcuts support bounded modifier-plus-known-key accelerators, explicit ids, owner-routed press events, same-process conflict detection, and automatic owner/shutdown cleanup behind separate register/unregister capabilities.",
        "Linux global shortcuts use the same accelerator/id model over X11 and require X11 or XWayland; a pure-Wayland session (no DISPLAY) returns a structured unsupported error instead of registering. Linux has no OS-reserved-shortcut list (unlike macOS/Windows), since that depends on the desktop environment.",
        "Shortcut availability still depends on OS-reserved bindings and other applications and requires packaged OS smoke testing."
      ],
      "apiSymbols": [
        "murasaki/native.tray",
        "TrayOptions",
        "TrayMenuItem",
        "TrayClickEvent",
        "murasaki/native.globalShortcut",
        "GlobalShortcutRegistration"
      ],
      "testEvidence": [
        "packages/murasaki/test/native-api.test.mjs",
        "crates/native/src/global_shortcut.rs",
        "crates/native/src/webview.rs",
        ".github/workflows/ci.yml"
      ],
      "docsSlug": "/docs/guides/native-apis"
    },
    {
      "id": "system-permissions",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "partial",
        "linux": "unsupported"
      },
      "limitations": [
        "Packaged macOS apps can declare usage descriptions and query/request consent, from a capability-gated renderer API and (for most kinds) an optional launch-time prompt, for camera, microphone, screen recording, accessibility, input monitoring, location, full disk access, photos, contacts, calendar, reminders, speech recognition, and Bluetooth. This covers thirteen request-capable kinds plus two declaration-only ones (appleEvents, localNetwork) below; all fifteen are macOS-only, since Windows/Linux have no OS-level equivalent of the app-scoped TCC prompts they represent.",
        "fullDiskAccess is guidance-only: macOS has no TCC request API for it, so `request()` only opens the Full Disk Access pane in System Settings (never claims a grant), and `status()` is a documented best-effort heuristic (reading a TCC-protected file) that can report `unknown` instead of a real answer.",
        "appleEvents and localNetwork are declaration-only: Murasaki writes their purpose string (NSAppleEventsUsageDescription/NSLocalNetworkUsageDescription) but there is no query API for either. appleEvents' `request()` only opens the Automation pane in System Settings as guidance (consent is per-target-app and only resolvable at send time); localNetwork's `status()`/`request()` are both static `unknown` no-ops since macOS prompts automatically on first actual local-network access. Neither has a `requestOnLaunch` config field.",
        "bluetooth has no explicit request call: CoreBluetooth determines consent implicitly the first time a central manager is instantiated. `status()` reads `CBManager.authorization`, a class property that needs no live manager instance; `request()` instantiates one (delegate-less, like `location`) purely to trigger that OS-side determination.",
        "calendar/reminders' launch-time and runtime `request()` use the macOS 14+ full-access EventKit API when the running system supports it, falling back to the deprecated pre-14 entity-type API otherwise (checked with NSProcessInfo at call time, not at build time), and Info.plist always carries both the legacy and 14+ full-access usage-description keys so one packaged build stays correct on both.",
        "location's `mode: 'always'` writes both `NSLocationWhenInUseUsageDescription` and `NSLocationAlwaysAndWhenInUseUsageDescription` to Info.plist and is read back from that same Info.plist key at request time, so it applies identically to `requestOnLaunch` and a runtime `systemPermission.request('location')` call without separate plumbing.",
        "Hardened-runtime signing separates main-app and bundled-Node entitlements. The main app derives the declared camera, microphone, location, photos, contacts, calendar/reminders, and Apple Events resource-access rights from `systemPermissions.macOS`; signed builds need these rights in addition to their Info.plist purpose strings. Bluetooth's device entitlement is App-Sandbox-only and speech recognition has no Hardened Runtime resource entitlement. Node alone gets JIT/unsigned-executable-memory/disabled-library-validation. Native add-ons get no executable entitlements, and app-owned executable bundle resources must be marked `executable: true` for inner-to-outer macOS/Windows signing. `sign.appSandbox: true` is rejected fail-closed because Apple's inherit-only helper rules are incompatible with the current bundled Node/JIT architecture. Custom `sign.entitlements` and `sign.helperEntitlements` files are used verbatim; missing or invalid configured files fail closed.",
        "Windows unpackaged desktop privacy consent is usage-driven rather than an app-scoped launch prompt, so these generic calls report unsupported there; Linux is not implemented. Development requests use the terminal/Node host identity and should be tested with a packaged app."
      ],
      "apiSymbols": [
        "MurasakiConfig.systemPermissions",
        "SystemPermissionsConfig",
        "MacOSSystemPermissionsConfig",
        "MacOSLocationPermissionConfig",
        "MacOSDeclarationOnlyPermissionConfig",
        "MurasakiConfig.sign.appSandbox",
        "MurasakiConfig.sign.entitlements",
        "MurasakiConfig.sign.helperEntitlements",
        "murasaki/native.systemPermission"
      ],
      "testEvidence": [
        "packages/murasaki/test/system-permissions.test.mjs",
        "crates/native/src/system_permission.rs"
      ],
      "docsSlug": "/docs/guides/native-apis"
    },
    {
      "id": "single-instance-and-deep-links",
      "category": "application-model",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Packaged macOS apps and installed Windows apps register declared URL schemes and file associations, preserve the per-user single-instance lock, and deliver normalized startup, second-instance, and system open requests to src/main.ts.",
        "Windows portable .zip and bare executable distributions do not register protocols or file associations automatically; registration is supplied by the NSIS and MSI installers. Linux preserves the same per-user single-instance lock and delivers cold-start argv (the %U/%F the .desktop Exec line expands to) and second-instance activation over the existing loopback channel; protocol/file-association MimeType entries are declared in the .desktop file (installed under usr/share/applications by the .deb, refreshed by update-desktop-database) but there is no OS-level registration step to verify for a manually-extracted AppImage/AppDir the way NSIS/MSI perform on Windows."
      ],
      "apiSymbols": [
        "ProtocolConfig",
        "FileAssociationConfig",
        "OpenRequestEvent",
        "OpenTarget",
        "MainDefinition.openRequested",
        "MainDefinition.secondInstance",
        "SecondInstanceEvent"
      ],
      "testEvidence": [
        "packages/murasaki/test/associations.test.mjs",
        "packages/murasaki/test/main-runtime.test.mjs",
        "packages/murasaki/test/prod-server-http.test.mjs",
        "crates/native/src/launcher.rs",
        ".github/workflows/app-package-linux.yml"
      ],
      "docsSlug": "/docs/guides/deep-links"
    },
    {
      "id": "capability-permissions",
      "category": "security",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Renderer native commands are deny-by-default and granted through a runtime-validated per-window capability allowlist; sender origin and command names are validated in Rust. Renderer-to-Node resources are separately deny-by-default through label-bound backendCapabilities.",
        "URL (including cookie origin/path), filesystem path, secure-storage key, target-window, and OS-permission scopes support explicit allow/deny rules; other native arguments remain command-level. Cookie domain overrides cannot escape the URL host. Backend resources support exact and trailing-prefix grants for Main exports, Server Actions, API methods/paths, updater routes, events, and diagnostics. Secondary windows intentionally inherit neither list, and privileged menu roles require their corresponding native capability."
      ],
      "apiSymbols": [
        "MurasakiConfig.capabilities",
        "WindowConfig.capabilities",
        "NativeCapability",
        "MurasakiConfig.backendCapabilities",
        "WindowConfig.backendCapabilities",
        "BackendCapability"
      ],
      "testEvidence": [
        "crates/native/src/webview.rs",
        "packages/murasaki/test/native-api.test.mjs",
        "packages/murasaki/test/windows.test.mjs",
        "packages/murasaki/test/runtime-security.test.mjs",
        "packages/murasaki/test/prod-server-http.test.mjs"
      ],
      "docsSlug": "/docs/building/security"
    },
    {
      "id": "diagnostics-and-logging",
      "category": "operations",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Node Main provides structured JSONL logging, bounded rotation, secret-looking field redaction, shutdown flushing, and opt-in bounded diagnostic reports with application/runtime metadata and log tails.",
        "Murasaki also captures versioned local crash reports across three domains: Node uncaughtException/unhandledRejection, native launcher panics and unexpected-exit metadata, and (production builds only) uncaught renderer errors/unhandled rejections, all bounded and redacted the same way as log fields and readable through MainContext.diagnostics.",
        "Crash reports are local JSON files only and are never transmitted by Murasaki; there is no minidump/native-symbolication support, no automatic upload, and renderer capture is a no-op under murasaki dev (the dev error overlay owns that UX instead). Wiring reports to a crash-reporting service remains an application responsibility."
      ],
      "apiSymbols": [
        "MainContext.log",
        "MainLogger",
        "createMainLogger",
        "DiagnosticReportOptions",
        "MainContext.diagnostics",
        "CrashDiagnosticsApi",
        "CrashReport",
        "CrashReportDomain",
        "CrashReportSummary",
        "MurasakiConfig.diagnostics",
        "DiagnosticsConfig"
      ],
      "testEvidence": [
        "packages/murasaki/test/main-logger.test.mjs",
        "packages/murasaki/test/main-runtime.test.mjs",
        "packages/murasaki/test/crash-diagnostics.test.mjs",
        "packages/murasaki/test/config-loader.test.mjs",
        "crates/native/src/launcher.rs"
      ],
      "docsSlug": "/docs/guides/node-main"
    },
    {
      "id": "webview-session-network",
      "category": "native-integration",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Application-wide custom User-Agent, non-persistent/incognito sessions, and bounded unauthenticated HTTP CONNECT or SOCKSv5 proxy endpoints are runtime-validated and passed to Wry for development and packaged macOS, Windows, and Linux WebViews.",
        "Browser profiles are isolated by native window. The primary retains the historical app profile; secondary profiles persist on Windows/Linux and macOS 14+, while macOS 11-13 uses isolated non-persistent stores. Cross-window cookie/storage/worker sharing is intentionally unsupported; apps should share durable state through Main/API handlers.",
        "macOS proxy configuration requires macOS 14+ and fails startup on older releases; Windows custom User-Agent requires WebView2 86.0.616.0+ and private mode requires 101.0.1210.39+, with older runtimes ignoring those settings. Per-window overrides and authenticated proxies are not supported.",
        "webview:download confines sanitized, collision-resolved downloads to a configured (or OS default) directory and reports start/completion events; there is no reliable id correlating a completed event with the started event it followed, and macOS never reports a completed download's path (an upstream WebKit limitation).",
        "webview:dragDrop reports file drag-and-drop events (dragover throttled to 20/sec) without ever blocking the OS default, so file inputs keep working regardless of the grant. webview.initScripts injects trusted, config-owned JavaScript before page load and is not capability-gated.",
        "webview:zoom bounds page zoom to 0.25-5.0 and is available on macOS 11+/iOS 14+ only; webview.hotkeysZoom (config, not a capability) enables OS zoom hotkeys/gestures on Windows only. webview:print opens the platform print dialog; there is no find-in-page API because Wry exposes none.",
        "webview:readCookies/webview:writeCookies expose bounded cookie read/set/delete and support structured URL scopes. Scoped reads require an explicit URL; writes are checked against the effective cookie path, and domain overrides must exactly match the URL host. The reserved legacy murasaki_runtime name is filtered out of reads and rejected from writes/deletes as defense in depth, although runtime authentication no longer relies on a cookie. deleteCookie matches by name, the URL host as domain, and the default / path only.",
        "Renderer camera, microphone, and geolocation Web APIs fail closed under a framework-owned Permissions-Policy header. Wry 0.55 has no cross-platform per-window permission callback, so these APIs cannot be enabled from config yet; use capability-checked native features instead."
      ],
      "apiSymbols": [
        "MurasakiConfig.webview",
        "WebviewConfig",
        "WebviewProxyConfig",
        "WebviewDownloadsConfig",
        "murasaki/native.webview",
        "murasaki.subscribeDownloads",
        "murasaki.subscribeFileDrops",
        "murasaki.useFileDrop"
      ],
      "testEvidence": [
        "packages/murasaki/test/webview-config.test.mjs",
        "packages/murasaki/test/webview-native-api.test.mjs",
        "packages/murasaki/test/webview-events.test.mjs",
        "crates/native/src/webview.rs",
        "crates/native/src/download.rs",
        "crates/native/src/launcher.rs",
        "examples/linux-parity-probe/src/lib/probeOrchestrator.ts"
      ],
      "docsSlug": "/docs/guides/webview"
    },
    {
      "id": "build-time-plugin-sdk",
      "category": "tooling",
      "status": "stable",
      "platforms": {
        "macos": "supported",
        "windows": "supported",
        "linux": "supported"
      },
      "limitations": [
        "Trusted build-time plugins can contribute Vite PluginOptions, deterministic bundle dependencies/resources, and serial dev/build/bundle lifecycle hooks with runtime-validated stable names.",
        "This is not a native Rust ABI, dynamic library loader, renderer/runtime plugin sandbox, or a permission boundary; plugin code has the same Node.js authority as murasaki.config.ts."
      ],
      "apiSymbols": [
        "defineMurasakiPlugin",
        "MurasakiPlugin",
        "MurasakiPluginHookContext",
        "MurasakiConfig.plugins"
      ],
      "testEvidence": [
        "packages/murasaki/test/plugin-sdk.test.mjs",
        "packages/murasaki/src/plugin-runtime.ts",
        "packages/murasaki/src/vite-plugin/index.ts"
      ],
      "docsSlug": "/docs/building/configuration"
    },
    {
      "id": "linux-distribution",
      "category": "distribution",
      "status": "stable",
      "platforms": {
        "macos": "unsupported",
        "windows": "unsupported",
        "linux": "supported"
      },
      "limitations": [
        "AppDir/AppImage/deb artifact assembly (see the application-packaging capability) and the native launcher runtime both work end to end: window/webview creation, single-instance locking, cold-start deep links (argv from the .desktop Exec line) and second-instance forwarding, graceful shutdown, and native crash reporting all run from the packaged AppImage or .deb, verified under Xvfb + a private D-Bus session in Docker and in app-package-linux.yml.",
        "AppImage self-update works (journaled single-file swap of the running .AppImage, relaunch via --appimage-extract-and-run, first-launch rollback on a failed health check); a .deb install or a bare/manually-extracted AppDir has no self-update (there is no single file to swap) and reports updates as managed by the system package manager instead. rpm packaging and repository metadata are not implemented; code signing is available via detached GPG signatures (see the code-signing feature)."
      ],
      "apiSymbols": [],
      "testEvidence": [
        "crates/native/src/launcher.rs",
        "crates/native/src/updater.rs",
        ".github/workflows/app-package-linux.yml",
        ".github/scripts/linux-installer-e2e.sh",
        ".github/scripts/linux-smoke-test.sh"
      ],
      "docsSlug": "/docs/core-concepts/platform-feature-status"
    }
  ]
}
