# Deno Runtime Signals & Policy Contract (v0.1-DRAFT) ## Purpose Define deterministic runtime evidence records and policy signals for Deno analyzer phase II (tasks DENO-26-009/010/011). The contract is offline-friendly, append-only, and compatible with Surface/Signals stores. ## Scope - Harnessed execution hook (`stella deno trace`) capturing module loads and permission grants during analysis. - Trace serialization for Worker/CLI/Offline Kit and AnalysisStore. - Policy signal keys consumed by Surface/Signals and Policy Engine. ## Event model - Encoding: NDJSON; each line is a UTF-8 JSON object sorted by key when written. - Path handling: absolute paths are converted to analyzer-relative paths; each relative path also emits `path_sha256` (lowercase hex) to proof without leaking paths. - Timestamps: ISO-8601 UTC with millisecond precision; no local time. ### Event types ```jsonc { "type": "deno.module.load", // required "ts": "2025-11-17T12:00:00.123Z", // required "module": { "specifier": "file:///src/app/main.ts", // original "normalized": "app/main.ts", "path_sha256": "..." }, "reason": "dynamic-import", // static-import | dynamic-import | npm | cache | bundle "permissions": ["fs", "net"], // granted at time of load "origin": "https://deno.land/x/std@0.208.0/http/server.ts" // optional for remote/npm } ``` ```jsonc { "type": "deno.permission.use", "ts": "2025-11-17T12:00:01.234Z", "permission": "ffi", // fs|net|env|ffi|process|crypto|worker "module": { "normalized": "native/mod.ts", "path_sha256": "..." }, "details": "Deno.dlopen" // short reason code } ``` ```jsonc { "type": "deno.npm.resolution", "ts": "2025-11-17T12:00:02.100Z", "specifier": "npm:chalk@5", "package": "chalk", "version": "5.3.0", "resolved": "file:///cache/npm/registry.npmjs.org/chalk/5.3.0", "exists": true } ``` ```jsonc { "type": "deno.wasm.load", "ts": "2025-11-17T12:00:03.000Z", "module": { "normalized": "pkg/module.wasm", "path_sha256": "..." }, "importer": "app/main.ts", "reason": "dynamic-import" } ``` ## Observation envelope (AnalysisStore) Key: `ScanAnalysisKeys.DenoObservationPayload` Payload fields: - `analyzerId`: `deno` - `kind`: `deno.runtime.v1` - `mediaType`: `application/x-ndjson` - `metadata` (map): - `deno.runtime.event_count` - `deno.runtime.permission_uses` - `deno.runtime.module_loads` - `deno.runtime.remote_origins` (comma-separated, sorted) - `deno.runtime.permissions` (unique perms CSV) - `deno.runtime.npm_resolutions` - `deno.runtime.wasm_loads` - `deno.runtime.dynamic_imports` - `content`: gz-safe byte stream of NDJSON lines. ## Policy signal keys Emit into Surface/Signals (namespaced `surface.lang.deno.*`) derived from observation digest + static analyzer outputs: - `surface.lang.deno.permissions`: CSV of unique permissions seen (fs, net, env, ffi, process, crypto, worker). - `surface.lang.deno.remote_origins`: CSV of normalized remote origins from module loads/fetches. - `surface.lang.deno.npm_modules`: integer count of npm resolutions observed. - `surface.lang.deno.wasm_modules`: integer count of wasm loads. - `surface.lang.deno.dynamic_imports`: integer count of `deno.module.load` events where `reason=dynamic-import`. - `surface.lang.deno.capabilities`: CSV of capability reason codes from static analyzer (`builtin.*`) merged with runtime permissions. - `surface.lang.deno.module_loads`: integer count of module load events. - `surface.lang.deno.permission_uses`: integer count of permission use events. ## CLI / Worker contracts - CLI verb `stella deno trace --root ` writes `deno-runtime.ndjson` to output folder and prints observation hash. - Worker: when `DenoRuntimeCapture:true`, analyzer writes observation to AnalysisStore and links hash in layer metadata `deno.observation.hash` (already produced by static analyzer) and new `deno.runtime.hash`. ## Determinism and safety - No network fetches; trace operates on cached artifacts or harnessed execution with `--allow-all` disabled. Permissions recorded reflect requested grants; blanks treated as deny. - Paths always normalized to forward slashes; hashing uses full relative path bytes. - Redaction: no environment variable values or file contents persisted—only paths + hashes. ## Open follow-ups (to track in sprint) - Map NDJSON to AOC writer once runtime ingestion lands (LANG-11-003 analogue for Deno). - Add integration tests mirroring fixtures from DENO-26-008 with synthetic permission use and dynamic imports.