@i4ctime/q-ring 0.3.2 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/envelope.ts","../src/core/collapse.ts","../src/core/observer.ts","../src/core/entanglement.ts","../src/core/keyring.ts","../src/utils/hash.ts","../src/core/scope.ts","../src/core/hooks.ts","../src/utils/http-request.ts","../src/core/approval.ts","../src/core/provision.ts","../src/core/policy.ts","../src/core/tunnel.ts"],"sourcesContent":["/**\n * Quantum Envelope: the storage format for all q-ring secrets.\n *\n * Instead of storing raw strings, every secret is wrapped in an envelope\n * that carries quantum metadata: environment states (superposition),\n * TTL/expiry (decay), entanglement links, and access tracking (observer).\n */\n\nexport type Environment = string; // \"dev\" | \"staging\" | \"prod\" | custom\n\nexport interface EntanglementLink {\n /** Service name of the entangled scope */\n service: string;\n /** Key name in the entangled scope */\n key: string;\n}\n\nexport interface SecretMetadata {\n createdAt: string;\n updatedAt: string;\n /** ISO timestamp when this secret expires (quantum decay) */\n expiresAt?: string;\n /** TTL in seconds from creation/update */\n ttlSeconds?: number;\n /** Human-readable description */\n description?: string;\n /** Tags for organization */\n tags?: string[];\n /** Entanglement links to other secrets */\n entangled?: EntanglementLink[];\n /** Total number of times this secret has been read */\n accessCount: number;\n /** ISO timestamp of last read */\n lastAccessedAt?: string;\n /** Whether this secret is ephemeral (tunneling - not persisted to keyring) */\n ephemeral?: boolean;\n /** Format to use when auto-rotating (e.g. \"api-key\", \"password\", \"uuid\") */\n rotationFormat?: string;\n /** Prefix to use when auto-rotating api-key/token formats */\n rotationPrefix?: string;\n /** Provider name for liveness validation (e.g. \"openai\", \"stripe\", \"github\") */\n provider?: string;\n /** Custom validation URL for generic HTTP provider */\n validationUrl?: string;\n /** Whether reading this secret via MCP requires explicit user approval */\n requiresApproval?: boolean;\n /** Just-In-Time (JIT) provisioning provider name (e.g. \"aws-sts\") */\n jitProvider?: string;\n /** Expiration timestamp for the cached JIT credential */\n jitExpiresAt?: string;\n}\n\nexport interface QuantumEnvelope {\n /** Schema version for forward compatibility */\n v: 1;\n /** Simple value (when not in superposition) */\n value?: string;\n /** Superposition: environment-keyed values */\n states?: Record<Environment, string>;\n /** Default environment to collapse to when no context is available */\n defaultEnv?: Environment;\n /** Quantum metadata */\n meta: SecretMetadata;\n}\n\nexport function createEnvelope(\n value: string,\n opts?: Partial<Pick<QuantumEnvelope, \"states\" | \"defaultEnv\">> & {\n description?: string;\n tags?: string[];\n ttlSeconds?: number;\n expiresAt?: string;\n entangled?: EntanglementLink[];\n rotationFormat?: string;\n rotationPrefix?: string;\n provider?: string;\n requiresApproval?: boolean;\n jitProvider?: string;\n },\n): QuantumEnvelope {\n const now = new Date().toISOString();\n\n let expiresAt = opts?.expiresAt;\n if (!expiresAt && opts?.ttlSeconds) {\n expiresAt = new Date(Date.now() + opts.ttlSeconds * 1000).toISOString();\n }\n\n return {\n v: 1,\n value: opts?.states ? undefined : value,\n states: opts?.states,\n defaultEnv: opts?.defaultEnv,\n meta: {\n createdAt: now,\n updatedAt: now,\n expiresAt,\n ttlSeconds: opts?.ttlSeconds,\n description: opts?.description,\n tags: opts?.tags,\n entangled: opts?.entangled,\n accessCount: 0,\n rotationFormat: opts?.rotationFormat,\n rotationPrefix: opts?.rotationPrefix,\n provider: opts?.provider,\n requiresApproval: opts?.requiresApproval,\n jitProvider: opts?.jitProvider,\n },\n };\n}\n\nexport function parseEnvelope(raw: string): QuantumEnvelope | null {\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\" && parsed.v === 1) {\n return parsed as QuantumEnvelope;\n }\n } catch {\n // Not a quantum envelope - legacy raw string\n }\n return null;\n}\n\n/**\n * Wrap a legacy raw string value into a quantum envelope.\n * Used for backward compatibility with secrets stored before the envelope format.\n */\nexport function wrapLegacy(rawValue: string): QuantumEnvelope {\n const now = new Date().toISOString();\n return {\n v: 1,\n value: rawValue,\n meta: {\n createdAt: now,\n updatedAt: now,\n accessCount: 0,\n },\n };\n}\n\nexport function serializeEnvelope(envelope: QuantumEnvelope): string {\n return JSON.stringify(envelope);\n}\n\n/**\n * Resolve the concrete value from a quantum envelope.\n * If in superposition, collapses based on the provided environment.\n */\nexport function collapseValue(\n envelope: QuantumEnvelope,\n env?: Environment,\n): string | null {\n if (envelope.states) {\n const targetEnv = env ?? envelope.defaultEnv;\n if (targetEnv && envelope.states[targetEnv]) {\n return envelope.states[targetEnv];\n }\n // If no env match, try default, then return null\n if (envelope.defaultEnv && envelope.states[envelope.defaultEnv]) {\n return envelope.states[envelope.defaultEnv];\n }\n // Last resort: return the first state\n const keys = Object.keys(envelope.states);\n if (keys.length > 0) {\n return envelope.states[keys[0]];\n }\n return null;\n }\n\n return envelope.value ?? null;\n}\n\nexport interface DecayStatus {\n isExpired: boolean;\n isStale: boolean;\n /** Percentage of lifetime elapsed (0-100+) */\n lifetimePercent: number;\n /** Seconds remaining until expiry, or negative if expired */\n secondsRemaining: number | null;\n /** Human-readable time remaining */\n timeRemaining: string | null;\n}\n\nexport function checkDecay(envelope: QuantumEnvelope): DecayStatus {\n if (!envelope.meta.expiresAt) {\n return {\n isExpired: false,\n isStale: false,\n lifetimePercent: 0,\n secondsRemaining: null,\n timeRemaining: null,\n };\n }\n\n const now = Date.now();\n const expires = new Date(envelope.meta.expiresAt).getTime();\n const created = new Date(envelope.meta.createdAt).getTime();\n const totalLifetime = expires - created;\n const elapsed = now - created;\n const remaining = expires - now;\n\n const lifetimePercent =\n totalLifetime > 0 ? Math.round((elapsed / totalLifetime) * 100) : 100;\n\n const secondsRemaining = Math.floor(remaining / 1000);\n\n let timeRemaining: string | null = null;\n if (remaining > 0) {\n const days = Math.floor(remaining / 86400000);\n const hours = Math.floor((remaining % 86400000) / 3600000);\n const minutes = Math.floor((remaining % 3600000) / 60000);\n\n if (days > 0) timeRemaining = `${days}d ${hours}h`;\n else if (hours > 0) timeRemaining = `${hours}h ${minutes}m`;\n else timeRemaining = `${minutes}m`;\n } else {\n timeRemaining = \"expired\";\n }\n\n return {\n isExpired: remaining <= 0,\n isStale: lifetimePercent >= 75,\n lifetimePercent,\n secondsRemaining,\n timeRemaining,\n };\n}\n\n/**\n * Record an access event on the envelope (observer effect).\n * Returns a new envelope with updated access metadata.\n */\nexport function recordAccess(envelope: QuantumEnvelope): QuantumEnvelope {\n return {\n ...envelope,\n meta: {\n ...envelope.meta,\n accessCount: envelope.meta.accessCount + 1,\n lastAccessedAt: new Date().toISOString(),\n },\n };\n}\n","/**\n * Wavefunction Collapse: auto-detect the current environment context.\n *\n * Resolution order (first match wins):\n * 1. Explicit --env flag\n * 2. QRING_ENV environment variable\n * 3. NODE_ENV environment variable\n * 4. Git branch heuristics (main/master → prod, develop → dev, staging → staging)\n * 5. .q-ring.json project config\n * 6. Default environment from the envelope\n */\n\nimport { execSync } from \"node:child_process\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Environment } from \"./envelope.js\";\n\nconst BRANCH_ENV_MAP: Record<string, Environment> = {\n main: \"prod\",\n master: \"prod\",\n production: \"prod\",\n develop: \"dev\",\n development: \"dev\",\n dev: \"dev\",\n staging: \"staging\",\n stage: \"staging\",\n test: \"test\",\n testing: \"test\",\n};\n\nfunction detectGitBranch(cwd?: string): string | null {\n try {\n const branch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n cwd: cwd ?? process.cwd(),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n encoding: \"utf8\",\n timeout: 3000,\n }).trim();\n return branch || null;\n } catch {\n return null;\n }\n}\n\nexport interface ManifestEntry {\n required?: boolean;\n description?: string;\n /** Expected format for auto-rotation (e.g. \"api-key\", \"password\", \"uuid\") */\n format?: string;\n /** Expected prefix (e.g. \"sk-\") */\n prefix?: string;\n /** Provider name for liveness validation (e.g. \"openai\", \"stripe\", \"github\") */\n provider?: string;\n /** Custom validation URL for generic HTTP provider */\n validationUrl?: string;\n}\n\nexport interface ProjectConfig {\n env?: Environment;\n defaultEnv?: Environment;\n branchMap?: Record<string, Environment>;\n /** Secrets manifest — declares required/expected secrets for this project */\n secrets?: Record<string, ManifestEntry>;\n /** Governance policy for MCP, exec, and secret lifecycle */\n policy?: import(\"./policy.js\").PolicyConfig;\n}\n\nexport function readProjectConfig(projectPath?: string): ProjectConfig | null {\n const configPath = join(projectPath ?? process.cwd(), \".q-ring.json\");\n try {\n if (existsSync(configPath)) {\n return JSON.parse(readFileSync(configPath, \"utf8\"));\n }\n } catch {\n // invalid config\n }\n return null;\n}\n\nexport interface CollapseContext {\n /** Explicitly provided environment */\n explicit?: Environment;\n /** Project path for git/config detection */\n projectPath?: string;\n}\n\nexport interface CollapseResult {\n env: Environment;\n source:\n | \"explicit\"\n | \"QRING_ENV\"\n | \"NODE_ENV\"\n | \"git-branch\"\n | \"project-config\"\n | \"default\";\n}\n\nexport function collapseEnvironment(\n ctx: CollapseContext = {},\n): CollapseResult | null {\n if (ctx.explicit) {\n return { env: ctx.explicit, source: \"explicit\" };\n }\n\n const qringEnv = process.env.QRING_ENV;\n if (qringEnv) {\n return { env: qringEnv, source: \"QRING_ENV\" };\n }\n\n const nodeEnv = process.env.NODE_ENV;\n if (nodeEnv) {\n const mapped = mapEnvName(nodeEnv);\n return { env: mapped, source: \"NODE_ENV\" };\n }\n\n const config = readProjectConfig(ctx.projectPath);\n if (config?.env) {\n return { env: config.env, source: \"project-config\" };\n }\n\n const branch = detectGitBranch(ctx.projectPath);\n if (branch) {\n const branchMap = { ...BRANCH_ENV_MAP, ...config?.branchMap };\n const mapped = branchMap[branch] ?? matchGlob(branchMap, branch);\n if (mapped) {\n return { env: mapped, source: \"git-branch\" };\n }\n }\n\n if (config?.defaultEnv) {\n return { env: config.defaultEnv, source: \"project-config\" };\n }\n\n return null;\n}\n\n/**\n * Match a branch name against glob-style patterns in the branchMap.\n * Supports `*` as a wildcard (e.g., `release/*`, `feature/*`).\n */\nfunction matchGlob(\n branchMap: Record<string, Environment>,\n branch: string,\n): Environment | undefined {\n for (const [pattern, env] of Object.entries(branchMap)) {\n if (!pattern.includes(\"*\")) continue;\n const regex = new RegExp(\n \"^\" + pattern.replace(/\\*/g, \".*\") + \"$\",\n );\n if (regex.test(branch)) return env;\n }\n return undefined;\n}\n\nfunction mapEnvName(raw: string): Environment {\n const lower = raw.toLowerCase();\n if (lower === \"production\") return \"prod\";\n if (lower === \"development\") return \"dev\";\n return lower;\n}\n","/**\n * Observer Effect: every secret read/write/delete is logged.\n * Audit trail stored at ~/.config/q-ring/audit.jsonl\n *\n * The act of observation changes the state — each access increments\n * the envelope's access counter and records a timestamp.\n *\n * Hash-chain integrity: each event includes a SHA-256 hash of the\n * previous event, creating a tamper-evident chain. If any event is\n * modified or deleted, the chain breaks and `audit:verify` reports it.\n */\n\nimport { existsSync, mkdirSync, appendFileSync, readFileSync, writeFileSync, openSync, fstatSync, readSync, closeSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createHash } from \"node:crypto\";\n\nexport type AuditAction =\n | \"read\"\n | \"write\"\n | \"delete\"\n | \"list\"\n | \"export\"\n | \"generate\"\n | \"entangle\"\n | \"tunnel\"\n | \"teleport\"\n | \"collapse\"\n | \"approve\"\n | \"revoke\"\n | \"policy_deny\"\n | \"rotate\";\n\nexport interface AuditEvent {\n timestamp: string;\n action: AuditAction;\n key?: string;\n scope?: string;\n env?: string;\n source: \"cli\" | \"mcp\" | \"agent\" | \"api\" | \"hook\" | \"ci\";\n detail?: string;\n pid: number;\n /** SHA-256 hash of the previous event line for chain integrity */\n prevHash?: string;\n /** Correlation ID to group related events across a single operation */\n correlationId?: string;\n}\n\nfunction getAuditDir(): string {\n const dir = join(homedir(), \".config\", \"q-ring\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return dir;\n}\n\nfunction getAuditPath(): string {\n return join(getAuditDir(), \"audit.jsonl\");\n}\n\nfunction getLastLineHash(): string | undefined {\n const path = getAuditPath();\n if (!existsSync(path)) return undefined;\n\n try {\n const fd = openSync(path, \"r\");\n const stat = fstatSync(fd);\n if (stat.size === 0) {\n closeSync(fd);\n return undefined;\n }\n\n // Read up to the last 8KB to find the last line\n const tailSize = Math.min(stat.size, 8192);\n const buf = Buffer.alloc(tailSize);\n readSync(fd, buf, 0, tailSize, stat.size - tailSize);\n closeSync(fd);\n\n const tail = buf.toString(\"utf8\");\n const lines = tail.split(\"\\n\").filter((l) => l.trim());\n if (lines.length === 0) return undefined;\n\n const lastLine = lines[lines.length - 1];\n return createHash(\"sha256\").update(lastLine).digest(\"hex\");\n } catch {\n return undefined;\n }\n}\n\nexport function logAudit(\n event: Omit<AuditEvent, \"timestamp\" | \"pid\" | \"prevHash\">,\n): void {\n const prevHash = getLastLineHash();\n\n const full: AuditEvent = {\n ...event,\n timestamp: new Date().toISOString(),\n pid: process.pid,\n prevHash,\n };\n\n try {\n appendFileSync(getAuditPath(), JSON.stringify(full) + \"\\n\");\n } catch {\n // audit logging should never crash the app\n }\n}\n\nexport interface AuditQuery {\n key?: string;\n action?: AuditAction;\n since?: string;\n limit?: number;\n source?: AuditEvent[\"source\"];\n correlationId?: string;\n}\n\nexport function queryAudit(query: AuditQuery = {}): AuditEvent[] {\n const path = getAuditPath();\n if (!existsSync(path)) return [];\n\n try {\n const lines = readFileSync(path, \"utf8\")\n .split(\"\\n\")\n .filter((l) => l.trim());\n\n let events: AuditEvent[] = lines\n .map((line) => {\n try {\n return JSON.parse(line) as AuditEvent;\n } catch {\n return null;\n }\n })\n .filter((e): e is AuditEvent => e !== null);\n\n if (query.key) events = events.filter((e) => e.key === query.key);\n if (query.action) events = events.filter((e) => e.action === query.action);\n if (query.source) events = events.filter((e) => e.source === query.source);\n if (query.correlationId) events = events.filter((e) => e.correlationId === query.correlationId);\n if (query.since) {\n const since = new Date(query.since).getTime();\n events = events.filter((e) => new Date(e.timestamp).getTime() >= since);\n }\n\n events.sort(\n (a, b) =>\n new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime(),\n );\n\n if (query.limit) events = events.slice(0, query.limit);\n\n return events;\n } catch {\n return [];\n }\n}\n\nexport interface VerifyResult {\n totalEvents: number;\n validEvents: number;\n brokenAt?: number;\n brokenEvent?: AuditEvent;\n intact: boolean;\n}\n\n/**\n * Verify the hash-chain integrity of the entire audit log.\n * Returns the first break point if the chain has been tampered with.\n */\nexport function verifyAuditChain(): VerifyResult {\n const path = getAuditPath();\n if (!existsSync(path)) {\n return { totalEvents: 0, validEvents: 0, intact: true };\n }\n\n const lines = readFileSync(path, \"utf8\")\n .split(\"\\n\")\n .filter((l) => l.trim());\n\n if (lines.length === 0) {\n return { totalEvents: 0, validEvents: 0, intact: true };\n }\n\n let validEvents = 0;\n\n for (let i = 0; i < lines.length; i++) {\n let event: AuditEvent;\n try {\n event = JSON.parse(lines[i]);\n } catch {\n return {\n totalEvents: lines.length,\n validEvents,\n brokenAt: i,\n intact: false,\n };\n }\n\n if (i === 0) {\n validEvents++;\n continue;\n }\n\n const expectedHash = createHash(\"sha256\")\n .update(lines[i - 1])\n .digest(\"hex\");\n\n if (event.prevHash !== expectedHash) {\n return {\n totalEvents: lines.length,\n validEvents,\n brokenAt: i,\n brokenEvent: event,\n intact: false,\n };\n }\n\n validEvents++;\n }\n\n return { totalEvents: lines.length, validEvents, intact: true };\n}\n\nexport interface ExportOptions {\n since?: string;\n until?: string;\n format?: \"jsonl\" | \"json\" | \"csv\";\n}\n\n/**\n * Export audit events in a portable format, optionally filtered by time range.\n */\nexport function exportAudit(opts: ExportOptions = {}): string {\n const path = getAuditPath();\n if (!existsSync(path)) return opts.format === \"json\" ? \"[]\" : \"\";\n\n const lines = readFileSync(path, \"utf8\")\n .split(\"\\n\")\n .filter((l) => l.trim());\n\n let events: AuditEvent[] = lines\n .map((l) => {\n try {\n return JSON.parse(l) as AuditEvent;\n } catch {\n return null;\n }\n })\n .filter((e): e is AuditEvent => e !== null);\n\n if (opts.since) {\n const since = new Date(opts.since).getTime();\n events = events.filter((e) => new Date(e.timestamp).getTime() >= since);\n }\n if (opts.until) {\n const until = new Date(opts.until).getTime();\n events = events.filter((e) => new Date(e.timestamp).getTime() <= until);\n }\n\n if (opts.format === \"json\") {\n return JSON.stringify(events, null, 2);\n }\n\n if (opts.format === \"csv\") {\n const header = \"timestamp,action,key,scope,env,source,pid,correlationId,detail\";\n const rows = events.map(\n (e) =>\n `${e.timestamp},${e.action},${e.key ?? \"\"},${e.scope ?? \"\"},${e.env ?? \"\"},${e.source},${e.pid},${e.correlationId ?? \"\"},${(e.detail ?? \"\").replace(/,/g, \";\")}`,\n );\n return [header, ...rows].join(\"\\n\");\n }\n\n return events.map((e) => JSON.stringify(e)).join(\"\\n\");\n}\n\nexport interface AccessAnomaly {\n type: \"burst\" | \"unusual-hour\" | \"new-source\" | \"tampered\";\n description: string;\n events: AuditEvent[];\n}\n\nexport function detectAnomalies(key?: string): AccessAnomaly[] {\n const recent = queryAudit({\n key,\n action: \"read\",\n since: new Date(Date.now() - 3600000).toISOString(),\n });\n\n const anomalies: AccessAnomaly[] = [];\n\n if (key && recent.length > 50) {\n anomalies.push({\n type: \"burst\",\n description: `${recent.length} reads of \"${key}\" in the last hour`,\n events: recent.slice(0, 10),\n });\n }\n\n const nightAccess = recent.filter((e) => {\n const hour = new Date(e.timestamp).getHours();\n return hour >= 1 && hour < 5;\n });\n\n if (nightAccess.length > 0) {\n anomalies.push({\n type: \"unusual-hour\",\n description: `${nightAccess.length} access(es) during unusual hours (1am-5am)`,\n events: nightAccess,\n });\n }\n\n const verification = verifyAuditChain();\n if (!verification.intact) {\n anomalies.push({\n type: \"tampered\",\n description: `Audit chain broken at event #${verification.brokenAt}`,\n events: verification.brokenEvent ? [verification.brokenEvent] : [],\n });\n }\n\n return anomalies;\n}\n","/**\n * Quantum Entanglement: link secrets across projects.\n * When one entangled secret is rotated, all linked copies update.\n *\n * Entanglement is stored as metadata in the envelope. The entanglement\n * registry at ~/.config/q-ring/entanglement.json provides a reverse\n * lookup: given a secret, find all its entangled partners.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\nexport interface EntanglementPair {\n /** Source: service/key */\n source: { service: string; key: string };\n /** Target: service/key */\n target: { service: string; key: string };\n /** When this entanglement was created */\n createdAt: string;\n}\n\ninterface EntanglementRegistry {\n pairs: EntanglementPair[];\n}\n\nfunction getRegistryPath(): string {\n const dir = join(homedir(), \".config\", \"q-ring\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return join(dir, \"entanglement.json\");\n}\n\nfunction loadRegistry(): EntanglementRegistry {\n const path = getRegistryPath();\n if (!existsSync(path)) {\n return { pairs: [] };\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return { pairs: [] };\n }\n}\n\nfunction saveRegistry(registry: EntanglementRegistry): void {\n writeFileSync(getRegistryPath(), JSON.stringify(registry, null, 2));\n}\n\nexport function entangle(\n source: { service: string; key: string },\n target: { service: string; key: string },\n): void {\n const registry = loadRegistry();\n\n const exists = registry.pairs.some(\n (p) =>\n p.source.service === source.service &&\n p.source.key === source.key &&\n p.target.service === target.service &&\n p.target.key === target.key,\n );\n\n if (!exists) {\n registry.pairs.push({\n source,\n target,\n createdAt: new Date().toISOString(),\n });\n // Bidirectional: add reverse link too\n registry.pairs.push({\n source: target,\n target: source,\n createdAt: new Date().toISOString(),\n });\n saveRegistry(registry);\n }\n}\n\nexport function disentangle(\n source: { service: string; key: string },\n target: { service: string; key: string },\n): void {\n const registry = loadRegistry();\n registry.pairs = registry.pairs.filter(\n (p) =>\n !(\n (p.source.service === source.service &&\n p.source.key === source.key &&\n p.target.service === target.service &&\n p.target.key === target.key) ||\n (p.source.service === target.service &&\n p.source.key === target.key &&\n p.target.service === source.service &&\n p.target.key === source.key)\n ),\n );\n saveRegistry(registry);\n}\n\n/**\n * Find all entangled partners for a given secret.\n */\nexport function findEntangled(\n source: { service: string; key: string },\n): { service: string; key: string }[] {\n const registry = loadRegistry();\n return registry.pairs\n .filter(\n (p) =>\n p.source.service === source.service && p.source.key === source.key,\n )\n .map((p) => p.target);\n}\n\n/**\n * List all entanglement pairs.\n */\nexport function listEntanglements(): EntanglementPair[] {\n return loadRegistry().pairs;\n}\n","import { Entry, findCredentials } from \"@napi-rs/keyring\";\nimport {\n resolveScope,\n globalService,\n projectService,\n teamService,\n orgService,\n type Scope,\n} from \"./scope.js\";\nimport {\n type QuantumEnvelope,\n type Environment,\n createEnvelope,\n parseEnvelope,\n wrapLegacy,\n serializeEnvelope,\n collapseValue,\n checkDecay,\n recordAccess,\n type DecayStatus,\n type EntanglementLink,\n} from \"./envelope.js\";\nimport { collapseEnvironment, type CollapseContext } from \"./collapse.js\";\nimport { logAudit, type AuditAction } from \"./observer.js\";\nimport { findEntangled, entangle as entangleLink, disentangle as disentangleLink } from \"./entanglement.js\";\nimport { fireHooks } from \"./hooks.js\";\nimport { hasApproval } from \"./approval.js\";\nimport { registry as jitRegistry } from \"./provision.js\";\nimport { checkKeyReadPolicy } from \"./policy.js\";\n\nexport interface SecretEntry {\n key: string;\n scope: Scope;\n value?: string;\n envelope?: QuantumEnvelope;\n decay?: DecayStatus;\n}\n\nexport interface KeyringOptions {\n scope?: Scope;\n projectPath?: string;\n /** Team identifier for team-scoped secrets */\n teamId?: string;\n /** Org identifier for org-scoped secrets */\n orgId?: string;\n /** Environment for superposition collapse */\n env?: Environment;\n /** Audit source */\n source?: \"cli\" | \"mcp\" | \"agent\" | \"api\" | \"hook\" | \"ci\";\n /** Skip audit logging (for internal polling like the dashboard) */\n silent?: boolean;\n}\n\nexport interface SetSecretOptions extends KeyringOptions {\n /** Environment states for superposition */\n states?: Record<Environment, string>;\n /** Default environment */\n defaultEnv?: Environment;\n /** TTL in seconds (quantum decay) */\n ttlSeconds?: number;\n /** Expiry timestamp */\n expiresAt?: string;\n /** Description */\n description?: string;\n /** Tags */\n tags?: string[];\n /** Format for auto-rotation (e.g. \"api-key\", \"password\", \"uuid\") */\n rotationFormat?: string;\n /** Prefix for auto-rotation (e.g. \"sk-\") */\n rotationPrefix?: string;\n /** Provider for liveness validation (e.g. \"openai\", \"stripe\") */\n provider?: string;\n /** Whether reading this secret via MCP requires explicit user approval */\n requiresApproval?: boolean;\n /** Just-In-Time (JIT) provisioning provider name (e.g. \"aws-sts\") */\n jitProvider?: string;\n}\n\nfunction readEnvelope(service: string, key: string): QuantumEnvelope | null {\n const entry = new Entry(service, key);\n const raw = entry.getPassword();\n if (raw === null) return null;\n\n const envelope = parseEnvelope(raw);\n return envelope ?? wrapLegacy(raw);\n}\n\nfunction writeEnvelope(\n service: string,\n key: string,\n envelope: QuantumEnvelope,\n): void {\n const entry = new Entry(service, key);\n entry.setPassword(serializeEnvelope(envelope));\n}\n\nfunction resolveEnv(opts: KeyringOptions): Environment | undefined {\n if (opts.env) return opts.env;\n const result = collapseEnvironment({ projectPath: opts.projectPath });\n return result?.env;\n}\n\nfunction resolveTemplates(value: string, opts: KeyringOptions & { _seen?: Set<string> }, seen: Set<string>): string {\n if (!value.includes(\"{{\") || !value.includes(\"}}\")) return value;\n \n return value.replace(/\\{\\{([^}]+)\\}\\}/g, (match, refKeyRaw) => {\n const refKey = refKeyRaw.trim();\n const refValue = getSecret(refKey, { ...opts, _seen: seen });\n if (refValue === null) {\n throw new Error(`Template resolution failed: referenced secret \"${refKey}\" not found`);\n }\n return refValue;\n });\n}\n\nexport function resolveTemplatesOffline(value: string, rawValues: Map<string, string>, seen: Set<string>): string {\n if (!value.includes(\"{{\") || !value.includes(\"}}\")) return value;\n \n return value.replace(/\\{\\{([^}]+)\\}\\}/g, (match, refKeyRaw) => {\n const refKey = refKeyRaw.trim();\n if (seen.has(refKey)) {\n throw new Error(`Circular dependency detected: ${[...seen].join(\" -> \")} -> ${refKey}`);\n }\n const rawRef = rawValues.get(refKey);\n if (rawRef === undefined) {\n throw new Error(`Template resolution failed: referenced secret \"${refKey}\" not found`);\n }\n const nextSeen = new Set(seen);\n nextSeen.add(refKey);\n return resolveTemplatesOffline(rawRef, rawValues, nextSeen);\n });\n}\n\n/**\n * Retrieve a secret by key, with scope resolution and superposition collapse.\n * Records the access in the audit log (observer effect).\n */\nexport function getSecret(\n key: string,\n opts: KeyringOptions & { _seen?: Set<string> } = {},\n): string | null {\n const scopes = resolveScope(opts);\n const env = resolveEnv(opts);\n const source = opts.source ?? \"cli\";\n const seen = opts._seen ?? new Set<string>();\n\n if (source === \"mcp\") {\n const policyDecision = checkKeyReadPolicy(key, undefined, opts.projectPath);\n if (!policyDecision.allowed) {\n throw new Error(`Policy Denied: ${policyDecision.reason}`);\n }\n }\n\n if (seen.has(key)) {\n throw new Error(`Circular dependency detected: ${[...seen].join(\" -> \")} -> ${key}`);\n }\n const nextSeen = new Set(seen);\n nextSeen.add(key);\n\n for (const { service, scope } of scopes) {\n const envelope = readEnvelope(service, key);\n if (!envelope) continue;\n\n // Check decay\n const decay = checkDecay(envelope);\n if (decay.isExpired) {\n if (!opts.silent) {\n logAudit({\n action: \"read\",\n key,\n scope,\n source,\n detail: \"blocked: secret expired (quantum decay)\",\n });\n }\n continue;\n }\n\n // Check approvals for MCP\n if (envelope.meta.requiresApproval && source === \"mcp\") {\n if (!hasApproval(key, scope)) {\n if (!opts.silent) {\n logAudit({\n action: \"read\",\n key,\n scope,\n source,\n detail: \"blocked: requires user approval\",\n });\n }\n throw new Error(`Access Denied: This secret requires user approval. Please ask the user to run 'qring approve ${key}'`);\n }\n }\n\n // Collapse superposition\n let value = collapseValue(envelope, env);\n if (value === null) continue;\n\n // Just-In-Time Provisioning\n if (envelope.meta.jitProvider) {\n const provider = jitRegistry.get(envelope.meta.jitProvider);\n if (provider) {\n let isExpired = true;\n if (envelope.states && envelope.states[\"jit\"] && envelope.meta.jitExpiresAt) {\n isExpired = new Date(envelope.meta.jitExpiresAt).getTime() <= Date.now();\n }\n\n if (isExpired) {\n const result = provider.provision(value); // value contains the config\n envelope.states = envelope.states ?? {};\n envelope.states[\"jit\"] = result.value;\n envelope.meta.jitExpiresAt = result.expiresAt;\n writeEnvelope(service, key, envelope);\n }\n value = envelope.states![\"jit\"];\n }\n }\n\n // Resolve templates\n value = resolveTemplates(value, { ...opts, _seen: nextSeen }, nextSeen);\n\n // Observer effect: record access and persist\n if (!opts.silent) {\n const updated = recordAccess(envelope);\n writeEnvelope(service, key, updated);\n logAudit({ action: \"read\", key, scope, env, source });\n }\n\n return value;\n }\n\n return null;\n}\n\n/**\n * Get the full envelope for a secret (for inspection, no value extraction).\n */\nexport function getEnvelope(\n key: string,\n opts: KeyringOptions = {},\n): { envelope: QuantumEnvelope; scope: Scope } | null {\n const scopes = resolveScope(opts);\n\n for (const { service, scope } of scopes) {\n const envelope = readEnvelope(service, key);\n if (envelope) return { envelope, scope };\n }\n\n return null;\n}\n\n/**\n * Store a secret with quantum metadata.\n */\nexport function setSecret(\n key: string,\n value: string,\n opts: SetSecretOptions = {},\n): void {\n const scope = opts.scope ?? \"global\";\n const scopes = resolveScope({ ...opts, scope });\n const { service } = scopes[0];\n const source = opts.source ?? \"cli\";\n\n // Check if there's an existing envelope to preserve metadata\n const existing = readEnvelope(service, key);\n\n let envelope: QuantumEnvelope;\n\n const rotFmt = opts.rotationFormat ?? existing?.meta.rotationFormat;\n const rotPfx = opts.rotationPrefix ?? existing?.meta.rotationPrefix;\n const prov = opts.provider ?? existing?.meta.provider;\n const reqApp = opts.requiresApproval ?? existing?.meta.requiresApproval;\n const jitProv = opts.jitProvider ?? existing?.meta.jitProvider;\n\n if (opts.states) {\n envelope = createEnvelope(\"\", {\n states: opts.states,\n defaultEnv: opts.defaultEnv,\n description: opts.description,\n tags: opts.tags,\n ttlSeconds: opts.ttlSeconds,\n expiresAt: opts.expiresAt,\n entangled: existing?.meta.entangled,\n rotationFormat: rotFmt,\n rotationPrefix: rotPfx,\n provider: prov,\n requiresApproval: reqApp,\n jitProvider: jitProv,\n });\n } else {\n envelope = createEnvelope(value, {\n description: opts.description,\n tags: opts.tags,\n ttlSeconds: opts.ttlSeconds,\n expiresAt: opts.expiresAt,\n entangled: existing?.meta.entangled,\n rotationFormat: rotFmt,\n rotationPrefix: rotPfx,\n provider: prov,\n requiresApproval: reqApp,\n jitProvider: jitProv,\n });\n }\n\n // Preserve access count from existing\n if (existing) {\n envelope.meta.createdAt = existing.meta.createdAt;\n envelope.meta.accessCount = existing.meta.accessCount;\n }\n\n writeEnvelope(service, key, envelope);\n logAudit({ action: \"write\", key, scope, source });\n\n // Propagate to entangled secrets\n const entangled = findEntangled({ service, key });\n for (const target of entangled) {\n try {\n const targetEnvelope = readEnvelope(target.service, target.key);\n if (targetEnvelope) {\n if (opts.states) {\n targetEnvelope.states = opts.states;\n } else {\n targetEnvelope.value = value;\n }\n targetEnvelope.meta.updatedAt = new Date().toISOString();\n writeEnvelope(target.service, target.key, targetEnvelope);\n logAudit({\n action: \"entangle\",\n key: target.key,\n scope: \"global\",\n source,\n detail: `propagated from ${key}`,\n });\n }\n } catch {\n // entangled target may not exist\n }\n }\n\n fireHooks({\n action: \"write\",\n key,\n scope,\n timestamp: new Date().toISOString(),\n source,\n }, envelope.meta.tags).catch(() => {});\n}\n\n/**\n * Delete a secret from the specified scope (or both if unscoped).\n */\nexport function deleteSecret(\n key: string,\n opts: KeyringOptions = {},\n): boolean {\n const scopes = resolveScope(opts);\n const source = opts.source ?? \"cli\";\n let deleted = false;\n\n for (const { service, scope } of scopes) {\n const entry = new Entry(service, key);\n try {\n if (entry.deleteCredential()) {\n deleted = true;\n logAudit({ action: \"delete\", key, scope, source });\n fireHooks({\n action: \"delete\",\n key,\n scope,\n timestamp: new Date().toISOString(),\n source,\n }).catch(() => {});\n }\n } catch {\n // not found\n }\n }\n\n return deleted;\n}\n\n/**\n * Check whether a secret exists in any applicable scope.\n */\nexport function hasSecret(\n key: string,\n opts: KeyringOptions = {},\n): boolean {\n const scopes = resolveScope(opts);\n\n for (const { service } of scopes) {\n const envelope = readEnvelope(service, key);\n if (envelope) {\n const decay = checkDecay(envelope);\n if (!decay.isExpired) return true;\n }\n }\n\n return false;\n}\n\n/**\n * List all secrets across applicable scopes with quantum metadata.\n */\nexport function listSecrets(opts: KeyringOptions = {}): SecretEntry[] {\n const source = opts.source ?? \"cli\";\n const services: { service: string; scope: Scope }[] = [];\n\n if (!opts.scope || opts.scope === \"global\") {\n services.push({ service: globalService(), scope: \"global\" });\n }\n\n if ((!opts.scope || opts.scope === \"project\") && opts.projectPath) {\n services.push({\n service: projectService(opts.projectPath),\n scope: \"project\",\n });\n }\n\n if ((!opts.scope || opts.scope === \"team\") && opts.teamId) {\n services.push({ service: teamService(opts.teamId), scope: \"team\" });\n }\n\n if ((!opts.scope || opts.scope === \"org\") && opts.orgId) {\n services.push({ service: orgService(opts.orgId), scope: \"org\" });\n }\n\n const results: SecretEntry[] = [];\n const seen = new Set<string>();\n\n for (const { service, scope } of services) {\n try {\n const credentials = findCredentials(service);\n for (const cred of credentials) {\n const id = `${scope}:${cred.account}`;\n if (seen.has(id)) continue;\n seen.add(id);\n\n const envelope = parseEnvelope(cred.password) ?? wrapLegacy(cred.password);\n const decay = checkDecay(envelope);\n\n results.push({\n key: cred.account,\n scope,\n envelope,\n decay,\n });\n }\n } catch {\n // keyring unavailable\n }\n }\n\n if (!opts.silent) {\n logAudit({ action: \"list\", source });\n }\n\n return results.sort((a, b) => a.key.localeCompare(b.key));\n}\n\n/**\n * Export all secrets with their values (for .env or JSON export).\n * Collapses superposition based on detected environment.\n */\nexport function exportSecrets(\n opts: KeyringOptions & { format?: \"env\" | \"json\"; keys?: string[]; tags?: string[] } = {},\n): string {\n const format = opts.format ?? \"env\";\n const env = resolveEnv(opts);\n let entries = listSecrets(opts);\n const source = opts.source ?? \"cli\";\n\n if (opts.keys?.length) {\n const keySet = new Set(opts.keys);\n entries = entries.filter((e) => keySet.has(e.key));\n }\n\n if (opts.tags?.length) {\n entries = entries.filter((e) =>\n opts.tags!.some((t) => e.envelope?.meta.tags?.includes(t)),\n );\n }\n\n const rawValues = new Map<string, string>();\n\n // Process in precedence order: global < org < team < project\n const globalEntries = entries.filter((e) => e.scope === \"global\");\n const orgEntries = entries.filter((e) => e.scope === \"org\");\n const teamEntries = entries.filter((e) => e.scope === \"team\");\n const projectEntries = entries.filter((e) => e.scope === \"project\");\n\n for (const entry of [...globalEntries, ...orgEntries, ...teamEntries, ...projectEntries]) {\n if (entry.envelope) {\n const decay = checkDecay(entry.envelope);\n if (decay.isExpired) continue;\n\n const value = collapseValue(entry.envelope, env);\n if (value !== null) {\n rawValues.set(entry.key, value);\n }\n }\n }\n\n const merged = new Map<string, string>();\n for (const [key, value] of rawValues) {\n try {\n const resolved = resolveTemplatesOffline(value, rawValues, new Set([key]));\n merged.set(key, resolved);\n } catch (err) {\n // In export, if a template fails, we just don't export it\n console.warn(`Warning: skipped exporting ${key} due to template error: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n logAudit({ action: \"export\", source, detail: `format=${format}` });\n\n if (format === \"json\") {\n const obj: Record<string, string> = {};\n for (const [key, value] of merged) {\n obj[key] = value;\n }\n return JSON.stringify(obj, null, 2);\n }\n\n const lines: string[] = [];\n for (const [key, value] of merged) {\n const escaped = value\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, \"\\\\n\");\n lines.push(`${key}=\"${escaped}\"`);\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Create an entanglement between two secrets.\n */\nexport function entangleSecrets(\n sourceKey: string,\n sourceOpts: KeyringOptions,\n targetKey: string,\n targetOpts: KeyringOptions,\n): void {\n const sourceScopes = resolveScope({ ...sourceOpts, scope: sourceOpts.scope ?? \"global\" });\n const targetScopes = resolveScope({ ...targetOpts, scope: targetOpts.scope ?? \"global\" });\n\n const source = { service: sourceScopes[0].service, key: sourceKey };\n const target = { service: targetScopes[0].service, key: targetKey };\n\n entangleLink(source, target);\n logAudit({\n action: \"entangle\",\n key: sourceKey,\n source: sourceOpts.source ?? \"cli\",\n detail: `entangled with ${targetKey}`,\n });\n}\n\n/**\n * Remove an entanglement between two secrets.\n */\nexport function disentangleSecrets(\n sourceKey: string,\n sourceOpts: KeyringOptions,\n targetKey: string,\n targetOpts: KeyringOptions,\n): void {\n const sourceScopes = resolveScope({ ...sourceOpts, scope: sourceOpts.scope ?? \"global\" });\n const targetScopes = resolveScope({ ...targetOpts, scope: targetOpts.scope ?? \"global\" });\n\n const source = { service: sourceScopes[0].service, key: sourceKey };\n const target = { service: targetScopes[0].service, key: targetKey };\n\n disentangleLink(source, target);\n logAudit({\n action: \"entangle\",\n key: sourceKey,\n source: sourceOpts.source ?? \"cli\",\n detail: `disentangled from ${targetKey}`,\n });\n}\n","import { createHash } from \"node:crypto\";\n\nexport function hashProjectPath(projectPath: string): string {\n return createHash(\"sha256\").update(projectPath).digest(\"hex\").slice(0, 12);\n}\n","import { hashProjectPath } from \"../utils/hash.js\";\n\nconst SERVICE_PREFIX = \"q-ring\";\n\nexport type Scope = \"global\" | \"project\" | \"team\" | \"org\";\n\nexport interface ResolvedScope {\n scope: Scope;\n service: string;\n projectPath?: string;\n teamId?: string;\n orgId?: string;\n}\n\nexport function globalService(): string {\n return `${SERVICE_PREFIX}:global`;\n}\n\nexport function projectService(projectPath: string): string {\n const hash = hashProjectPath(projectPath);\n return `${SERVICE_PREFIX}:project:${hash}`;\n}\n\nexport function teamService(teamId: string): string {\n return `${SERVICE_PREFIX}:team:${teamId}`;\n}\n\nexport function orgService(orgId: string): string {\n return `${SERVICE_PREFIX}:org:${orgId}`;\n}\n\nexport interface ScopeOpts {\n scope?: Scope;\n projectPath?: string;\n teamId?: string;\n orgId?: string;\n}\n\n/**\n * Resolution order (most specific first):\n * project → team → org → global\n *\n * When a scope is explicitly requested, only that scope is returned.\n * When no scope is specified, the full resolution chain is built so\n * project-level secrets override team, which override org, which\n * override global.\n */\nexport function resolveScope(opts: ScopeOpts): ResolvedScope[] {\n const { scope, projectPath, teamId, orgId } = opts;\n\n if (scope === \"global\") {\n return [{ scope: \"global\", service: globalService() }];\n }\n\n if (scope === \"project\") {\n if (!projectPath) throw new Error(\"Project path is required for project scope\");\n return [{ scope: \"project\", service: projectService(projectPath), projectPath }];\n }\n\n if (scope === \"team\") {\n if (!teamId) throw new Error(\"Team ID is required for team scope\");\n return [{ scope: \"team\", service: teamService(teamId), teamId }];\n }\n\n if (scope === \"org\") {\n if (!orgId) throw new Error(\"Org ID is required for org scope\");\n return [{ scope: \"org\", service: orgService(orgId), orgId }];\n }\n\n const chain: ResolvedScope[] = [];\n\n if (projectPath) {\n chain.push({ scope: \"project\", service: projectService(projectPath), projectPath });\n }\n if (teamId) {\n chain.push({ scope: \"team\", service: teamService(teamId), teamId });\n }\n if (orgId) {\n chain.push({ scope: \"org\", service: orgService(orgId), orgId });\n }\n\n chain.push({ scope: \"global\", service: globalService() });\n return chain;\n}\n\nexport function parseServiceName(service: string): ResolvedScope {\n if (service === globalService()) {\n return { scope: \"global\", service };\n }\n if (service.startsWith(`${SERVICE_PREFIX}:project:`)) {\n return { scope: \"project\", service };\n }\n if (service.startsWith(`${SERVICE_PREFIX}:team:`)) {\n const teamId = service.slice(`${SERVICE_PREFIX}:team:`.length);\n return { scope: \"team\", service, teamId };\n }\n if (service.startsWith(`${SERVICE_PREFIX}:org:`)) {\n const orgId = service.slice(`${SERVICE_PREFIX}:org:`.length);\n return { scope: \"org\", service, orgId };\n }\n return { scope: \"global\", service };\n}\n","/**\n * Hook system: fire callbacks when secrets are created, updated, or deleted.\n * Supports shell commands, HTTP webhooks, and process signals.\n *\n * Registry stored at ~/.config/q-ring/hooks.json\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { exec } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { lookup } from \"node:dns/promises\";\nimport { httpRequest_ } from \"../utils/http-request.js\";\nimport { logAudit } from \"./observer.js\";\n\nexport type HookType = \"shell\" | \"http\" | \"signal\";\nexport type HookAction = \"write\" | \"delete\" | \"rotate\";\n\nexport interface HookMatch {\n key?: string;\n keyPattern?: string;\n tag?: string;\n scope?: \"global\" | \"project\";\n action?: HookAction[];\n}\n\nexport interface HookEntry {\n id: string;\n type: HookType;\n match: HookMatch;\n command?: string;\n url?: string;\n signal?: { target: string; signal?: string };\n description?: string;\n createdAt: string;\n enabled: boolean;\n}\n\nexport interface HookPayload {\n action: HookAction;\n key: string;\n scope: string;\n timestamp: string;\n source: \"cli\" | \"mcp\" | \"agent\" | \"api\" | \"hook\" | \"ci\";\n}\n\nexport interface HookResult {\n hookId: string;\n success: boolean;\n message: string;\n}\n\ninterface HookRegistry {\n hooks: HookEntry[];\n}\n\nfunction getRegistryPath(): string {\n const dir = join(homedir(), \".config\", \"q-ring\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return join(dir, \"hooks.json\");\n}\n\nfunction loadRegistry(): HookRegistry {\n const path = getRegistryPath();\n if (!existsSync(path)) {\n return { hooks: [] };\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return { hooks: [] };\n }\n}\n\nfunction saveRegistry(registry: HookRegistry): void {\n writeFileSync(getRegistryPath(), JSON.stringify(registry, null, 2));\n}\n\nexport function registerHook(\n entry: Omit<HookEntry, \"id\" | \"createdAt\">,\n): HookEntry {\n const registry = loadRegistry();\n const hook: HookEntry = {\n ...entry,\n id: randomUUID().slice(0, 8),\n createdAt: new Date().toISOString(),\n };\n registry.hooks.push(hook);\n saveRegistry(registry);\n return hook;\n}\n\nexport function removeHook(id: string): boolean {\n const registry = loadRegistry();\n const before = registry.hooks.length;\n registry.hooks = registry.hooks.filter((h) => h.id !== id);\n if (registry.hooks.length < before) {\n saveRegistry(registry);\n return true;\n }\n return false;\n}\n\nexport function listHooks(): HookEntry[] {\n return loadRegistry().hooks;\n}\n\nexport function enableHook(id: string): boolean {\n const registry = loadRegistry();\n const hook = registry.hooks.find((h) => h.id === id);\n if (!hook) return false;\n hook.enabled = true;\n saveRegistry(registry);\n return true;\n}\n\nexport function disableHook(id: string): boolean {\n const registry = loadRegistry();\n const hook = registry.hooks.find((h) => h.id === id);\n if (!hook) return false;\n hook.enabled = false;\n saveRegistry(registry);\n return true;\n}\n\nfunction matchesHook(\n hook: HookEntry,\n payload: HookPayload,\n tags?: string[],\n): boolean {\n if (!hook.enabled) return false;\n\n const m = hook.match;\n\n if (m.action?.length && !m.action.includes(payload.action)) return false;\n\n if (m.key && m.key !== payload.key) return false;\n\n if (m.keyPattern) {\n const regex = new RegExp(\n \"^\" + m.keyPattern.replace(/\\*/g, \".*\") + \"$\",\n \"i\",\n );\n if (!regex.test(payload.key)) return false;\n }\n\n if (m.tag && (!tags || !tags.includes(m.tag))) return false;\n\n if (m.scope && m.scope !== payload.scope) return false;\n\n return true;\n}\n\nfunction executeShell(command: string, payload: HookPayload): Promise<HookResult> {\n return new Promise((resolve) => {\n const env = {\n ...process.env,\n QRING_HOOK_KEY: payload.key,\n QRING_HOOK_ACTION: payload.action,\n QRING_HOOK_SCOPE: payload.scope,\n };\n\n exec(command, { timeout: 30000, env }, (err, stdout, stderr) => {\n if (err) {\n resolve({ hookId: \"\", success: false, message: `Shell error: ${err.message}` });\n } else {\n resolve({ hookId: \"\", success: true, message: stdout.trim() || \"OK\" });\n }\n });\n });\n}\n\nfunction isPrivateIP(ip: string): boolean {\n // Normalize IPv4-mapped IPv6 addresses (e.g. ::ffff:127.0.0.1)\n const octet = \"(?:25[0-5]|2[0-4]\\\\d|1?\\\\d{1,2})\";\n const ipv4Re = new RegExp(`^::ffff:(${octet}\\\\.${octet}\\\\.${octet}\\\\.${octet})$`, \"i\");\n const ipv4Mapped = ip.match(ipv4Re);\n if (ipv4Mapped) return isPrivateIP(ipv4Mapped[1]);\n\n // IPv4 private/loopback/link-local\n if (/^127\\./.test(ip)) return true;\n if (/^10\\./.test(ip)) return true;\n if (/^172\\.(1[6-9]|2\\d|3[01])\\./.test(ip)) return true;\n if (/^192\\.168\\./.test(ip)) return true;\n if (/^169\\.254\\./.test(ip)) return true;\n if (ip === \"0.0.0.0\") return true;\n // IPv6 loopback and private\n if (ip === \"::1\" || ip === \"::\") return true;\n if (/^f[cd][0-9a-f]{2}:/i.test(ip)) return true;\n if (/^fe80:/i.test(ip)) return true;\n return false;\n}\n\nasync function checkSSRF(url: string): Promise<string | null> {\n if (process.env.Q_RING_ALLOW_PRIVATE_HOOKS === \"1\") return null;\n\n try {\n const parsed = new URL(url);\n const hostname = parsed.hostname.replace(/^\\[|\\]$/g, \"\");\n\n // If the hostname is already an IP literal, check it directly.\n if (isPrivateIP(hostname)) {\n return `Blocked: hook URL resolves to private address (${hostname}). Set Q_RING_ALLOW_PRIVATE_HOOKS=1 to override.`;\n }\n\n // Resolve all addresses (A and AAAA) and block if any are private.\n const results = await lookup(hostname, { all: true });\n for (const { address } of results) {\n if (isPrivateIP(address)) {\n return `Blocked: hook URL \"${hostname}\" resolves to private address ${address}. Set Q_RING_ALLOW_PRIVATE_HOOKS=1 to override.`;\n }\n }\n } catch {\n // DNS failure will surface as a request error downstream\n }\n return null;\n}\n\nasync function executeHttp(url: string, payload: HookPayload): Promise<HookResult> {\n const ssrfBlock = await checkSSRF(url);\n if (ssrfBlock) {\n logAudit({\n action: \"policy_deny\",\n key: payload.key,\n scope: payload.scope,\n source: payload.source,\n detail: `hook SSRF blocked: ${url}`,\n });\n return { hookId: \"\", success: false, message: ssrfBlock };\n }\n\n try {\n const body = JSON.stringify(payload);\n const res = await httpRequest_({\n url,\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"q-ring-hooks/1.0\",\n },\n body,\n timeoutMs: 10_000,\n });\n return {\n hookId: \"\",\n success: res.statusCode >= 200 && res.statusCode < 300,\n message: `HTTP ${res.statusCode}`,\n };\n } catch (err) {\n return {\n hookId: \"\",\n success: false,\n message: err instanceof Error ? err.message : \"HTTP error\",\n };\n }\n}\n\nfunction executeSignal(\n target: string,\n signal: string = \"SIGHUP\",\n): Promise<HookResult> {\n return new Promise((resolve) => {\n const pid = parseInt(target, 10);\n if (!isNaN(pid)) {\n try {\n process.kill(pid, signal as NodeJS.Signals);\n resolve({ hookId: \"\", success: true, message: `Signal ${signal} sent to PID ${pid}` });\n } catch (err) {\n resolve({ hookId: \"\", success: false, message: `Signal error: ${err instanceof Error ? err.message : String(err)}` });\n }\n return;\n }\n\n exec(`pgrep -f \"${target}\"`, { timeout: 5000 }, (err, stdout) => {\n if (err || !stdout.trim()) {\n resolve({ hookId: \"\", success: false, message: `Process \"${target}\" not found` });\n return;\n }\n const pids = stdout.trim().split(\"\\n\").map((p) => parseInt(p.trim(), 10)).filter((p) => !isNaN(p));\n let sent = 0;\n for (const p of pids) {\n try {\n process.kill(p, signal as NodeJS.Signals);\n sent++;\n } catch { /* ignore dead PIDs */ }\n }\n resolve({ hookId: \"\", success: sent > 0, message: `Signal ${signal} sent to ${sent} process(es)` });\n });\n });\n}\n\nasync function executeHook(\n hook: HookEntry,\n payload: HookPayload,\n): Promise<HookResult> {\n let result: HookResult;\n\n switch (hook.type) {\n case \"shell\":\n result = hook.command\n ? await executeShell(hook.command, payload)\n : { hookId: hook.id, success: false, message: \"No command specified\" };\n break;\n case \"http\":\n result = hook.url\n ? await executeHttp(hook.url, payload)\n : { hookId: hook.id, success: false, message: \"No URL specified\" };\n break;\n case \"signal\":\n result = hook.signal\n ? await executeSignal(hook.signal.target, hook.signal.signal)\n : { hookId: hook.id, success: false, message: \"No signal target specified\" };\n break;\n default:\n result = { hookId: hook.id, success: false, message: `Unknown hook type: ${hook.type}` };\n }\n\n result.hookId = hook.id;\n return result;\n}\n\n/**\n * Fire all matching hooks for a given payload. Fire-and-forget — never blocks\n * the caller on hook failures.\n */\nexport async function fireHooks(\n payload: HookPayload,\n tags?: string[],\n): Promise<HookResult[]> {\n const hooks = listHooks();\n const matching = hooks.filter((h) => matchesHook(h, payload, tags));\n\n if (matching.length === 0) return [];\n\n const results = await Promise.allSettled(\n matching.map((h) => executeHook(h, payload)),\n );\n\n const hookResults: HookResult[] = [];\n for (const r of results) {\n if (r.status === \"fulfilled\") {\n hookResults.push(r.value);\n } else {\n hookResults.push({\n hookId: \"unknown\",\n success: false,\n message: r.reason?.message ?? \"Hook execution failed\",\n });\n }\n }\n\n for (const r of hookResults) {\n try {\n logAudit({\n action: \"write\",\n key: payload.key,\n scope: payload.scope,\n source: payload.source,\n detail: `hook:${r.hookId} ${r.success ? \"ok\" : \"fail\"} — ${r.message}`,\n });\n } catch { /* never crash on audit logging */ }\n }\n\n return hookResults;\n}\n","/**\n * Shared HTTP request helper with timeout and response body cap.\n * Used by validation providers and webhook hooks.\n */\n\nimport { request as httpsRequest } from \"node:https\";\nimport { request as httpRequest } from \"node:http\";\n\nexport interface HttpRequestOptions {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n body?: string;\n timeoutMs?: number;\n maxResponseBytes?: number;\n}\n\nexport interface HttpResponse {\n statusCode: number;\n body: string;\n truncated: boolean;\n}\n\nconst DEFAULT_TIMEOUT_MS = 10_000;\nconst DEFAULT_MAX_RESPONSE_BYTES = 65_536; // 64 KiB\n\nexport function httpRequest_(\n opts: HttpRequestOptions,\n): Promise<HttpResponse> {\n const {\n url,\n method = \"GET\",\n headers = {},\n body,\n timeoutMs = DEFAULT_TIMEOUT_MS,\n maxResponseBytes = DEFAULT_MAX_RESPONSE_BYTES,\n } = opts;\n\n return new Promise((resolve, reject) => {\n const parsed = new URL(url);\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n reject(new Error(`Unsupported URL protocol: ${parsed.protocol}`));\n return;\n }\n const reqFn = parsed.protocol === \"https:\" ? httpsRequest : httpRequest;\n\n const reqHeaders: Record<string, string | number> = { ...headers };\n if (body && !reqHeaders[\"Content-Length\"]) {\n reqHeaders[\"Content-Length\"] = Buffer.byteLength(body);\n }\n\n const req = reqFn(\n url,\n { method, headers: reqHeaders, timeout: timeoutMs },\n (res) => {\n const chunks: Buffer[] = [];\n let totalBytes = 0;\n let truncated = false;\n\n res.on(\"data\", (chunk: Buffer) => {\n totalBytes += chunk.length;\n if (totalBytes > maxResponseBytes) {\n truncated = true;\n res.destroy();\n return;\n }\n chunks.push(chunk);\n });\n\n let settled = false;\n const settle = (result: HttpResponse) => {\n if (!settled) { settled = true; resolve(result); }\n };\n const fail = (err: Error) => {\n if (!settled) { settled = true; reject(err); }\n };\n\n res.on(\"error\", (err) => fail(new Error(`Response error: ${err.message}`)));\n\n res.on(\"end\", () => {\n settle({\n statusCode: res.statusCode ?? 0,\n body: Buffer.concat(chunks).toString(\"utf8\"),\n truncated,\n });\n });\n\n res.on(\"close\", () => {\n settle({\n statusCode: res.statusCode ?? 0,\n body: Buffer.concat(chunks).toString(\"utf8\"),\n truncated,\n });\n });\n },\n );\n\n req.on(\"error\", (err) => reject(new Error(`Network error: ${err.message}`)));\n req.on(\"timeout\", () => {\n req.destroy();\n reject(new Error(\"Request timed out\"));\n });\n\n if (body) req.write(body);\n req.end();\n });\n}\n","/**\n * Stronger Approval Workflows (Zero-Trust Agent)\n *\n * Manages scoped, reasoned, time-limited approval tokens for accessing\n * protected secrets via MCP. Each token carries:\n * - Reason: why the approval was granted\n * - Workspace / session binding\n * - HMAC verification to prevent tampering\n * - Expiry enforcement\n *\n * Approvals are stored in a file so the CLI can grant them and the MCP\n * server can read and verify them.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createHmac, randomBytes } from \"node:crypto\";\n\nexport interface ApprovalEntry {\n id: string;\n key: string;\n scope: string;\n reason: string;\n grantedBy: string;\n grantedAt: string;\n expiresAt: string;\n workspace?: string;\n sessionId?: string;\n hmac: string;\n}\n\ninterface ApprovalRegistry {\n approvals: ApprovalEntry[];\n}\n\nfunction getHmacSecret(): string {\n const secretPath = join(homedir(), \".config\", \"q-ring\", \".approval-key\");\n const dir = join(homedir(), \".config\", \"q-ring\");\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n\n if (existsSync(secretPath)) {\n return readFileSync(secretPath, \"utf8\").trim();\n }\n const secret = randomBytes(32).toString(\"hex\");\n writeFileSync(secretPath, secret, { mode: 0o600 });\n return secret;\n}\n\nfunction computeHmac(entry: Omit<ApprovalEntry, \"hmac\">): string {\n const payload = `${entry.id}|${entry.key}|${entry.scope}|${entry.reason}|${entry.grantedBy}|${entry.grantedAt}|${entry.expiresAt}`;\n return createHmac(\"sha256\", getHmacSecret()).update(payload).digest(\"hex\");\n}\n\nfunction verifyHmac(entry: ApprovalEntry): boolean {\n const expected = computeHmac(entry);\n return expected === entry.hmac;\n}\n\nfunction getRegistryPath(): string {\n const dir = join(homedir(), \".config\", \"q-ring\");\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n return join(dir, \"approvals.json\");\n}\n\nfunction loadRegistry(): ApprovalRegistry {\n const path = getRegistryPath();\n if (!existsSync(path)) {\n return { approvals: [] };\n }\n try {\n return JSON.parse(readFileSync(path, \"utf8\"));\n } catch {\n return { approvals: [] };\n }\n}\n\nfunction saveRegistry(registry: ApprovalRegistry): void {\n writeFileSync(getRegistryPath(), JSON.stringify(registry, null, 2), { mode: 0o600 });\n}\n\nfunction cleanup(registry: ApprovalRegistry): void {\n const now = Date.now();\n registry.approvals = registry.approvals.filter(\n (a) => new Date(a.expiresAt).getTime() > now,\n );\n}\n\nexport interface GrantOptions {\n reason?: string;\n grantedBy?: string;\n workspace?: string;\n sessionId?: string;\n}\n\nexport function grantApproval(\n key: string,\n scope: string,\n ttlSeconds: number = 3600,\n grantOpts: GrantOptions = {},\n): ApprovalEntry {\n const registry = loadRegistry();\n cleanup(registry);\n\n const id = randomBytes(8).toString(\"hex\");\n const grantedAt = new Date().toISOString();\n const expiresAt = new Date(Date.now() + ttlSeconds * 1000).toISOString();\n\n const partial: Omit<ApprovalEntry, \"hmac\"> = {\n id,\n key,\n scope,\n reason: grantOpts.reason ?? \"no reason provided\",\n grantedBy: grantOpts.grantedBy ?? \"cli-user\",\n grantedAt,\n expiresAt,\n workspace: grantOpts.workspace,\n sessionId: grantOpts.sessionId,\n };\n\n const entry: ApprovalEntry = { ...partial, hmac: computeHmac(partial) };\n\n const existingIdx = registry.approvals.findIndex(\n (a) => a.key === key && a.scope === scope,\n );\n if (existingIdx >= 0) {\n registry.approvals[existingIdx] = entry;\n } else {\n registry.approvals.push(entry);\n }\n\n saveRegistry(registry);\n return entry;\n}\n\nexport function revokeApproval(key: string, scope: string): boolean {\n const registry = loadRegistry();\n const before = registry.approvals.length;\n registry.approvals = registry.approvals.filter(\n (a) => !(a.key === key && a.scope === scope),\n );\n saveRegistry(registry);\n return registry.approvals.length < before;\n}\n\nexport function hasApproval(key: string, scope: string): boolean {\n const registry = loadRegistry();\n const entry = registry.approvals.find(\n (a) => a.key === key && a.scope === scope,\n );\n if (!entry) return false;\n if (new Date(entry.expiresAt).getTime() < Date.now()) return false;\n if (!verifyHmac(entry)) return false;\n return true;\n}\n\nexport function getApprovalDetail(key: string, scope: string): ApprovalEntry | null {\n const registry = loadRegistry();\n const entry = registry.approvals.find(\n (a) => a.key === key && a.scope === scope,\n );\n if (!entry) return null;\n if (new Date(entry.expiresAt).getTime() < Date.now()) return null;\n return entry;\n}\n\nexport function listApprovals(): (ApprovalEntry & { valid: boolean; tampered: boolean })[] {\n const registry = loadRegistry();\n const now = Date.now();\n return registry.approvals.map((a) => ({\n ...a,\n valid: new Date(a.expiresAt).getTime() > now,\n tampered: !verifyHmac(a),\n }));\n}\n","/**\n * Just-In-Time (JIT) Credential Provisioning\n *\n * Dynamically generates short-lived credentials when requested, caching them\n * until they expire.\n */\n\nimport { execFileSync, spawnSync } from \"node:child_process\";\n\nexport interface ProvisionResult {\n value: string;\n expiresAt: string;\n}\n\nexport interface JitProvider {\n name: string;\n description: string;\n provision(configRaw: string): ProvisionResult;\n}\n\nexport class ProvisionRegistry {\n private providers = new Map<string, JitProvider>();\n\n register(provider: JitProvider): void {\n this.providers.set(provider.name, provider);\n }\n\n get(name: string): JitProvider | undefined {\n return this.providers.get(name);\n }\n\n listProviders(): JitProvider[] {\n return [...this.providers.values()];\n }\n}\n\n// Built-in Providers\n\nconst awsStsProvider: JitProvider = {\n name: \"aws-sts\",\n description: \"AWS STS AssumeRole (requires existing local AWS CLI credentials)\",\n provision(configRaw: string): ProvisionResult {\n let config: any;\n try {\n config = JSON.parse(configRaw);\n } catch {\n throw new Error(\"aws-sts requires valid JSON config (e.g. {\\\"roleArn\\\":\\\"arn:aws:...\\\"})\");\n }\n\n const roleArn = config.roleArn;\n const sessionName = config.sessionName || \"q-ring-agent\";\n const duration = config.durationSeconds || 3600;\n\n if (!roleArn) throw new Error(\"aws-sts requires roleArn in config\");\n\n try {\n const output = execFileSync(\"aws\", [\n \"sts\", \"assume-role\",\n \"--role-arn\", roleArn,\n \"--role-session-name\", sessionName,\n \"--duration-seconds\", String(duration),\n \"--output\", \"json\",\n ], { encoding: \"utf8\" });\n const parsed = JSON.parse(output);\n const creds = parsed.Credentials;\n \n const value = JSON.stringify({\n AWS_ACCESS_KEY_ID: creds.AccessKeyId,\n AWS_SECRET_ACCESS_KEY: creds.SecretAccessKey,\n AWS_SESSION_TOKEN: creds.SessionToken,\n });\n \n return {\n value,\n expiresAt: creds.Expiration\n };\n } catch (err) {\n throw new Error(`AWS STS provision failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n};\n\nconst httpProvider: JitProvider = {\n name: \"http\",\n description: \"Generic HTTP token endpoint using Node.js http/https\",\n provision(configRaw: string): ProvisionResult {\n let config: any;\n try {\n config = JSON.parse(configRaw);\n } catch {\n throw new Error(\"http provider requires valid JSON config\");\n }\n\n const url = config.url;\n const method = config.method || \"POST\";\n const valuePath = config.valuePath || \"token\"; // dot notation path to value\n const expiresInSeconds = config.expiresInSeconds || 3600;\n\n if (!url) throw new Error(\"http provider requires url in config\");\n\n const headers: Record<string, string> = {\n \"User-Agent\": \"q-ring-jit/1.0\",\n ...(config.headers ?? {}),\n };\n let bodyStr: string | undefined;\n if (config.body) {\n headers[\"Content-Type\"] = \"application/json\";\n bodyStr = JSON.stringify(config.body);\n }\n\n // Pass config via environment variable to avoid code interpolation\n const scriptConfig = JSON.stringify({ url, method, headers, bodyStr });\n\n // Static script that reads config from env var\n const script = `\nconst cfg = JSON.parse(process.env.__QRING_HTTP_CFG);\nconst parsedUrl = new URL(cfg.url);\nconst http = require(parsedUrl.protocol === \"https:\" ? \"node:https\" : \"node:http\");\nconst req = http.request(cfg.url, { method: cfg.method, headers: cfg.headers, timeout: 30000 }, (res) => {\n let body = \"\";\n res.on(\"data\", (chunk) => body += chunk);\n res.on(\"end\", () => process.stdout.write(body));\n});\nreq.on(\"error\", (e) => { process.stderr.write(e.message); process.exit(1); });\nif (cfg.bodyStr) req.write(cfg.bodyStr);\nreq.end();\n`;\n\n try {\n const result = spawnSync(\"node\", [\"-e\", script], {\n encoding: \"utf8\",\n timeout: 35000,\n env: { ...process.env, __QRING_HTTP_CFG: scriptConfig },\n });\n\n if (result.status !== 0) {\n throw new Error(result.stderr || \"HTTP request failed\");\n }\n\n const parsed = JSON.parse(result.stdout);\n let val = parsed;\n for (const key of valuePath.split(\".\")) {\n val = val[key];\n }\n return {\n value: String(val),\n expiresAt: new Date(Date.now() + expiresInSeconds * 1000).toISOString()\n };\n } catch (err) {\n throw new Error(`HTTP provision failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n};\n\nexport const registry = new ProvisionRegistry();\nregistry.register(awsStsProvider);\nregistry.register(httpProvider);\n","/**\n * Governance-As-Code Policy Engine\n *\n * Evaluates project-level policies declared in `.q-ring.json` under the\n * `policy` key. Enforces MCP tool gating, key/tag access restrictions,\n * exec allowlists, and mandatory metadata requirements.\n */\n\nimport { readProjectConfig } from \"./collapse.js\";\n\nexport interface PolicyConfig {\n mcp?: {\n allowTools?: string[];\n denyTools?: string[];\n readableKeys?: string[];\n deniedKeys?: string[];\n deniedTags?: string[];\n };\n exec?: {\n allowCommands?: string[];\n denyCommands?: string[];\n maxRuntimeSeconds?: number;\n allowNetwork?: boolean;\n };\n secrets?: {\n requireApprovalForTags?: string[];\n requireRotationFormatForTags?: string[];\n maxTtlSeconds?: number;\n };\n}\n\nexport interface PolicyDecision {\n allowed: boolean;\n reason?: string;\n policySource: string;\n}\n\nlet cachedPolicy: { path: string; policy: PolicyConfig } | null = null;\n\nexport function loadPolicy(projectPath?: string): PolicyConfig {\n const pp = projectPath ?? process.cwd();\n if (cachedPolicy && cachedPolicy.path === pp) {\n return cachedPolicy.policy;\n }\n\n const config = readProjectConfig(pp);\n const policy: PolicyConfig = (config as any)?.policy ?? {};\n cachedPolicy = { path: pp, policy };\n return policy;\n}\n\nexport function clearPolicyCache(): void {\n cachedPolicy = null;\n}\n\nexport function checkToolPolicy(toolName: string, projectPath?: string): PolicyDecision {\n const policy = loadPolicy(projectPath);\n if (!policy.mcp) return { allowed: true, policySource: \"no-policy\" };\n\n if (policy.mcp.denyTools?.includes(toolName)) {\n return {\n allowed: false,\n reason: `Tool \"${toolName}\" is denied by project policy`,\n policySource: \".q-ring.json policy.mcp.denyTools\",\n };\n }\n\n if (policy.mcp.allowTools && !policy.mcp.allowTools.includes(toolName)) {\n return {\n allowed: false,\n reason: `Tool \"${toolName}\" is not in the allowlist`,\n policySource: \".q-ring.json policy.mcp.allowTools\",\n };\n }\n\n return { allowed: true, policySource: \".q-ring.json\" };\n}\n\nexport function checkKeyReadPolicy(key: string, tags: string[] | undefined, projectPath?: string): PolicyDecision {\n const policy = loadPolicy(projectPath);\n if (!policy.mcp) return { allowed: true, policySource: \"no-policy\" };\n\n if (policy.mcp.deniedKeys?.includes(key)) {\n return {\n allowed: false,\n reason: `Key \"${key}\" is denied by project policy`,\n policySource: \".q-ring.json policy.mcp.deniedKeys\",\n };\n }\n\n if (policy.mcp.readableKeys && !policy.mcp.readableKeys.includes(key)) {\n return {\n allowed: false,\n reason: `Key \"${key}\" is not in the readable keys allowlist`,\n policySource: \".q-ring.json policy.mcp.readableKeys\",\n };\n }\n\n if (tags && policy.mcp.deniedTags) {\n const blocked = tags.find((t) => policy.mcp!.deniedTags!.includes(t));\n if (blocked) {\n return {\n allowed: false,\n reason: `Tag \"${blocked}\" is denied by project policy`,\n policySource: \".q-ring.json policy.mcp.deniedTags\",\n };\n }\n }\n\n return { allowed: true, policySource: \".q-ring.json\" };\n}\n\nexport function checkExecPolicy(command: string, projectPath?: string): PolicyDecision {\n const policy = loadPolicy(projectPath);\n if (!policy.exec) return { allowed: true, policySource: \"no-policy\" };\n\n if (policy.exec.denyCommands) {\n const denied = policy.exec.denyCommands.find((d) => command.includes(d));\n if (denied) {\n return {\n allowed: false,\n reason: `Command containing \"${denied}\" is denied by project policy`,\n policySource: \".q-ring.json policy.exec.denyCommands\",\n };\n }\n }\n\n if (policy.exec.allowCommands) {\n const allowed = policy.exec.allowCommands.some((a) => command.startsWith(a));\n if (!allowed) {\n return {\n allowed: false,\n reason: `Command \"${command}\" is not in the exec allowlist`,\n policySource: \".q-ring.json policy.exec.allowCommands\",\n };\n }\n }\n\n return { allowed: true, policySource: \".q-ring.json\" };\n}\n\nexport function getExecMaxRuntime(projectPath?: string): number | undefined {\n return loadPolicy(projectPath).exec?.maxRuntimeSeconds;\n}\n\nexport function getPolicySummary(projectPath?: string): {\n hasMcpPolicy: boolean;\n hasExecPolicy: boolean;\n hasSecretPolicy: boolean;\n details: PolicyConfig;\n} {\n const policy = loadPolicy(projectPath);\n return {\n hasMcpPolicy: !!policy.mcp,\n hasExecPolicy: !!policy.exec,\n hasSecretPolicy: !!policy.secrets,\n details: policy,\n };\n}\n","/**\n * Quantum Tunneling: ephemeral secrets that exist only in memory.\n *\n * Tunneled secrets are never persisted to the OS keyring. They live\n * in a process-scoped in-memory store with optional auto-expiry.\n * Useful for passing secrets between agents without touching disk.\n */\n\ninterface TunnelEntry {\n value: string;\n createdAt: number;\n expiresAt?: number;\n accessCount: number;\n /** Max number of reads before auto-destruct */\n maxReads?: number;\n}\n\nconst tunnelStore = new Map<string, TunnelEntry>();\n\nlet cleanupInterval: ReturnType<typeof setInterval> | null = null;\n\nfunction ensureCleanup(): void {\n if (cleanupInterval) return;\n cleanupInterval = setInterval(() => {\n const now = Date.now();\n for (const [id, entry] of tunnelStore) {\n if (entry.expiresAt && now >= entry.expiresAt) {\n tunnelStore.delete(id);\n }\n }\n if (tunnelStore.size === 0 && cleanupInterval) {\n clearInterval(cleanupInterval);\n cleanupInterval = null;\n }\n }, 5000);\n\n // Don't prevent process exit\n if (cleanupInterval && typeof cleanupInterval === \"object\" && \"unref\" in cleanupInterval) {\n cleanupInterval.unref();\n }\n}\n\nexport interface TunnelOptions {\n /** TTL in seconds */\n ttlSeconds?: number;\n /** Self-destruct after N reads */\n maxReads?: number;\n}\n\n/**\n * Create a tunneled (ephemeral) secret. Returns a tunnel ID.\n */\nexport function tunnelCreate(\n value: string,\n opts: TunnelOptions = {},\n): string {\n const id = `tun_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\n const now = Date.now();\n\n tunnelStore.set(id, {\n value,\n createdAt: now,\n expiresAt: opts.ttlSeconds ? now + opts.ttlSeconds * 1000 : undefined,\n accessCount: 0,\n maxReads: opts.maxReads,\n });\n\n ensureCleanup();\n return id;\n}\n\n/**\n * Read a tunneled secret by ID. Returns null if expired or not found.\n * Each read increments the access counter; auto-destructs after maxReads.\n */\nexport function tunnelRead(id: string): string | null {\n const entry = tunnelStore.get(id);\n if (!entry) return null;\n\n if (entry.expiresAt && Date.now() >= entry.expiresAt) {\n tunnelStore.delete(id);\n return null;\n }\n\n entry.accessCount++;\n\n if (entry.maxReads && entry.accessCount >= entry.maxReads) {\n const value = entry.value;\n tunnelStore.delete(id);\n return value;\n }\n\n return entry.value;\n}\n\n/**\n * Destroy a tunneled secret immediately.\n */\nexport function tunnelDestroy(id: string): boolean {\n return tunnelStore.delete(id);\n}\n\n/**\n * List all active tunnel IDs (never exposes values).\n */\nexport function tunnelList(): {\n id: string;\n createdAt: number;\n expiresAt?: number;\n accessCount: number;\n maxReads?: number;\n}[] {\n const now = Date.now();\n const result: ReturnType<typeof tunnelList> = [];\n\n for (const [id, entry] of tunnelStore) {\n if (entry.expiresAt && now >= entry.expiresAt) {\n tunnelStore.delete(id);\n continue;\n }\n result.push({\n id,\n createdAt: entry.createdAt,\n expiresAt: entry.expiresAt,\n accessCount: entry.accessCount,\n maxReads: entry.maxReads,\n });\n }\n\n return result;\n}\n"],"mappings":"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","names":["existsSync","readFileSync","join","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","registry","createHash","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","getRegistryPath","join","homedir","existsSync","mkdirSync","loadRegistry","readFileSync","saveRegistry","registry","writeFileSync","existsSync","readFileSync","writeFileSync","mkdirSync","join","homedir","getRegistryPath","loadRegistry","registry","loadRegistry"]}