import type { PluginOption } from 'vite'; export type MurasakiBuildTarget = 'darwin-arm64' | 'darwin-x64' | 'win32-x64' | 'win32-arm64' | 'linux-x64' | 'linux-arm64'; export type BundleResource = string | { from: string; to?: string; /** * Marks an app-owned executable sidecar for platform code signing. Required * for executable files shipped through `bundle.resources`; ordinary data * files must leave this false/undefined. */ executable?: boolean; }; export interface BundleConfig { /** Packages staged in the packaged app instead of compiled into server code. */ external?: string[]; /** JavaScript packages forced into the compiled server bundle. */ noExternal?: string[]; /** * Files/directories copied into packaged resources. Executable sidecars * must use the object form with `executable: true` so macOS/Windows signing * can seal them before the outer application artifact. */ resources?: BundleResource[]; } export interface WebviewProxyConfig { /** `http` uses HTTP CONNECT; `socks5` uses SOCKSv5. */ protocol: 'http' | 'socks5'; /** Hostname or IP literal only. URLs, credentials, and paths are rejected. */ host: string; /** TCP port from 1 through 65535. */ port: number; } /** `webview:download`-granted downloads' confinement directory. */ export interface WebviewDownloadsConfig { /** * Absolute directory downloads are confined to. Defaults to the OS user * Downloads folder when omitted (resolved natively per-OS). */ directory?: string; } /** Application-wide native WebView session and network configuration. */ export interface WebviewConfig { /** Complete custom User-Agent header value. */ userAgent?: string; /** Use a non-persistent private session instead of the app profile. */ incognito?: boolean; /** Unauthenticated proxy applied to every application WebView. */ proxy?: WebviewProxyConfig; /** Confines `webview:download`-granted downloads to a directory. */ downloads?: WebviewDownloadsConfig; /** * Trusted, project-root-relative JavaScript file paths injected into every * page before load (in this declaration order), via * `with_initialization_script_for_main_only`. Not capability-gated — * config is already fully trusted, unlike renderer-triggered commands. * Each file is bounded to 256 KiB and the combined total to 1 MiB, * enforced when the project is loaded (see `resolveInitScripts`). */ initScripts?: string[]; /** * Enables OS page-zoom hotkeys/gestures. Effective on Windows (WebView2) * only; no-op on macOS/Linux. */ hotkeysZoom?: boolean; } /** Local crash report capture (Node, native, and prod renderer domains). Murasaki never transmits these. */ export interface DiagnosticsConfig { /** * Capture uncaught exceptions/rejections (Node Main), native panics and * unexpected exits, and prod renderer errors as local crash report files. * Default `true`. */ crashReports?: boolean; /** Newest crash reports retained per app. Default 20; out-of-range values are clamped to 1-100. */ keepReports?: number; } export type MurasakiPluginCommand = 'dev' | 'build' | 'bundle'; export type MurasakiDeepReadonly = T extends (...args: never[]) => unknown ? T : T extends readonly (infer Item)[] ? readonly MurasakiDeepReadonly[] : T extends object ? { readonly [Key in keyof T]: MurasakiDeepReadonly; } : T; /** Immutable build configuration exposed to a trusted build-time plugin hook. */ export type MurasakiPluginHookConfig = MurasakiDeepReadonly>; export interface MurasakiPluginHookContext { readonly projectRoot: string; readonly config: MurasakiPluginHookConfig; readonly command: MurasakiPluginCommand; readonly target?: MurasakiBuildTarget; } export interface MurasakiPluginHooks { before?: (context: MurasakiPluginHookContext) => void | Promise; after?: (context: MurasakiPluginHookContext) => void | Promise; } /** * A trusted, build-time Murasaki extension. This is not a native Rust ABI or * a runtime plugin system: installing a plugin grants it the same privileges * as code in murasaki.config.ts. */ export interface MurasakiPlugin { /** Stable identifier used in diagnostics and duplicate detection. */ name: string; /** Vite plugins appended in declaration order after Murasaki's core plugins. */ vite?: PluginOption; /** Deterministic additions to the application's packaging configuration. */ bundle?: BundleConfig; /** Serial CLI lifecycle hooks. A rejection stops the command. */ hooks?: MurasakiPluginHooks; } /** Type-safe identity helper for authoring a trusted build-time plugin. */ export declare function defineMurasakiPlugin(plugin: MurasakiPlugin): MurasakiPlugin; export interface WindowConfig { title?: string; width?: number; height?: number; minWidth?: number; minHeight?: number; /** * Maximum inner width/height, in logical pixels. Setting only one axis is * rejected — provide both or neither. Must be greater than or equal to * `minWidth`/`minHeight` when both are configured. */ maxWidth?: number; maxHeight?: number; resizable?: boolean; transparent?: boolean; /** * Shows/hides the OS window chrome (titlebar + borders). Default `true`; * `false` produces a frameless window on every platform. Pair with * `useWindowDrag()` for a custom, draggable titlebar region. */ decorations?: boolean; /** * macOS only. `'hidden'` keeps the traffic-light buttons but hides the * title text and extends the WebView under the titlebar. Accepted (and * ignored) on Windows/Linux. */ titleBarStyle?: 'default' | 'hidden'; /** Initial borderless-fullscreen state. Exclusive fullscreen is not supported. */ fullscreen?: boolean; /** * macOS translucent window vibrancy. The native host automatically makes * the tao window and WebView transparent when a material is configured. */ vibrancy?: 'hud' | 'sidebar' | 'popover' | null; /** * Windows only — show the backend Node console window (useful for * CLI/debug logs). Default `false` (standalone GUI, no console). */ console?: boolean; /** Same-origin renderer route loaded into this window. Defaults to `/`. */ route?: string; /** Whether the window is initially visible. The primary window defaults to true. */ visible?: boolean; /** * Native renderer command allowlist. The primary window falls back to the * top-level list; a secondary window with no list remains deny-all. */ capabilities?: NativeCapabilityGrant[]; /** * Node/backend operations exposed to this renderer. Default deny-all. * Grants use stable resource IDs such as `main:src/backend.ts#read`, * `action:src/actions.ts#save`, `api:GET:/api/items/*`, `updater:*`, * `events:*`, or `diagnostics:renderer-error`. A single trailing `*` is a * prefix wildcard; no other wildcard placement is accepted. */ backendCapabilities?: BackendCapability[]; } /** A labelled value shown in the configurable native About panel. */ export interface AboutDetailConfig { label: string; value: string; /** Optional external destination opened when the value is activated. */ href?: string; } /** An external-action button shown at the bottom of the About panel. */ export interface AboutButtonConfig { label: string; href: string; } /** * Opts into Murasaki's configurable About panel. When omitted, each platform * keeps using its compact standard About dialog. */ export interface AboutConfig { /** Display name inside the panel. Defaults to `productName`. */ name?: string; /** Content width in logical pixels. Default 480; accepted range 360-900. */ width?: number; /** Content height in logical pixels. Auto-sized when omitted; range 320-1000. */ height?: number; /** Separate body paragraphs. Falls back to top-level `description`. */ paragraphs?: string[]; /** Vertical spacing between body paragraphs. Default 12; range 0-48. */ paragraphSpacing?: number; /** Label/value metadata rows such as Build and Commit. */ details?: AboutDetailConfig[]; /** Ordered external links rendered as native push buttons. */ buttons?: AboutButtonConfig[]; } /** A declaratively-created non-primary application window. */ export type SecondaryWindowConfig = Omit & { /** Create this window during application launch. Defaults to true. */ createOnLaunch?: boolean; }; /** Fully-resolved window declaration written to bundle metadata. */ export interface ResolvedWindowConfig extends WindowConfig { label: string; primary: boolean; route: string; visible: boolean; createOnLaunch: boolean; capabilities: NativeCapabilityGrant[]; backendCapabilities: BackendCapability[]; } /** A custom URL scheme registered by packaged macOS/Windows applications. */ export interface ProtocolConfig { /** RFC 3986 scheme, for example `my-app` in `my-app://open/42`. */ scheme: string; /** Human-readable handler name shown by the operating system. */ name?: string; } /** A document type the packaged application can open. */ export interface FileAssociationConfig { /** Extensions without a leading dot, for example `['note', 'mnote']`. */ extensions: string[]; /** Human-readable document type name. Defaults to ` document`. */ name?: string; /** Optional document description used by Windows. */ description?: string; /** macOS document role. Defaults to `viewer`. */ role?: 'viewer' | 'editor' | 'shell' | 'none'; /** Optional MIME type used in Windows registration metadata. */ mimeType?: string; } export interface MacOSCapturePermissionConfig { /** Text macOS shows in its consent dialog and System Settings. */ usageDescription: string; /** Ask as the native host starts. Prefer an in-context request when possible. */ requestOnLaunch?: boolean; } export interface MacOSPromptPermissionConfig { /** Ask as the native host starts. */ requestOnLaunch?: boolean; } /** * Core Location consent. Unlike `MacOSPromptPermissionConfig`, this requires * a purpose string (Core Location refuses to prompt without one). */ export interface MacOSLocationPermissionConfig { /** Text macOS shows in its consent dialog and System Settings. */ usageDescription: string; /** * `'whenInUse'` (default) writes only `NSLocationWhenInUseUsageDescription`. * `'always'` additionally writes `NSLocationAlwaysAndWhenInUseUsageDescription` * (Apple requires the when-in-use key present even for an always request) * and requests always-authorization instead of when-in-use. */ mode?: 'whenInUse' | 'always'; /** Ask as the native host starts. Prefer an in-context request when possible. */ requestOnLaunch?: boolean; } /** * A macOS TCC purpose string with no meaningful launch-time request: the OS * itself decides when to prompt (per-target automation, or the first actual * local-network access), so there is no `requestOnLaunch` — see * `appleEvents`/`localNetwork` below. */ export interface MacOSDeclarationOnlyPermissionConfig { /** Text macOS shows in its consent dialog and System Settings. */ usageDescription: string; } /** macOS TCC permissions supported by Murasaki's native host. */ export interface MacOSSystemPermissionsConfig { camera?: MacOSCapturePermissionConfig; microphone?: MacOSCapturePermissionConfig; screenRecording?: MacOSPromptPermissionConfig; accessibility?: MacOSPromptPermissionConfig; /** Listen Event access (global keyboard/mouse taps), e.g. for a global shortcut library. */ inputMonitoring?: MacOSPromptPermissionConfig; location?: MacOSLocationPermissionConfig; /** * Full Disk Access has no TCC request API — macOS only lets a user grant it * from System Settings. `requestOnLaunch` therefore means something * different here than for the other permissions above: if the heuristic * status isn't `granted`, the native host opens the Full Disk Access pane * in System Settings instead of showing an in-app consent prompt. */ fullDiskAccess?: MacOSPromptPermissionConfig; /** Photos library (read-write). Writes `NSPhotoLibraryUsageDescription`. */ photos?: MacOSCapturePermissionConfig; /** Writes `NSContactsUsageDescription`. */ contacts?: MacOSCapturePermissionConfig; /** * Calendar events (EventKit). Writes `NSCalendarsUsageDescription` and, * since the native host's launch-time request uses the macOS 14+ full-access * API when running on 14+ (falling back to the deprecated pre-14 API * otherwise), also writes `NSCalendarsFullAccessUsageDescription` so a * single build stays correct on both. */ calendar?: MacOSCapturePermissionConfig; /** * Reminders (EventKit). Writes `NSRemindersUsageDescription` and (see * `calendar` above for why) `NSRemindersFullAccessUsageDescription`. */ reminders?: MacOSCapturePermissionConfig; /** Writes `NSSpeechRecognitionUsageDescription`. */ speechRecognition?: MacOSCapturePermissionConfig; /** * CoreBluetooth has no explicit request call — consent is determined * implicitly the first time the native host stands up a Bluetooth central * manager. Writes `NSBluetoothAlwaysUsageDescription`. */ bluetooth?: MacOSCapturePermissionConfig; /** * Automation (sending Apple Events to another app). Writes * `NSAppleEventsUsageDescription`. Declaration-only: consent is granted per * TARGET app and only resolvable at send time, so there is no generic * `status()`/`requestOnLaunch` — a runtime `systemPermission.request('appleEvents')` * call only opens System Settings' Automation pane as guidance (like * `fullDiskAccess`) and `status()` always reports `unknown`. */ appleEvents?: MacOSDeclarationOnlyPermissionConfig; /** * Writes `NSLocalNetworkUsageDescription`. Declaration-only: macOS has no * query/request API at all for this — it prompts automatically the first * time the app actually attempts local-network traffic. `status()`/ * `request()` both always report `unknown`. */ localNetwork?: MacOSDeclarationOnlyPermissionConfig; } /** Host-OS consent declarations. Separate from renderer native capabilities. */ export interface SystemPermissionsConfig { macOS?: MacOSSystemPermissionsConfig; } /** Windows Authenticode settings used by `bundle --sign` and `installer --sign`. */ export interface WindowsSigningConfig { /** PFX/P12 certificate file. The optional password is read only from * `MURASAKI_WINDOWS_CERTIFICATE_PASSWORD`, never from this config. */ certificateFile?: string; /** Subject-name selector for a certificate already imported into the Windows `My` store. */ certificateSubjectName?: string; /** 40-character SHA-1 thumbprint selector for a certificate in the Windows `My` store. */ certificateSha1?: string; /** Certificate-store scope. Defaults to the current user's store. */ certificateStore?: 'currentUser' | 'localMachine'; /** RFC 3161 timestamp URL. `false` disables timestamping. Defaults to the * Microsoft Artifact Signing timestamp service for Artifact Signing and * DigiCert's timestamp service otherwise. */ timestampUrl?: string | false; /** Explicit path to `signtool.exe`. Normally auto-detected from PATH or the Windows SDK. */ signToolPath?: string; /** Microsoft Artifact Signing (formerly Trusted Signing) SignTool provider. * Authentication remains outside config (Azure CLI, workload identity, or managed identity). */ artifactSigning?: { /** Path to `Azure.CodeSigning.Dlib.dll`. */ dlib: string; /** Path to Artifact Signing's non-secret account/profile metadata JSON. */ metadata: string; }; } /** Linux GPG signing settings used by `bundle --sign` and `installer --sign`. */ export interface LinuxSigningConfig { /** `gpg --local-user` selector: key id, fingerprint, or email. */ gpgKey?: string; } /** * `true` enables the updater with every default inferred (GitHub repo from * `package.json#repository`, public key from `.murasaki/update-key.pub`, * stable channel, 6h re-check) — a complete, working config for a normal OSS * app. `false`/omitted disables it entirely. The object form only needs to * override what doesn't fit those defaults. * * There is deliberately no `provider` field — GitHub vs. self-hosted is * inferred from whether `repo` or `endpoint` is set (see `resolveUpdater`), * so it can't drift out of sync with the rest of the config. */ export type UpdaterConfig = boolean | { /** GitHub "owner/repo". Defaults to `repository` in package.json. */ repo?: string; /** * Self-hosted manifest URL (points at latest.json). Mutually exclusive * with `repo`. Must be `https:` — `http:` is only accepted for * loopback hosts (`127.0.0.1`, `localhost`, `[::1]`), for local * testing. Enforced here and again at fetch time in the runtime * engine. */ endpoint?: string; /** Release channel. Default 'stable' (GitHub: ignores prereleases). */ channel?: string; /** Check once at launch. Default true. */ checkOnStart?: boolean; /** Re-check on a timer, e.g. '6h'. `false` disables. Default '6h'. */ checkInterval?: string | false; /** Ed25519 public key (base64, raw 32 bytes). Defaults to .murasaki/update-key.pub. */ publicKey?: string; /** * Additional pinned Ed25519 public keys (base64, raw 32 bytes each; * at most 4) for key rotation. Merged with `publicKey` into one * deduplicated pinned set — verification tries every pinned key * until one succeeds. See the auto-update guide's rotation runbook. */ publicKeys?: string[]; /** * Maximum accepted age, in days, of a manifest's `generatedAt` * timestamp — an anti-freeze/replay guard: a manifest older than this * is rejected outright. Default 90, minimum 1. */ maxManifestAgeDays?: number; /** * Compatibility escape hatch for manifests created before `generatedAt` * existed. Default false: production rejects a missing timestamp because * an old, still-validly-signed manifest can otherwise be replayed. */ allowLegacyManifestsWithoutGeneratedAt?: boolean; }; /** The fully-resolved shape `resolveUpdater()` produces from a `UpdaterConfig`. */ export interface ResolvedUpdater { /** Absolute URL of latest.json. Derived from repo or endpoint. */ manifestUrl: string; /** base64 raw-32-byte Ed25519 public key — the primary pinned key (back-compat; also `publicKeys[0]`). */ publicKey: string; /** Every pinned Ed25519 public key (base64 raw 32 bytes), deduplicated — the union of `publicKey` and `publicKeys`. Verification tries each until one succeeds. */ publicKeys: string[]; channel: string; checkOnStart: boolean; /** milliseconds, or false */ checkIntervalMs: number | false; /** Maximum accepted age, in days, of a manifest's `generatedAt`. */ maxManifestAgeDays: number; /** Whether a signed legacy manifest may omit `generatedAt`. */ allowLegacyManifestsWithoutGeneratedAt: boolean; } /** * `resolveUpdater()` — which resolves a `UpdaterConfig` down to a * `ResolvedUpdater` per contract §3 — lives in `resolve-updater.ts`, not * here. It does filesystem/env I/O (reads `package.json`, * `.murasaki/update-key.pub`), and this module must stay free of any Node * builtin imports: `index.ts`'s client-facing barrel re-exports * `defineConfig`/`UpdaterConfig` from here, so anything this file imports * is reachable from a browser bundle. */ export interface MurasakiConfig { appId: string; productName: string; version?: string; /** Short description shown in the native "About " panel. */ description?: string; /** Copyright notice shown in the native "About " panel. */ copyright?: string; /** Homepage URL shown in the native "About " panel. */ homepage?: string; /** Author names shown in the native "About " panel (Windows/Linux only). */ authors?: string[]; /** Optional custom About panel layout, details, size, and external buttons. */ about?: AboutConfig; window?: WindowConfig; /** * Declarative secondary windows keyed by their stable native label. * `main` is reserved for the primary `window` declaration. */ windows?: Record; /** * Native commands exposed to trusted renderer code through `murasaki/native`. * Default is deny-all; grant only the capabilities the app uses. */ capabilities?: NativeCapabilityGrant[]; /** Primary-window backend grants. Secondary windows remain deny-all unless declared. */ backendCapabilities?: BackendCapability[]; /** * Host operating-system permissions. On macOS, camera/microphone usage * descriptions are embedded into Info.plist and selected permissions can * be requested at launch. Windows desktop consent remains usage-driven. */ systemPermissions?: SystemPermissionsConfig; /** Long-lived Node main process (`src/main.ts` by default when present). */ main?: false | { /** Entry relative to the project root. Default `src/main.ts`. */ entry?: string; /** End-to-end limit for `beforeQuit` plus `shutdown` before host exit. Default 10s. */ shutdownTimeoutMs?: number; }; /** Production packaging for Node-side code and non-code assets. */ bundle?: BundleConfig; /** Trusted build-time extensions. Plugin objects are never written to app metadata. */ plugins?: MurasakiPlugin[]; /** Application-wide native WebView session and network settings. */ webview?: WebviewConfig; /** Client/server build orchestration and public client environment prefixes. */ build?: { /** Command run before the client and Node bundles (for workspace packages, codegen, etc.). */ before?: string; /** Variables with these prefixes may be embedded in renderer code. Default `MURASAKI_PUBLIC_`. */ envPrefix?: string[]; }; /** Local crash report capture. See `DiagnosticsConfig`. */ diagnostics?: DiagnosticsConfig; /** Renderer security policy applied to framework- and user-owned HTML. */ security?: { /** * Content Security Policy injected as a single `` tag. * A string completely replaces Murasaki's environment-specific default; * `false` opts out of framework injection. A user-owned CSP meta tag is * normalized to the start of ``; setting both sources is an error. */ csp?: string | false; }; /** * Auto-update config. `true` is a complete, working setup for a normal OSS * app (GitHub repo inferred from `package.json`, public key from * `.murasaki/update-key.pub`). Enabling it also grants the primary renderer * `app:quit` for the verified restart handshake. See * `UpdaterConfig`/`resolveUpdater`. */ updater?: UpdaterConfig; /** * BCP-47 UI languages your app supports, e.g. ['en', 'ja']. Feeds the macOS * bundle's CFBundleLocalizations (so macOS localizes its injected menus and * standard dialogs) and constrains murasaki's native default menu: it follows * the system language when that language is in this list, otherwise falls back * to the first entry. Defaults to every language murasaki ships menu * translations for (en, ja, zh-Hans, ko, es, fr, de). */ locales?: string[]; /** Vite server port during `murasaki dev`. Defaults to 5178. */ devPort?: number; /** Build targets. Defaults to the host platform. */ targets?: MurasakiBuildTarget[]; /** * Square app-icon source (PNG; 1024px recommended). On macOS with full * Xcode installed, Murasaki compiles an AppIcon asset catalog so the OS * applies the current platform mask and appearances. A legacy `.icns` is * retained for older macOS/tooling; Windows/Linux assets are generated from * the same source. */ icon?: string; /** * Custom URL schemes registered by packaged macOS apps and Windows * installers. Open requests are delivered to `defineMain({ openRequested })`. */ protocols?: ProtocolConfig[]; /** * File extensions registered by packaged macOS apps and Windows installers. * Open requests are delivered to `defineMain({ openRequested })`. */ fileAssociations?: FileAssociationConfig[]; /** `murasaki installer` styling/options — macOS `.dmg` fields plus Windows `.exe`/`.msi` fields below. */ installer?: { /** Path (relative to project root) to a custom DMG background PNG. Overrides murasaki's default. */ background?: string; /** DMG window content size in points. Defaults to `width: 640, height: 420` to match the default background. */ window?: { width: number; height: number; }; /** Icon size in the DMG window. Default 128. */ iconSize?: number; /** Windows NSIS (`.exe`)/MSI (`.msi`) installer options. */ windows?: { /** * `'perUser'` installs to `%LOCALAPPDATA%\Programs\` with * no admin prompt (the NSIS installer's default — the friendlier * choice for an unsigned app). `'perMachine'` installs to * `Program Files` and requires admin. Built-in self-update is intentionally * incompatible with `perMachine`, because a non-elevated running app cannot * transactionally replace files under Program Files. Default `'perUser'`. */ installMode?: 'perUser' | 'perMachine'; /** Publisher name shown in the installer UI and Add/Remove Programs. Defaults to `authors.join(', ')`, then `copyright`, then `productName`. */ publisher?: string; /** * MSI UpgradeCode (a GUID) — must stay stable across versions for * upgrades to replace rather than duplicate-install. Defaults to a * GUID deterministically derived from `appId` (SHA-256-based), so you * normally don't need to set this yourself. */ upgradeCode?: string; /** * Installer/uninstaller icon (`.ico`). Applied to the NSIS installer * (`MUI_ICON`/`MUI_UNICON`) and the MSI's Add/Remove Programs entry * (`ARPPRODUCTICON`). Defaults to the app icon already generated from * top-level `icon` (`/resources/icon.ico`); if that's also * unset, both installers fall back to their own default icon. */ icon?: string; /** * Wizard header/banner image. Path (relative to project root) to a * BMP: 150×57 for the NSIS installer (`MUI_HEADERIMAGE_BITMAP`), 493×58 * for the MSI (`WixUIBannerBmp`) — the same file is handed to both, so * pick whichever size matters more, or provide one sized for the * installer you care about. Unset uses each installer's plain default. */ banner?: string; /** * Welcome/finish page side image. Path (relative to project root) to a * BMP: 164×314 for the NSIS installer (`MUI_WELCOMEFINISHPAGE_BITMAP`), * 493×312 for the MSI (`WixUIDialogBmp`) — same file handed to both. * Unset uses each installer's plain default. */ sidebar?: string; /** * License shown on a license-acceptance page. Path (relative to * project root) to a `.txt`/`.rtf` for the NSIS installer * (`MUI_PAGE_LICENSE` — added only when this is set) and a `.rtf` for * the MSI (`WixUILicenseRtf` — the MSI wizard always has a license * page, so a minimal placeholder is used when this is unset). */ license?: string; }; }; /** Code-signing. Murasaki signs with YOUR certificate/provider — it ships none. * Secrets (notarization credentials and PFX passwords) are read from env vars, never here. */ sign?: { /** Signing identity, e.g. "Developer ID Application: Name (TEAMID)". Defaults to * $MURASAKI_SIGN_IDENTITY, then the first "Developer ID Application" in your keychain. */ identity?: string; /** Path to a custom entitlements .plist for the main app executable. * Defaults to the minimum host entitlements derived from `systemPermissions`. * A configured path must exist; Murasaki never silently falls back. */ entitlements?: string; /** Path to a custom entitlements .plist for the bundled Node helper. * Defaults to the JIT/library-loading hardened-runtime permissions. * App Sandbox/inherit rights are rejected by the current architecture. */ helperEntitlements?: string; /** * Reserved for a future macOS App Sandbox process architecture. `true` is * currently rejected fail-closed: the bundled Node runtime requires * hardened-runtime/JIT entitlements that Apple does not permit on an * `app-sandbox` + `inherit` child. Default `false`. */ appSandbox?: boolean; /** Windows Authenticode signing for the application executable, portable ZIP payload, * NSIS setup executable, and MSI installer. */ windows?: WindowsSigningConfig; /** * Linux GPG signing identity for the `.AppImage` and `.deb` (and their * `SHA256SUMS`) produced by `bundle --sign`/`installer --sign` — a key * id, fingerprint, or email passed to `gpg --local-user`. * `$MURASAKI_GPG_KEY` overrides this at build time. The passphrase (if * the key has one) is never configured here — only read from * `$MURASAKI_GPG_PASSPHRASE`, falling back to gpg-agent when unset. */ linux?: LinuxSigningConfig; }; } /** Canonical runtime allowlist. Keep native permission dispatch in sync with this list. */ export declare const NATIVE_CAPABILITIES: readonly ["app:quit", "app:isElevated", "autostart:read", "autostart:write", "dialog:openFile", "dialog:openDirectory", "dialog:saveFile", "dialog:message", "clipboard:readText", "clipboard:writeText", "clipboard:readImage", "clipboard:writeImage", "clipboard:writeHtml", "menu:application", "menu:context", "notification:show", "shell:openExternal", "shell:showItemInFolder", "shell:trashItem", "shell:openPath", "shell:runElevated", "secureStorage:get", "secureStorage:set", "secureStorage:delete", "systemPermission:status", "systemPermission:request", "window:setTitle", "window:setSize", "window:minimize", "window:toggleMaximize", "window:show", "window:hide", "window:focus", "window:close", "window:setAlwaysOnTop", "window:isVisible", "window:isFocused", "window:isMaximized", "window:isMinimized", "window:getLabel", "window:open", "window:list", "window:manage", "globalShortcut:register", "globalShortcut:unregister", "tray:create", "tray:remove", "tray:setTooltip", "tray:setIcon", "tray:setMenu", "webview:download", "webview:dragDrop", "webview:zoom", "webview:print", "webview:readCookies", "webview:writeCookies"]; export type NativeCapability = (typeof NATIVE_CAPABILITIES)[number]; export interface ElevatedExecutionScope { /** Exact absolute path to the executable that may receive elevation. */ executable: string; /** Exact argv sequence. Omit for an executable that accepts no arguments. */ args?: string[]; } /** * Optional value-level constraints for a renderer-native permission. * * String grants remain backwards compatible and unrestricted. Use the object * form when a command accepts an external target so a compromised renderer * cannot turn one permission into arbitrary URL/path/window access. */ export interface NativeCapabilityScope { /** Exact URLs, or an absolute URL ending in `/**` for a path subtree. */ urls?: string[]; /** Exact absolute paths, or an absolute directory ending in `/**`. */ paths?: string[]; /** Exact executable + argv pairs accepted by `shell:runElevated`. */ executions?: ElevatedExecutionScope[]; /** Declarative native window labels. */ windows?: string[]; /** Host permissions that may be queried/requested. */ permissions?: SystemPermissionName[]; /** Exact secure-storage keys, or a key prefix ending in `*`. */ keys?: string[]; } export interface ScopedNativeCapability { permission: NativeCapability; /** Values this permission may operate on. Omitted means unrestricted. */ allow?: NativeCapabilityScope; /** Values denied before the allow list is considered. */ deny?: NativeCapabilityScope; } export type NativeCapabilityGrant = NativeCapability | ScopedNativeCapability; /** A renderer-to-Node/API authority resource ID. See `WindowConfig.backendCapabilities`. */ export type BackendCapability = string; /** Default end-to-end bound for Node main quit hooks. */ export declare const DEFAULT_MAIN_SHUTDOWN_TIMEOUT_MS = 10000; /** * Keep native-host shutdown waits bounded. Five minutes is deliberately well * above normal cleanup while still preventing a malformed config from * turning application exit into an effectively unbounded socket wait. */ export declare const MAX_MAIN_SHUTDOWN_TIMEOUT_MS = 300000; export declare function validateMainShutdownTimeoutMs(value: unknown): asserts value is number | undefined; export declare function defineConfig(config: MurasakiConfig): MurasakiConfig; /** * Runtime validation used by every CLI config loader as well as defineConfig(). * Config files are executable JavaScript, so their exports cannot be trusted to * have passed TypeScript checking (and users are not required to call * defineConfig()). */ export declare function validateConfig(config: unknown): asserts config is MurasakiConfig; /** @internal One normalized app-level value shared by dev and bundle metadata. * `initScripts` is deliberately excluded — its file contents are resolved by * the Node-only `resolveInitScripts` (see `cli/init-scripts.ts`), since this * module stays free of Node builtins (see the module doc comment above * `resolveUpdater`'s reference). */ export declare function resolveWebviewNetworkConfig(config: Pick): WebviewConfig | undefined; /** * Fully-resolved `diagnostics` defaults shared by dev (`main-process.ts` * passes `config.diagnostics` through as-is) and bundle metadata * (`cli/bundle.ts`'s `metaJson` writes this resolved shape so * `prod-server.mjs` and the native launcher never re-derive the defaults). * Unlike most numeric config here, an out-of-range `keepReports` is clamped * rather than rejected, matching `MainRuntimeOptions.diagnostics`'s runtime * behavior. */ export declare function resolveDiagnosticsConfig(config: Pick): { crashReports: boolean; keepReports: number; }; export type SystemPermissionName = 'camera' | 'microphone' | 'screenRecording' | 'accessibility' | 'inputMonitoring' | 'location' | 'fullDiskAccess' | 'photos' | 'contacts' | 'calendar' | 'reminders' | 'speechRecognition' | 'bluetooth' | 'appleEvents' | 'localNetwork'; /** * Resolve only the permissions explicitly opted into launch-time prompts. * `appleEvents`/`localNetwork` are declaration-only (see * `MacOSDeclarationOnlyPermissionConfig`) and have no `requestOnLaunch` field * at all, so they are never included here — only reachable through a runtime * `systemPermission.request()` call. */ export declare function resolveStartupSystemPermissions(config: Pick): SystemPermissionName[]; /** Shared runtime validation for defineConfig() and the Vite HTML transform. */ export declare function validateContentSecurityPolicy(value: unknown): asserts value is string | false | undefined; /** Validate and resolve primary and secondary declarative windows. */ export declare function resolveWindowDeclarations(config: Pick): ResolvedWindowConfig[]; /** Validate backend authority grants at the same trusted config boundary as native capabilities. */ export declare function resolveBackendCapabilities(value: BackendCapability[] | undefined, field?: string): BackendCapability[]; /** @internal Legacy permission-name projection consumed by native menus. */ export declare function capabilityPermissionNames(grants: readonly NativeCapabilityGrant[]): NativeCapability[]; /** @internal Versioned value-scope policy passed unchanged to the native host. */ export declare function serializeCapabilityPolicy(grants: readonly NativeCapabilityGrant[]): string; //# sourceMappingURL=config.d.ts.map