/** * Device adapter contract (realtime voice / desktop OS control) — 0.0.14. * * Contracts + deny-by-default policy ONLY. No vendor voice or desktop-control * implementation ships in 0.0.14 (demand-gated to 0.1.x). This module composes * over the existing `PermissionPolicy` / `RunLimits` / redactor seams; it adds * no second approval runtime and no device framework. Hosts implement * `DeviceAdapter`, resolve a policy, and admit sessions through the fail-closed * gate below. Conformance fixtures (denial/approval/stream-bounds/redaction) * live in `runDevicePolicyConformance` for future vendor adapters to run. */ import type { RunLimits } from "./contracts.js"; import { type SecretRedactor } from "./redaction.js"; /** Audio / screenshot / stream chunk: 1 MiB default / 8 MiB hard. */ export declare const DEFAULT_DEVICE_MAX_CHUNK_BYTES: number; export declare const HARD_DEVICE_MAX_CHUNK_BYTES: number; /** Concurrent device sessions per identity: 1 default / 4 hard. */ export declare const DEFAULT_DEVICE_MAX_CONCURRENT_SESSIONS = 1; export declare const HARD_DEVICE_MAX_CONCURRENT_SESSIONS = 4; export type DeviceKind = "voice" | "desktop-control"; export type DevicePolicyErrorCode = "ERR_PRISM_DEVICE_INPUT" | "ERR_PRISM_DEVICE_DISABLED" | "ERR_PRISM_DEVICE_APPROVAL" | "ERR_PRISM_DEVICE_SESSIONS" | "ERR_PRISM_DEVICE_CHUNK" | "ERR_PRISM_DEVICE_RUN_LIMITS"; export declare class DevicePolicyError extends Error { readonly code: DevicePolicyErrorCode; constructor(code: DevicePolicyErrorCode, message: string); } export interface DeviceStreamLimits { readonly maxChunkBytes?: number; readonly maxConcurrentSessions?: number; } /** * Host-declared device adapter. `enabled` is deny-by-default: a device is * admitted only when the host explicitly sets it `true` AND supplies a sandbox * AND (when `requireApproval`) explicit per-side-effect approval. */ export interface DeviceAdapter { readonly kind: DeviceKind; readonly enabled: boolean; readonly requireApproval: boolean; readonly limits?: DeviceStreamLimits; /** Host-owned sandbox identifier; admission fails closed without it. */ readonly sandbox?: string; /** Host-owned network/egress policy identifier. */ readonly network?: string; } export interface ResolvedDevicePolicy { readonly kind: DeviceKind; readonly enabled: boolean; readonly requireApproval: boolean; readonly maxChunkBytes: number; readonly maxConcurrentSessions: number; readonly sandbox?: string; readonly network?: string; /** Shared run accounting the device session must consume. */ readonly runLimits?: RunLimits; } export interface DevicePolicyOptions { readonly maxChunkBytes?: number; readonly maxConcurrentSessions?: number; readonly runLimits?: RunLimits; } export declare function resolveDevicePolicy(adapter: DeviceAdapter, options?: DevicePolicyOptions): ResolvedDevicePolicy; export interface DeviceAdmitRequest { /** Explicit host approval for this device side effect. */ readonly approved: boolean; /** Currently active device sessions for this identity. */ readonly activeSessions: number; } /** * Fail-closed admission gate. Denies unless the device is explicitly enabled, * sandboxed, approved (when required), under the concurrent-session budget, and * bound to shared run accounting. Side effects never replay after reconnect: * hosts must re-admit on every resume. */ export declare function assertDeviceAdmit(policy: ResolvedDevicePolicy, request: DeviceAdmitRequest): void; export interface DeviceChunkResult { readonly accepted: boolean; readonly bytes: number; /** Present when the chunk exceeded the stream bound and was dropped. */ readonly marker?: "dropped_oversize"; } /** Stream bound: oversize audio/screenshot/stream chunks are dropped with a marker, never forwarded. */ export declare function acceptDeviceChunk(policy: ResolvedDevicePolicy, bytes: number): DeviceChunkResult; /** Telemetry must be metadata-safe: apply the host redactor before any emit/persist. */ export declare function redactDeviceTelemetry(redactor: SecretRedactor | undefined, telemetry: T): T; export interface DeviceConformanceResult { readonly passed: readonly string[]; } /** * Conformance pair for future voice / desktop-control adapters. Runs the * deny-by-default fixtures (denial, approval, stream bounds, session budget, * run accounting, redaction) against a resolved policy and throws on any * regression. Tested in 0.0.14 via fixtures only. */ export declare function runDevicePolicyConformance(adapter: DeviceAdapter, options?: DevicePolicyOptions): DeviceConformanceResult;