🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

@sunaiva/gate

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sunaiva/gate - npm Package Compare versions

Comparing version
1.1.4
to
1.1.8
+61
dist/bypass/allow-file.d.ts
/**
* T06 — `.sunaiva-allow` file parser + validator.
*
* Project-local `.sunaiva-allow` is a JSON file at `<repo>/.sunaiva-allow`
* shaped like:
*
* {
* "version": 1,
* "entries": [
* {
* "fingerprint": "<64-char hex sha256>",
* "reason": "approved by sec-review #432",
* "added_by": "kinan",
* "added_at": "2026-05-15T10:00:00Z",
* "rule_id": "fin-007" // optional metadata
* }
* ]
* }
*
* **Constitutional immutability is enforced at read time.** Any entry whose
* `rule_id` is constitutional is dropped from the returned list and a
* stderr warning is logged. The file is left untouched on disk — the
* rejection is purely in-memory.
*
* Failure mode is fail-OPEN: a missing, unreadable, or malformed file
* returns an empty entry list. Enforcement continues without the
* allowlist. This matches the rule-engine's fail-OPEN behaviour on
* malformed `rules.json` (see `loadAllRules` in `engine/rule-engine.ts`).
*/
import { type AllowFileEntry } from "./fingerprint.js";
export interface AllowFileLoadResult {
/** Entries safe to use for bypass matching. */
entries: AllowFileEntry[];
/** Entries whose rule_id was constitutional (REJECTED). */
rejected_constitutional: AllowFileEntry[];
/** Entries that were structurally malformed (skipped silently). */
rejected_malformed: number;
/** Was the file present? (false if the project has no `.sunaiva-allow`). */
file_existed: boolean;
}
/**
* Parse a raw allow-file payload, validate every entry, and split into
* (safe / constitutional-rejected / malformed) buckets.
*
* `constitutional` is the canonical set of constitutional rule IDs (from
* `engine/immutability.ts#getConstitutionalRuleIds`). Passed in to keep
* this module dependency-light for unit testing.
*/
export declare function parseAllowFile(raw: unknown, constitutional: ReadonlySet<string>): Omit<AllowFileLoadResult, "file_existed">;
/**
* Load and validate `.sunaiva-allow` from disk.
*
* Fail-OPEN: a missing/unreadable/malformed file returns
* `{ entries: [], file_existed: false }` and never throws.
*
* Warnings are written to stderr (NOT thrown) when constitutional
* rule IDs appear in the file — this is informational so the user
* can clean their allowlist, but it never blocks enforcement.
*/
export declare function loadAllowFile(cwd?: string, constitutional?: ReadonlySet<string>): AllowFileLoadResult;
//# sourceMappingURL=allow-file.d.ts.map
{"version":3,"file":"allow-file.d.ts","sourceRoot":"","sources":["../../src/bypass/allow-file.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EACL,KAAK,cAAc,EAGpB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,mBAAmB;IAClC,+CAA+C;IAC/C,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,2DAA2D;IAC3D,uBAAuB,EAAE,cAAc,EAAE,CAAC;IAC1C,mEAAmE;IACnE,kBAAkB,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;CACvB;AA4BD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,GAAG,EAAE,OAAO,EACZ,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,IAAI,CAAC,mBAAmB,EAAE,cAAc,CAAC,CA2C3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,GAAG,GAAE,MAAsB,EAC3B,cAAc,GAAE,WAAW,CAAC,MAAM,CAAa,GAC9C,mBAAmB,CAkCrB"}
/**
* T06 — `.sunaiva-allow` file parser + validator.
*
* Project-local `.sunaiva-allow` is a JSON file at `<repo>/.sunaiva-allow`
* shaped like:
*
* {
* "version": 1,
* "entries": [
* {
* "fingerprint": "<64-char hex sha256>",
* "reason": "approved by sec-review #432",
* "added_by": "kinan",
* "added_at": "2026-05-15T10:00:00Z",
* "rule_id": "fin-007" // optional metadata
* }
* ]
* }
*
* **Constitutional immutability is enforced at read time.** Any entry whose
* `rule_id` is constitutional is dropped from the returned list and a
* stderr warning is logged. The file is left untouched on disk — the
* rejection is purely in-memory.
*
* Failure mode is fail-OPEN: a missing, unreadable, or malformed file
* returns an empty entry list. Enforcement continues without the
* allowlist. This matches the rule-engine's fail-OPEN behaviour on
* malformed `rules.json` (see `loadAllRules` in `engine/rule-engine.ts`).
*/
import { existsSync } from "node:fs";
import { readAllowFileRaw, resolveAllowFilePath, } from "./fingerprint.js";
const FP_HEX_REGEX = /^[0-9a-f]{16,}$/i;
function isPlainObject(v) {
return typeof v === "object" && v !== null && !Array.isArray(v);
}
function validateEntry(raw) {
if (!isPlainObject(raw))
return null;
const fp = raw["fingerprint"];
const reason = raw["reason"];
const added_by = raw["added_by"];
const added_at = raw["added_at"];
if (typeof fp !== "string" || !FP_HEX_REGEX.test(fp))
return null;
if (typeof reason !== "string")
return null;
if (typeof added_by !== "string")
return null;
if (typeof added_at !== "string")
return null;
const entry = {
fingerprint: fp.toLowerCase(),
reason,
added_by,
added_at,
};
if (typeof raw["rule_id"] === "string")
entry.rule_id = raw["rule_id"];
return entry;
}
/**
* Parse a raw allow-file payload, validate every entry, and split into
* (safe / constitutional-rejected / malformed) buckets.
*
* `constitutional` is the canonical set of constitutional rule IDs (from
* `engine/immutability.ts#getConstitutionalRuleIds`). Passed in to keep
* this module dependency-light for unit testing.
*/
export function parseAllowFile(raw, constitutional) {
const out = [];
const rejectedConst = [];
let rejectedMalformed = 0;
if (!isPlainObject(raw)) {
// top-level not an object → treat as empty
return {
entries: out,
rejected_constitutional: rejectedConst,
rejected_malformed: rejectedMalformed,
};
}
const entriesRaw = raw["entries"];
if (!Array.isArray(entriesRaw)) {
return {
entries: out,
rejected_constitutional: rejectedConst,
rejected_malformed: rejectedMalformed,
};
}
for (const raw_entry of entriesRaw) {
const e = validateEntry(raw_entry);
if (e === null) {
rejectedMalformed += 1;
continue;
}
// Constitutional rejection: if the entry's metadata declares
// a constitutional rule_id, refuse to honour it.
if (e.rule_id && constitutional.has(e.rule_id)) {
rejectedConst.push(e);
continue;
}
out.push(e);
}
return {
entries: out,
rejected_constitutional: rejectedConst,
rejected_malformed: rejectedMalformed,
};
}
/**
* Load and validate `.sunaiva-allow` from disk.
*
* Fail-OPEN: a missing/unreadable/malformed file returns
* `{ entries: [], file_existed: false }` and never throws.
*
* Warnings are written to stderr (NOT thrown) when constitutional
* rule IDs appear in the file — this is informational so the user
* can clean their allowlist, but it never blocks enforcement.
*/
export function loadAllowFile(cwd = process.cwd(), constitutional = new Set()) {
const path = resolveAllowFilePath(cwd);
// existsSync is the source of truth for `file_existed`. A malformed-but-
// present file still has file_existed: true; the entries array is empty
// because readAllowFileRaw returned null on parse failure.
const fileExisted = existsSync(path);
const raw = readAllowFileRaw(path);
if (raw === null) {
return {
entries: [],
rejected_constitutional: [],
rejected_malformed: 0,
file_existed: fileExisted,
};
}
const parsed = parseAllowFile(raw, constitutional);
if (parsed.rejected_constitutional.length > 0) {
const ids = parsed.rejected_constitutional
.map((e) => e.rule_id ?? "?")
.join(", ");
process.stderr.write(`[sunaiva-gate] WARN: .sunaiva-allow contained ${parsed.rejected_constitutional.length} ` +
`entry(ies) referencing constitutional rule(s) [${ids}]. ` +
`These are REJECTED — constitutional rules cannot be bypassed via fingerprint.\n`);
}
return {
...parsed,
file_existed: true,
};
}
//# sourceMappingURL=allow-file.js.map
{"version":3,"file":"allow-file.js","sourceRoot":"","sources":["../../src/bypass/allow-file.ts"],"names":[],"mappings":"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"}
/**
* T06 — `.sunaiva-allow` fingerprint suppression.
*
* Pattern stolen from gitleaks's `.gitleaksignore` discipline (R3 §4.2).
*
* A fingerprint is a deterministic hex hash of the tuple
* (rule_id | action | target? | context?)
*
* stored project-locally in `<repo>/.sunaiva-allow`. On match, the action
* bypasses with `bypass_reason: "fingerprint"` recorded in the audit log.
*
* **Constitutional immutability remains absolute.** Fingerprints whose
* `rule_id` is constitutional are REJECTED at read time — they never enter
* the lookup map. A warning is logged to stderr but the file load itself
* is fail-OPEN (the rest of the allowlist is honoured).
*/
/**
* Compute a fingerprint for the bypass tuple.
*
* The hash is SHA-256 over the joined components separated by a NUL byte
* (` `) to prevent ambiguity between e.g. `("a|b", "c")` and
* `("a", "b|c")`. Output is the lower-cased hex digest, 64 chars.
*
* Determinism contract:
* - Same input → same output across processes / OSes / Node versions.
* - Order of properties on the input object DOES NOT matter (we read
* them by name).
*/
export interface FingerprintInput {
rule_id: string;
action: string;
target?: string;
context?: string;
}
export declare function computeFingerprint(input: FingerprintInput): string;
/**
* One entry inside `.sunaiva-allow`. The `fingerprint` is the SHA-256 hex.
* The metadata fields (reason / added_by / added_at) are informational —
* the engine only matches on `fingerprint`.
*/
export interface AllowFileEntry {
fingerprint: string;
reason: string;
added_by: string;
added_at: string;
/** Optional: which rule this fingerprint was originally created against.
* Used for the constitutional-rejection check at file-load time. */
rule_id?: string;
}
/**
* Look up a fingerprint in the entries array. O(n) but n is typically
* small (single-digit to low-double-digit). Returns the FIRST match — if
* multiple entries share a fingerprint, the first wins.
*/
export declare function findMatch(fp: string, entries: AllowFileEntry[]): AllowFileEntry | null;
/**
* Helper for engine-callers that have a {rule_id, action, context} triple
* and want the canonical fingerprint without re-stating shape.
*/
export declare function fingerprintFor(rule_id: string, action: string, context?: string, target?: string): string;
/**
* Resolve the project-local `.sunaiva-allow` file path for a given cwd.
* Returns the absolute path even if the file does not exist; callers must
* `existsSync` before reading.
*/
export declare function resolveAllowFilePath(cwd?: string): string;
/**
* Convenience predicate — does the project at `cwd` have an allow file?
*/
export declare function hasAllowFile(cwd?: string): boolean;
/**
* Raw JSON read of the allow file. Returns parsed entries or `null` if the
* file is missing or unparseable (fail-OPEN — the engine continues without
* the allowlist). Validation against constitutional rules happens in
* `allow-file.ts#parseAllowFile`.
*/
export declare function readAllowFileRaw(path: string): unknown;
//# sourceMappingURL=fingerprint.d.ts.map
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../src/bypass/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CASlE;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB;yEACqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,cAAc,EAAE,GACxB,cAAc,GAAG,IAAI,CAKvB;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE,MAAM,EAChB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAER;AAMD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAsB,GAAG,MAAM,CAExE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAEjE;AAMD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUtD"}
/**
* T06 — `.sunaiva-allow` fingerprint suppression.
*
* Pattern stolen from gitleaks's `.gitleaksignore` discipline (R3 §4.2).
*
* A fingerprint is a deterministic hex hash of the tuple
* (rule_id | action | target? | context?)
*
* stored project-locally in `<repo>/.sunaiva-allow`. On match, the action
* bypasses with `bypass_reason: "fingerprint"` recorded in the audit log.
*
* **Constitutional immutability remains absolute.** Fingerprints whose
* `rule_id` is constitutional are REJECTED at read time — they never enter
* the lookup map. A warning is logged to stderr but the file load itself
* is fail-OPEN (the rest of the allowlist is honoured).
*/
import { createHash } from "node:crypto";
import { readFileSync, existsSync } from "node:fs";
import { join, resolve } from "node:path";
export function computeFingerprint(input) {
const parts = [
input.rule_id,
input.action,
input.target ?? "",
input.context ?? "",
];
const joined = parts.join(" ");
return createHash("sha256").update(joined, "utf-8").digest("hex");
}
/**
* Look up a fingerprint in the entries array. O(n) but n is typically
* small (single-digit to low-double-digit). Returns the FIRST match — if
* multiple entries share a fingerprint, the first wins.
*/
export function findMatch(fp, entries) {
for (const e of entries) {
if (e.fingerprint === fp)
return e;
}
return null;
}
// ---------------------------------------------------------------------------
// Build a fingerprint from the same input the engine sees
// ---------------------------------------------------------------------------
/**
* Helper for engine-callers that have a {rule_id, action, context} triple
* and want the canonical fingerprint without re-stating shape.
*/
export function fingerprintFor(rule_id, action, context, target) {
return computeFingerprint({ rule_id, action, target, context });
}
// ---------------------------------------------------------------------------
// Path resolution
// ---------------------------------------------------------------------------
/**
* Resolve the project-local `.sunaiva-allow` file path for a given cwd.
* Returns the absolute path even if the file does not exist; callers must
* `existsSync` before reading.
*/
export function resolveAllowFilePath(cwd = process.cwd()) {
return resolve(join(cwd, ".sunaiva-allow"));
}
/**
* Convenience predicate — does the project at `cwd` have an allow file?
*/
export function hasAllowFile(cwd = process.cwd()) {
return existsSync(resolveAllowFilePath(cwd));
}
// ---------------------------------------------------------------------------
// File loader (delegates to allow-file.ts for parse/validate)
// ---------------------------------------------------------------------------
/**
* Raw JSON read of the allow file. Returns parsed entries or `null` if the
* file is missing or unparseable (fail-OPEN — the engine continues without
* the allowlist). Validation against constitutional rules happens in
* `allow-file.ts#parseAllowFile`.
*/
export function readAllowFileRaw(path) {
if (!existsSync(path))
return null;
try {
const raw = readFileSync(path, "utf-8");
return JSON.parse(raw);
}
catch {
// Fail-OPEN: malformed allow file does not block enforcement. A
// warning is logged from parseAllowFile when this happens.
return null;
}
}
//# sourceMappingURL=fingerprint.js.map
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/bypass/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqB1C,MAAM,UAAU,kBAAkB,CAAC,KAAuB;IACxD,MAAM,KAAK,GAAG;QACZ,KAAK,CAAC,OAAO;QACb,KAAK,CAAC,MAAM;QACZ,KAAK,CAAC,MAAM,IAAI,EAAE;QAClB,KAAK,CAAC,OAAO,IAAI,EAAE;KACpB,CAAC;IACF,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACpE,CAAC;AAiBD;;;;GAIG;AACH,MAAM,UAAU,SAAS,CACvB,EAAU,EACV,OAAyB;IAEzB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,WAAW,KAAK,EAAE;YAAE,OAAO,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,8EAA8E;AAC9E,0DAA0D;AAC1D,8EAA8E;AAE9E;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAe,EACf,MAAc,EACd,OAAgB,EAChB,MAAe;IAEf,OAAO,kBAAkB,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IAC9D,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,OAAO,CAAC,GAAG,EAAE;IACtD,OAAO,UAAU,CAAC,oBAAoB,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,8EAA8E;AAC9E,8DAA8D;AAC9D,8EAA8E;AAE9E;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,gEAAgE;QAChE,2DAA2D;QAC3D,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
/**
* T05 — SUNAIVA_SKIP env-var granular bypass.
*
* Pattern stolen from pre-commit's `SKIP=hook_id1,hook_id2` discipline (R3 §4.1).
*
* Parses the comma-separated rule IDs listed in `SUNAIVA_SKIP` into a Set
* used by the engine to short-circuit individual rules' evaluation.
*
* **Constitutional immutability is absolute.** Constitutional rule IDs in
* the skip set are silently dropped — they CANNOT be bypassed. This mirrors
* the existing log_bypass / update_rules guard (`src/engine/immutability.ts`)
* and is checked at both parse-time (`filterSkippableSet`) and call-site
* (`isConstitutional` is re-asserted on every lookup as defense in depth).
*
* Format:
* SUNAIVA_SKIP=fin-001,sec-002 → Set { "fin-001", "sec-002" }
* SUNAIVA_SKIP=" fin-001 , sec-002 " → Set { "fin-001", "sec-002" } (trim)
* SUNAIVA_SKIP= → empty Set
* SUNAIVA_SKIP unset → empty Set
* SUNAIVA_SKIP=fin-001,,sec-002 → Set { "fin-001", "sec-002" } (skip empties)
*/
/**
* Parse the raw env-var value into a Set of rule IDs.
*
* **No constitutional check happens here** — the parse returns whatever
* the user wrote. Filtering is done by `filterSkippableSet` so that a
* caller who wants to AUDIT a user's intent (including refused attempts
* to skip constitutional rules) sees the raw declared set first.
*/
export declare function parseSkipEnv(envValue: string | undefined): Set<string>;
/**
* Test predicate — is this rule ID protected by constitutional immutability?
*
* Takes the constitutional set as an explicit parameter (rather than
* importing from `engine/immutability.ts`) so that this module stays
* dependency-free for unit testing.
*/
export declare function isConstitutional(ruleId: string, constitutional: ReadonlySet<string>): boolean;
/**
* Return the subset of `requested` IDs that are SAFE to skip.
* Constitutional IDs are dropped — they cannot be bypassed.
*
* The dropped IDs are returned via the `refused` array so the caller
* can log a `bypass_reason: "SUNAIVA_SKIP_REFUSED_CONSTITUTIONAL"`
* audit entry per Rule 26 + R3 §1.5.
*/
export declare function filterSkippableSet(requested: Set<string>, constitutional: ReadonlySet<string>): {
allowed: Set<string>;
refused: string[];
};
/**
* Convenience entry-point reading `process.env.SUNAIVA_SKIP`. Tests should
* call `parseSkipEnv(value)` directly; production callers use this.
*/
export declare function readSkipFromEnv(env?: NodeJS.ProcessEnv): Set<string>;
//# sourceMappingURL=skip-env.d.ts.map
{"version":3,"file":"skip-env.d.ts","sourceRoot":"","sources":["../../src/bypass/skip-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAQtE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,OAAO,CAET;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,EACtB,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC;IAAE,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAW7C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,GAAG,CAAC,MAAM,CAAC,CAEb"}
/**
* T05 — SUNAIVA_SKIP env-var granular bypass.
*
* Pattern stolen from pre-commit's `SKIP=hook_id1,hook_id2` discipline (R3 §4.1).
*
* Parses the comma-separated rule IDs listed in `SUNAIVA_SKIP` into a Set
* used by the engine to short-circuit individual rules' evaluation.
*
* **Constitutional immutability is absolute.** Constitutional rule IDs in
* the skip set are silently dropped — they CANNOT be bypassed. This mirrors
* the existing log_bypass / update_rules guard (`src/engine/immutability.ts`)
* and is checked at both parse-time (`filterSkippableSet`) and call-site
* (`isConstitutional` is re-asserted on every lookup as defense in depth).
*
* Format:
* SUNAIVA_SKIP=fin-001,sec-002 → Set { "fin-001", "sec-002" }
* SUNAIVA_SKIP=" fin-001 , sec-002 " → Set { "fin-001", "sec-002" } (trim)
* SUNAIVA_SKIP= → empty Set
* SUNAIVA_SKIP unset → empty Set
* SUNAIVA_SKIP=fin-001,,sec-002 → Set { "fin-001", "sec-002" } (skip empties)
*/
/**
* Parse the raw env-var value into a Set of rule IDs.
*
* **No constitutional check happens here** — the parse returns whatever
* the user wrote. Filtering is done by `filterSkippableSet` so that a
* caller who wants to AUDIT a user's intent (including refused attempts
* to skip constitutional rules) sees the raw declared set first.
*/
export function parseSkipEnv(envValue) {
if (!envValue)
return new Set();
const out = new Set();
for (const raw of envValue.split(",")) {
const id = raw.trim();
if (id)
out.add(id);
}
return out;
}
/**
* Test predicate — is this rule ID protected by constitutional immutability?
*
* Takes the constitutional set as an explicit parameter (rather than
* importing from `engine/immutability.ts`) so that this module stays
* dependency-free for unit testing.
*/
export function isConstitutional(ruleId, constitutional) {
return constitutional.has(ruleId);
}
/**
* Return the subset of `requested` IDs that are SAFE to skip.
* Constitutional IDs are dropped — they cannot be bypassed.
*
* The dropped IDs are returned via the `refused` array so the caller
* can log a `bypass_reason: "SUNAIVA_SKIP_REFUSED_CONSTITUTIONAL"`
* audit entry per Rule 26 + R3 §1.5.
*/
export function filterSkippableSet(requested, constitutional) {
const allowed = new Set();
const refused = [];
for (const id of requested) {
if (isConstitutional(id, constitutional)) {
refused.push(id);
}
else {
allowed.add(id);
}
}
return { allowed, refused };
}
/**
* Convenience entry-point reading `process.env.SUNAIVA_SKIP`. Tests should
* call `parseSkipEnv(value)` directly; production callers use this.
*/
export function readSkipFromEnv(env = process.env) {
return parseSkipEnv(env["SUNAIVA_SKIP"]);
}
//# sourceMappingURL=skip-env.js.map
{"version":3,"file":"skip-env.js","sourceRoot":"","sources":["../../src/bypass/skip-env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,QAA4B;IACvD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAChC,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,MAAM,EAAE,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,EAAE;YAAE,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,cAAmC;IAEnC,OAAO,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAsB,EACtB,cAAmC;IAEnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,EAAE,IAAI,SAAS,EAAE,CAAC;QAC3B,IAAI,gBAAgB,CAAC,EAAE,EAAE,cAAc,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC9B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;AAC3C,CAAC"}
/**
* Re-export shim for the legacy compliance-dossier engine.
*
* The compiled dist/compliance/dossier.js imports from
* "../tools/compliance-dossier.legacy.js" — i.e. dist/tools/compliance-dossier.legacy.js.
* That file is currently parked at dist/_v1.2.0_pending/tools/compliance-dossier.legacy.js
* and does not yet have a src/tools/compliance-dossier.legacy.ts counterpart
* (writing outside src/compliance/ is out of scope for this build pass).
*
* This shim re-declares the minimum public contract needed by src/compliance/*.ts
* so the TypeScript compiler resolves types cleanly. When the orchestrator wires
* the legacy file into src/tools/ (next pass), swap the import in dossier.ts /
* exporters/json.ts / exporters/pdf.ts back to "../tools/compliance-dossier.legacy.js".
*
* IMPORTANT: The runtime import in dossier.ts MUST point at the actual
* compiled JS location. The shim approach below declares types only — the
* runtime import resolves via the .js extension to whatever dist/tools path
* the orchestrator places the file.
*/
export interface DossierEvent {
timestamp: string;
event_type: string;
artifact_id?: string;
tier?: string | null;
reason?: string;
audit_status?: string;
evidence?: Record<string, unknown> | null;
violations?: string[];
command_preview?: string;
bypass_reason?: string;
upgrade_hint?: string;
}
export interface DossierVerdict {
verdict_id?: string;
level?: string;
signed_at?: string;
signature?: string;
signature_algorithm?: string;
product_name?: string;
property_layer?: Record<string, unknown>;
adversarial_layer?: Record<string, unknown>;
cross_provider?: Record<string, unknown>;
}
export interface DossierStats {
total_events: number;
allows: number;
blocks: number;
bypasses: number;
dry_runs: number;
errors: number;
paid_tier_allows: number;
free_tier_allows: number;
constitutional_violations: number;
}
export interface DossierManifest {
schema_version: string;
tool: string;
tool_version: string;
generated_at: string;
product: string;
period: {
from: string;
to: string;
};
stats: DossierStats;
article_evidence: {
art_12_logging: {
satisfied: boolean;
notes: string;
};
art_13_transparency: {
satisfied: boolean;
notes: string;
};
art_14_human_oversight: {
satisfied: boolean;
notes: string;
};
art_15_accuracy_robustness: {
satisfied: boolean;
notes: string;
};
art_15_cybersecurity: {
satisfied: boolean;
notes: string;
};
};
constitutional_rules: {
count: number;
ids: string[];
hash: string;
};
events: DossierEvent[];
override_audit: DossierEvent[];
verdicts: DossierVerdict[];
bundle_hash_algorithm: "sha256";
signature_algorithm: "HMAC-SHA256";
}
export interface SignedDossierManifest extends DossierManifest {
signature?: string;
signing_key_env?: string;
signing_warning?: string;
}
export interface GenerateDossierResult {
pdfPath: string | null;
signedJsonPath: string;
manifest: SignedDossierManifest;
warnings: string[];
}
export interface LegacyDossierOptions {
product: string;
from: string;
to: string;
output: string;
auditLogPath?: string;
verdictDir?: string;
env?: NodeJS.ProcessEnv;
signingKeyEnv?: string;
skipPdf?: boolean;
}
/**
* Runtime re-export. This file uses a dynamic require-style resolution so that
* the TypeScript compiler can check types while the actual runtime path (once
* the orchestrator places the legacy file at src/tools/) remains correct.
*
* NOTE: `generateComplianceDossier` is declared here as `never` for type-check
* purposes only — the actual callable is re-exported from the runtime shim below.
* Replace with the direct import once src/tools/compliance-dossier.legacy.ts exists.
*/
export declare function generateComplianceDossier(opts: LegacyDossierOptions): Promise<GenerateDossierResult>;
//# sourceMappingURL=_legacy-shim.d.ts.map
{"version":3,"file":"_legacy-shim.d.ts","sourceRoot":"","sources":["../../src/compliance/_legacy-shim.ts"],"names":[],"mappings":"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"}
/**
* Re-export shim for the legacy compliance-dossier engine.
*
* The compiled dist/compliance/dossier.js imports from
* "../tools/compliance-dossier.legacy.js" — i.e. dist/tools/compliance-dossier.legacy.js.
* That file is currently parked at dist/_v1.2.0_pending/tools/compliance-dossier.legacy.js
* and does not yet have a src/tools/compliance-dossier.legacy.ts counterpart
* (writing outside src/compliance/ is out of scope for this build pass).
*
* This shim re-declares the minimum public contract needed by src/compliance/*.ts
* so the TypeScript compiler resolves types cleanly. When the orchestrator wires
* the legacy file into src/tools/ (next pass), swap the import in dossier.ts /
* exporters/json.ts / exporters/pdf.ts back to "../tools/compliance-dossier.legacy.js".
*
* IMPORTANT: The runtime import in dossier.ts MUST point at the actual
* compiled JS location. The shim approach below declares types only — the
* runtime import resolves via the .js extension to whatever dist/tools path
* the orchestrator places the file.
*/
export {};
//# sourceMappingURL=_legacy-shim.js.map
{"version":3,"file":"_legacy-shim.js","sourceRoot":"","sources":["../../src/compliance/_legacy-shim.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
import { type SignedDossierManifest } from "./_legacy-shim.js";
import { type TaggedProbeResult } from "./mappings/mitre-atlas.js";
export type DossierPeriod = "last-quarter" | "last-month" | "last-90-days" | {
from: string;
to: string;
};
export type DossierFormat = "pdf" | "json";
export interface DossierOptions {
/** Date range — supports preset strings or explicit {from, to}. */
period: DossierPeriod;
/** Which artifact formats to emit. Order matters for UI display. */
format: DossierFormat[];
/** Optional signing key override (defaults to env SUNAIVA_DOSSIER_SIGNING_KEY). */
signing_key?: string;
/** Output directory (created if missing). */
output_dir: string;
/** Optional product filter (defaults to '@sunaiva/gate' — matches everything starting with this prefix). */
product?: string;
/** Test-only env override. */
env?: NodeJS.ProcessEnv;
/** Test-only audit log path override. */
auditLogPath?: string;
/** Test-only verdict dir override. */
verdictDir?: string;
}
export interface DossierResult {
/** Path to the emitted PDF, if 'pdf' was in format. */
pdf_path?: string;
/** Path to the emitted signed JSON sidecar, if 'json' was in format. */
json_path?: string;
/** The HMAC signature over the JSON bundle (hex). */
signature: string;
/** Warnings surfaced during generation (e.g., missing signing key). */
warnings: string[];
/** Reference to the inner manifest (for tests / callers that want full data). */
manifest: SignedDossierManifest & {
mappings: {
eu_ai_act: Record<string, string[]>;
nist_ai_rmf: Record<string, string[]>;
};
adversarial_results: TaggedProbeResult[];
};
}
/** Convert a DossierPeriod into concrete from/to ISO dates. Uses UTC. */
export declare function resolvePeriod(period: DossierPeriod, now?: Date): {
from: string;
to: string;
};
export declare function exportComplianceDossier(opts: DossierOptions): Promise<DossierResult>;
export declare function runExportComplianceCli(args: {
period?: string;
format?: string;
output_dir?: string;
product?: string;
}): Promise<{
pdf_path?: string;
json_path?: string;
warnings: string[];
}>;
//# sourceMappingURL=dossier.d.ts.map
{"version":3,"file":"dossier.d.ts","sourceRoot":"","sources":["../../src/compliance/dossier.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,qBAAqB,EAC3B,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,2BAA2B,CAAC;AAMnC,MAAM,MAAM,aAAa,GACrB,cAAc,GACd,YAAY,GACZ,cAAc,GACd;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,mEAAmE;IACnE,MAAM,EAAE,aAAa,CAAC;IACtB,oEAAoE;IACpE,MAAM,EAAE,aAAa,EAAE,CAAC;IACxB,mFAAmF;IACnF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6CAA6C;IAC7C,UAAU,EAAE,MAAM,CAAC;IACnB,4GAA4G;IAC5G,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8BAA8B;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,yCAAyC;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iFAAiF;IACjF,QAAQ,EAAE,qBAAqB,GAAG;QAChC,QAAQ,EAAE;YACR,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACpC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;SACvC,CAAC;QACF,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;KAC1C,CAAC;CACH;AAMD,yEAAyE;AACzE,wBAAgB,aAAa,CAC3B,MAAM,EAAE,aAAa,EACrB,GAAG,GAAE,IAAiB,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CA+B9B;AAgGD,wBAAsB,uBAAuB,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CA8E1F;AAMD,wBAAsB,sBAAsB,CAAC,IAAI,EAAE;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA2CzE"}
import { mkdirSync, writeFileSync } from "node:fs";
import { generateComplianceDossier as runDossierLegacy, } from "./_legacy-shim.js";
import { featuresIndex as euFeaturesIndex } from "./mappings/eu-ai-act.js";
import { nistFeatureIndex } from "./mappings/nist-ai-rmf.js";
import { MITRE_ATLAS_MAPPING, tagProbes, } from "./mappings/mitre-atlas.js";
// ---------------------------------------------------------------------------
// Period parsing
// ---------------------------------------------------------------------------
/** Convert a DossierPeriod into concrete from/to ISO dates. Uses UTC. */
export function resolvePeriod(period, now = new Date()) {
if (typeof period === "object" && period !== null) {
if (!period.from || !period.to) {
throw new Error("Custom period requires both 'from' and 'to' ISO dates");
}
return { from: period.from, to: period.to };
}
// ISO date format YYYY-MM-DD
const isoDate = (d) => d.toISOString().slice(0, 10);
const to = isoDate(now);
let fromDate;
switch (period) {
case "last-quarter": {
fromDate = new Date(now);
fromDate.setUTCDate(fromDate.getUTCDate() - 92); // ~3 months
break;
}
case "last-month": {
fromDate = new Date(now);
fromDate.setUTCDate(fromDate.getUTCDate() - 31);
break;
}
case "last-90-days": {
fromDate = new Date(now);
fromDate.setUTCDate(fromDate.getUTCDate() - 90);
break;
}
default:
throw new Error(`Unknown period preset: ${period}`);
}
return { from: isoDate(fromDate), to };
}
// ---------------------------------------------------------------------------
// Mapping extraction
// ---------------------------------------------------------------------------
/** Build the manifest.mappings.eu_ai_act block (feature → [article ids]). */
function buildEuMapping() {
return euFeaturesIndex();
}
/** Build the manifest.mappings.nist_ai_rmf block (feature → [subcategory ids]). */
function buildNistMapping() {
return nistFeatureIndex();
}
/**
* Extract probes from verdict adversarial layers and tag with MITRE ATLAS.
* Probe results stored in verdicts under adversarial_layer.results or
* adversarial_layer.probes (depending on emitter version). Best-effort.
*/
function extractAdversarialResults(manifest) {
const probes = [];
// Direct technique IDs collected separately — these don't have a probe name,
// so we tag them by ATLAS ID lookup instead of probe-name lookup.
const directTechniqueResults = [];
for (const v of manifest.verdicts ?? []) {
const layer = v.adversarial_layer;
if (!layer)
continue;
// Common shapes we tolerate
const candidates = (layer.probes ??
layer.results ??
layer.findings);
if (Array.isArray(candidates)) {
for (const entry of candidates) {
if (entry && typeof entry === "object") {
const e = entry;
const probe = typeof e.probe === "string"
? e.probe
: typeof e.name === "string"
? e.name
: null;
const resultRaw = typeof e.result === "string"
? e.result
: typeof e.outcome === "string"
? e.outcome
: "indeterminate";
let result = "indeterminate";
if (resultRaw === "caught" ||
resultRaw === "passed" ||
resultRaw === "blocked")
result = "caught";
else if (resultRaw === "escaped" ||
resultRaw === "failed" ||
resultRaw === "allowed")
result = "escaped";
if (probe)
probes.push({ probe, result });
}
}
}
// Direct atlas_techniques array — verdict claims these techniques were caught.
// Look up each technique by ID and emit a tagged result directly.
const tts = layer.atlas_techniques;
if (Array.isArray(tts)) {
for (const t of tts) {
if (typeof t === "string") {
const tech = MITRE_ATLAS_MAPPING[t];
directTechniqueResults.push({
probe: tech?.gate_probe_names?.[0] ?? `atlas_${t}_probe`,
result: "caught",
atlas_technique_id: tech?.id ?? t,
atlas_technique_name: tech?.name,
atlas_tactic: tech?.tactic,
});
}
}
}
}
return [...tagProbes(probes), ...directTechniqueResults];
}
// ---------------------------------------------------------------------------
// Main entry — exportComplianceDossier (1.2.0 spec)
// ---------------------------------------------------------------------------
export async function exportComplianceDossier(opts) {
// Validation
if (!opts.output_dir) {
throw new Error("exportComplianceDossier: 'output_dir' is required");
}
if (!opts.format || opts.format.length === 0) {
throw new Error("exportComplianceDossier: 'format' must include at least one of 'pdf' | 'json'");
}
for (const f of opts.format) {
if (f !== "pdf" && f !== "json") {
throw new Error(`exportComplianceDossier: unsupported format '${f}'`);
}
}
const env = opts.env ?? process.env;
const { from, to } = resolvePeriod(opts.period);
const product = opts.product ?? "@sunaiva/gate";
// Separation-of-keys per §9.2 #8. Prefer dedicated dossier key; fall back to
// ship-confidence key with explicit warning.
let signingKeyEnv = "SUNAIVA_DOSSIER_SIGNING_KEY";
let signingKeyOverride;
if (opts.signing_key) {
// Inject signing key into a synthetic env so the legacy implementation picks it up.
signingKeyOverride = { ...env, [signingKeyEnv]: opts.signing_key };
}
else if (!env[signingKeyEnv] && env.SHIP_CONFIDENCE_SIGNING_KEY) {
// Legacy fallback — log warning later.
signingKeyEnv = "SHIP_CONFIDENCE_SIGNING_KEY";
}
const legacyOpts = {
product,
from,
to,
output: opts.output_dir,
env: signingKeyOverride ?? env,
signingKeyEnv,
skipPdf: !opts.format.includes("pdf"),
auditLogPath: opts.auditLogPath,
verdictDir: opts.verdictDir,
};
const legacyResult = await runDossierLegacy(legacyOpts);
// Inject 1.2.0 mappings + adversarial tagging into the manifest before re-write.
const enrichedManifest = {
...legacyResult.manifest,
mappings: {
eu_ai_act: buildEuMapping(),
nist_ai_rmf: buildNistMapping(),
},
adversarial_results: extractAdversarialResults(legacyResult.manifest),
};
const warnings = [...legacyResult.warnings];
if (signingKeyEnv === "SHIP_CONFIDENCE_SIGNING_KEY" && !opts.signing_key) {
warnings.push("SUNAIVA_DOSSIER_SIGNING_KEY not set — falling back to SHIP_CONFIDENCE_SIGNING_KEY. Per §9.2 #8, use a dedicated dossier key in production.");
}
// Re-write JSON sidecar with enrichment (if json was requested).
let jsonPath;
if (opts.format.includes("json")) {
jsonPath = legacyResult.signedJsonPath;
mkdirSync(opts.output_dir, { recursive: true });
writeFileSync(jsonPath, JSON.stringify(enrichedManifest, null, 2), "utf-8");
}
return {
pdf_path: legacyResult.pdfPath ?? undefined,
json_path: jsonPath,
signature: enrichedManifest.signature ?? "",
warnings,
manifest: enrichedManifest,
};
}
// ---------------------------------------------------------------------------
// CLI helper — used by src/index.ts for the `export-compliance` subcommand.
// ---------------------------------------------------------------------------
export async function runExportComplianceCli(args) {
const periodRaw = args.period ?? "last-quarter";
const period = periodRaw === "last-quarter" ||
periodRaw === "last-month" ||
periodRaw === "last-90-days"
? periodRaw
: (() => {
// Try {from..to} delimited
const m = /^([\d:T.Z-]+)\.\.([\d:T.Z-]+)$/.exec(periodRaw);
if (m)
return { from: m[1], to: m[2] };
throw new Error(`Unknown --period value '${periodRaw}'. Use 'last-quarter' | 'last-month' | 'last-90-days' | 'FROM..TO'.`);
})();
const formatRaw = args.format ?? "json";
const format = formatRaw
.split(",")
.map((s) => s.trim())
.filter((s) => s === "pdf" || s === "json");
if (format.length === 0) {
throw new Error(`--format must include at least one of 'pdf' | 'json' (got '${formatRaw}')`);
}
if (!args.output_dir) {
throw new Error("--output-dir is required");
}
const result = await exportComplianceDossier({
period,
format,
output_dir: args.output_dir,
product: args.product,
});
return {
pdf_path: result.pdf_path,
json_path: result.json_path,
warnings: result.warnings,
};
}
//# sourceMappingURL=dossier.js.map
{"version":3,"file":"dossier.js","sourceRoot":"","sources":["../../src/compliance/dossier.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EACL,yBAAyB,IAAI,gBAAgB,GAE9C,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,aAAa,IAAI,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,SAAS,GAEV,MAAM,2BAA2B,CAAC;AAoDnC,8EAA8E;AAC9E,iBAAiB;AACjB,8EAA8E;AAE9E,yEAAyE;AACzE,MAAM,UAAU,aAAa,CAC3B,MAAqB,EACrB,MAAY,IAAI,IAAI,EAAE;IAEtB,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC9C,CAAC;IACD,6BAA6B;IAC7B,MAAM,OAAO,GAAG,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC1D,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,QAAc,CAAC;IACnB,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,QAAQ,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,YAAY;YAC7D,MAAM;QACR,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,QAAQ,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;YAChD,MAAM;QACR,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,QAAQ,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;YAChD,MAAM;QACR,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;AACzC,CAAC;AAED,8EAA8E;AAC9E,qBAAqB;AACrB,8EAA8E;AAE9E,6EAA6E;AAC7E,SAAS,cAAc;IACrB,OAAO,eAAe,EAAE,CAAC;AAC3B,CAAC;AAED,mFAAmF;AACnF,SAAS,gBAAgB;IACvB,OAAO,gBAAgB,EAAE,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,SAAS,yBAAyB,CAAC,QAA+B;IAChE,MAAM,MAAM,GAAwE,EAAE,CAAC;IACvF,6EAA6E;IAC7E,kEAAkE;IAClE,MAAM,sBAAsB,GAAwB,EAAE,CAAC;IAEvD,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,CAAC,CAAC,iBAAiB,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,4BAA4B;QAC5B,MAAM,UAAU,GAAG,CAChB,KAAiC,CAAC,MAAM;YACxC,KAAiC,CAAC,OAAO;YACzC,KAAiC,CAAC,QAAQ,CAC5C,CAAC;QACF,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,UAAU,EAAE,CAAC;gBAC/B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACvC,MAAM,CAAC,GAAG,KAAgC,CAAC;oBAC3C,MAAM,KAAK,GACT,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;wBACzB,CAAC,CAAC,CAAC,CAAC,KAAK;wBACT,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;4BAC5B,CAAC,CAAC,CAAC,CAAC,IAAI;4BACR,CAAC,CAAC,IAAI,CAAC;oBACX,MAAM,SAAS,GACb,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;wBAC1B,CAAC,CAAC,CAAC,CAAC,MAAM;wBACV,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;4BAC/B,CAAC,CAAC,CAAC,CAAC,OAAO;4BACX,CAAC,CAAC,eAAe,CAAC;oBACtB,IAAI,MAAM,GAA2C,eAAe,CAAC;oBACrE,IACE,SAAS,KAAK,QAAQ;wBACtB,SAAS,KAAK,QAAQ;wBACtB,SAAS,KAAK,SAAS;wBAEvB,MAAM,GAAG,QAAQ,CAAC;yBACf,IACH,SAAS,KAAK,SAAS;wBACvB,SAAS,KAAK,QAAQ;wBACtB,SAAS,KAAK,SAAS;wBAEvB,MAAM,GAAG,SAAS,CAAC;oBACrB,IAAI,KAAK;wBAAE,MAAM,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;gBAC5C,CAAC;YACH,CAAC;QACH,CAAC;QAED,+EAA+E;QAC/E,kEAAkE;QAClE,MAAM,GAAG,GAAI,KAAiC,CAAC,gBAAgB,CAAC;QAChE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;gBACpB,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;oBAC1B,MAAM,IAAI,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;oBACpC,sBAAsB,CAAC,IAAI,CAAC;wBAC1B,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,QAAQ;wBACxD,MAAM,EAAE,QAAQ;wBAChB,kBAAkB,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC;wBACjC,oBAAoB,EAAE,IAAI,EAAE,IAAI;wBAChC,YAAY,EAAE,IAAI,EAAE,MAAM;qBAC3B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,GAAG,sBAAsB,CAAC,CAAC;AAC3D,CAAC;AAED,8EAA8E;AAC9E,oDAAoD;AACpD,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,IAAoB;IAChE,aAAa;IACb,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACb,+EAA+E,CAChF,CAAC;IACJ,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IACpC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC;IAEhD,6EAA6E;IAC7E,6CAA6C;IAC7C,IAAI,aAAa,GAAG,6BAA6B,CAAC;IAClD,IAAI,kBAAiD,CAAC;IACtD,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,oFAAoF;QACpF,kBAAkB,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;IACrE,CAAC;SAAM,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,2BAA2B,EAAE,CAAC;QAClE,uCAAuC;QACvC,aAAa,GAAG,6BAA6B,CAAC;IAChD,CAAC;IAED,MAAM,UAAU,GAAG;QACjB,OAAO;QACP,IAAI;QACJ,EAAE;QACF,MAAM,EAAE,IAAI,CAAC,UAAU;QACvB,GAAG,EAAE,kBAAkB,IAAI,GAAG;QAC9B,aAAa;QACb,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QACrC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,UAAU,EAAE,IAAI,CAAC,UAAU;KAC5B,CAAC;IAEF,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAExD,iFAAiF;IACjF,MAAM,gBAAgB,GAAG;QACvB,GAAG,YAAY,CAAC,QAAQ;QACxB,QAAQ,EAAE;YACR,SAAS,EAAE,cAAc,EAAE;YAC3B,WAAW,EAAE,gBAAgB,EAAE;SAChC;QACD,mBAAmB,EAAE,yBAAyB,CAAC,YAAY,CAAC,QAAQ,CAAC;KACtE,CAAC;IAEF,MAAM,QAAQ,GAAG,CAAC,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC5C,IAAI,aAAa,KAAK,6BAA6B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QACzE,QAAQ,CAAC,IAAI,CACX,4IAA4I,CAC7I,CAAC;IACJ,CAAC;IAED,iEAAiE;IACjE,IAAI,QAA4B,CAAC;IACjC,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACjC,QAAQ,GAAG,YAAY,CAAC,cAAc,CAAC;QACvC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,YAAY,CAAC,OAAO,IAAI,SAAS;QAC3C,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,gBAAgB,CAAC,SAAS,IAAI,EAAE;QAC3C,QAAQ;QACR,QAAQ,EAAE,gBAAgB;KAC3B,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,4EAA4E;AAC5E,8EAA8E;AAE9E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAK5C;IACC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC;IAChD,MAAM,MAAM,GACV,SAAS,KAAK,cAAc;QAC5B,SAAS,KAAK,YAAY;QAC1B,SAAS,KAAK,cAAc;QAC1B,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,CAAC,GAAG,EAAE;YACJ,2BAA2B;YAC3B,MAAM,CAAC,GAAG,gCAAgC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3D,IAAI,CAAC;gBAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CACb,2BAA2B,SAAS,qEAAqE,CAC1G,CAAC;QACJ,CAAC,CAAC,EAAE,CAAC;IAEX,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;IACxC,MAAM,MAAM,GAAG,SAAS;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAsB,EAAE,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC;IAElE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,8DAA8D,SAAS,IAAI,CAC5E,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC;QAC3C,MAAM;QACN,MAAM;QACN,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;KACtB,CAAC,CAAC;IAEH,OAAO;QACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAC;AACJ,CAAC"}
import type { SignedDossierManifest } from "../_legacy-shim.js";
export interface JsonExportOptions {
manifest: SignedDossierManifest & Record<string, unknown>;
output_path: string;
}
export interface JsonExportResult {
path: string;
size_bytes: number;
signature: string;
}
export declare function exportToJson(opts: JsonExportOptions): JsonExportResult;
//# sourceMappingURL=json.d.ts.map
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../../src/compliance/exporters/json.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1D,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,CAatE"}
/**
* JSON exporter for compliance dossier (1.2.0 T04).
*
* Emits the signed JSON bundle. The signing is done by the upstream
* compliance-dossier.ts implementation (canonicalJson + HMAC-SHA256).
* This exporter just writes the bytes and re-checks the file exists.
*/
import { existsSync, writeFileSync, mkdirSync, statSync } from "node:fs";
import { dirname } from "node:path";
export function exportToJson(opts) {
mkdirSync(dirname(opts.output_path), { recursive: true });
// Pretty-printed for human auditors; canonicalJson is used SEPARATELY for the
// HMAC payload, not for the on-disk bytes.
writeFileSync(opts.output_path, JSON.stringify(opts.manifest, null, 2), "utf-8");
if (!existsSync(opts.output_path)) {
throw new Error(`exportToJson: failed to write ${opts.output_path}`);
}
return {
path: opts.output_path,
size_bytes: statSync(opts.output_path).size,
signature: opts.manifest.signature ?? "",
};
}
//# sourceMappingURL=json.js.map
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../../src/compliance/exporters/json.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAcpC,MAAM,UAAU,YAAY,CAAC,IAAuB;IAClD,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,8EAA8E;IAC9E,2CAA2C;IAC3C,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACjF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,WAAW;QACtB,UAAU,EAAE,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI;QAC3C,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE;KACzC,CAAC;AACJ,CAAC"}
import type { SignedDossierManifest } from "../_legacy-shim.js";
export interface PdfExportOptions {
manifest: SignedDossierManifest;
output_path: string;
}
export interface PdfExportResult {
path: string;
size_bytes: number;
format: "pdf" | "markdown";
warning?: string;
}
export declare function exportToPdf(opts: PdfExportOptions): Promise<PdfExportResult>;
//# sourceMappingURL=pdf.d.ts.map
{"version":3,"file":"pdf.d.ts","sourceRoot":"","sources":["../../../src/compliance/exporters/pdf.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAEhE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,qBAAqB,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,KAAK,GAAG,UAAU,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAoED,wBAAsB,WAAW,CAAC,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CA2BlF"}
/**
* PDF exporter for compliance dossier (1.2.0 T04).
*
* Library choice: pdfkit (already in package.json — lightweight, pure JS, ~1MB).
* Per Risk R-02 in SPRINT_1_2_0_PLAN.md §9.1, if pdfkit is unavailable at runtime,
* this exporter degrades to a Markdown fallback with a clear note in warnings.
*
* Per §3.4: "if neither [pdfkit nor puppeteer] is in package.json, ship Markdown
* + pdf-fallback note." pdfkit IS in package.json, so PDF is the default path.
*
* The heavy PDF rendering is delegated to the renderPdf() function inside
* src/tools/compliance-dossier.ts (preserved 1.1.0 implementation). This file
* supplies the 1.2.0-style entry point used by exporters/index.ts.
*/
import { existsSync } from "node:fs";
import { writeFileSync, mkdirSync } from "node:fs";
import { dirname } from "node:path";
/**
* Detect whether pdfkit is loadable. We use a dynamic import + try/catch so
* the runtime falls back gracefully if pdfkit is missing from the bundle
* (e.g., when distributed as a slimmed-down `npx` package).
*/
async function pdfkitAvailable() {
try {
const mod = await import("pdfkit").catch(() => null);
return mod !== null && mod !== undefined;
}
catch {
return false;
}
}
/**
* Markdown fallback — emits a clean human-readable summary when pdfkit is
* unavailable. Auditors can still verify all fields against the JSON sidecar.
*/
function buildMarkdownFallback(manifest) {
const lines = [];
lines.push(`# EU AI Act Article 14/15 — Ship-Confidence Compliance Dossier`);
lines.push("");
lines.push(`**Product**: ${manifest.product}`);
lines.push(`**Period**: ${manifest.period.from} → ${manifest.period.to}`);
lines.push(`**Generated**: ${manifest.generated_at}`);
lines.push(`**Tool**: ${manifest.tool} v${manifest.tool_version}`);
lines.push("");
if (manifest.signature) {
lines.push(`**Signature** (HMAC-SHA256): \`${manifest.signature.slice(0, 32)}…\``);
}
else {
lines.push(`> **UNSIGNED** — ${manifest.signing_warning ?? "no signing key"}`);
}
lines.push("");
lines.push(`## Executive Summary`);
const s = manifest.stats;
lines.push(`- Total events: ${s.total_events}`);
lines.push(`- Allow decisions: ${s.allows} (paid=${s.paid_tier_allows}, free=${s.free_tier_allows})`);
lines.push(`- Block decisions: ${s.blocks}`);
lines.push(`- Constitutional violations: ${s.constitutional_violations}`);
lines.push(`- Bypasses: ${s.bypasses}`);
lines.push(`- Dry-run probes: ${s.dry_runs}`);
lines.push(`- Errors (fail-open): ${s.errors}`);
lines.push("");
lines.push(`## Article Evidence Map`);
const articles = [
["Art. 12 — Logging", manifest.article_evidence.art_12_logging],
["Art. 13 — Transparency", manifest.article_evidence.art_13_transparency],
["Art. 14 — Human Oversight", manifest.article_evidence.art_14_human_oversight],
["Art. 15 — Accuracy & Robustness", manifest.article_evidence.art_15_accuracy_robustness],
["Art. 15 — Cybersecurity", manifest.article_evidence.art_15_cybersecurity],
];
for (const [name, ev] of articles) {
const tag = ev.satisfied ? "[SATISFIED]" : "[FLAGGED]";
lines.push(`### ${tag} ${name}`);
lines.push(ev.notes);
lines.push("");
}
lines.push(`## Constitutional Immutability`);
lines.push(`${manifest.constitutional_rules.count} rules are marked enforcement="constitutional" and cannot be disabled.`);
lines.push(`Rule list SHA-256: \`${manifest.constitutional_rules.hash}\``);
lines.push("");
return lines.join("\n");
}
export async function exportToPdf(opts) {
mkdirSync(dirname(opts.output_path), { recursive: true });
const haspdfkit = await pdfkitAvailable();
if (!haspdfkit) {
// Fallback to Markdown — same path with .md suffix.
const mdPath = opts.output_path.replace(/\.pdf$/i, ".md");
const body = buildMarkdownFallback(opts.manifest);
writeFileSync(mdPath, body, "utf-8");
return {
path: mdPath,
size_bytes: Buffer.byteLength(body, "utf-8"),
format: "markdown",
warning: "pdfkit not available — Markdown fallback emitted. See SPRINT_1_2_0_PLAN §9.1 R-02.",
};
}
// Delegate to legacy renderPdf via the legacy generateComplianceDossier path.
// The legacy implementation already does the heavy lifting and is byte-stable.
// Here we just confirm the file exists; the caller (src/compliance/dossier.ts)
// generated it via the legacy runner.
if (!existsSync(opts.output_path)) {
throw new Error(`exportToPdf: expected legacy renderer to have written ${opts.output_path}`);
}
const sz = (await import("node:fs")).statSync(opts.output_path).size;
return { path: opts.output_path, size_bytes: sz, format: "pdf" };
}
//# sourceMappingURL=pdf.js.map
{"version":3,"file":"pdf.js","sourceRoot":"","sources":["../../../src/compliance/exporters/pdf.ts"],"names":[],"mappings":"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"}
/**
* EU AI Act → Sunaiva Gate feature mapping (Tier-1 T04).
*
* Source: Regulation (EU) 2024/1689 — Articles 12, 13, 14, 15, 72.
* High-risk obligations enforce 2 Aug 2026. This mapping enables the
* compliance dossier (T04) to declare, per Article, which Gate features
* supply the evidence.
*
* NOT legal advice. The mapping is structural — auditors must verify the
* evidence-quality threshold against their own Article interpretation.
*/
export type EuAiActArticle = "12" | "13" | "14" | "15" | "72";
export interface EuAiActMappingEntry {
/** Article number */
article: EuAiActArticle;
/** Article name */
name: string;
/** Specific Article paragraphs / sub-clauses cited */
clauses: string[];
/** Gate feature(s) that satisfy this clause */
gate_features: string[];
/** Evidence path / location inside the dossier */
evidence_locations: string[];
/** Notes / caveats */
notes: string;
}
export declare const EU_AI_ACT_MAPPING: Record<EuAiActArticle, EuAiActMappingEntry>;
/** Feature → list of Articles it supports (inverse index). */
export declare function featuresIndex(): Record<string, EuAiActArticle[]>;
/** Get all Article clauses covered by Sunaiva Gate. */
export declare function coveredClauses(): {
article: EuAiActArticle;
clause: string;
}[];
//# sourceMappingURL=eu-ai-act.d.ts.map
{"version":3,"file":"eu-ai-act.d.ts","sourceRoot":"","sources":["../../../src/compliance/mappings/eu-ai-act.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE9D,MAAM,WAAW,mBAAmB;IAClC,qBAAqB;IACrB,OAAO,EAAE,cAAc,CAAC;IACxB,mBAAmB;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,sDAAsD;IACtD,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,+CAA+C;IAC/C,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kDAAkD;IAClD,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,cAAc,EAAE,mBAAmB,CAoFzE,CAAC;AAEF,8DAA8D;AAC9D,wBAAgB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAShE;AAED,uDAAuD;AACvD,wBAAgB,cAAc,IAAI;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAAE,CAQ9E"}
/**
* EU AI Act → Sunaiva Gate feature mapping (Tier-1 T04).
*
* Source: Regulation (EU) 2024/1689 — Articles 12, 13, 14, 15, 72.
* High-risk obligations enforce 2 Aug 2026. This mapping enables the
* compliance dossier (T04) to declare, per Article, which Gate features
* supply the evidence.
*
* NOT legal advice. The mapping is structural — auditors must verify the
* evidence-quality threshold against their own Article interpretation.
*/
export const EU_AI_ACT_MAPPING = {
"12": {
article: "12",
name: "Record-keeping (logging)",
clauses: ["12(1) automatic event recording", "12(2) traceability of operation"],
gate_features: [
"ship_confidence_gate.audit_ledger",
"validate_action.audit_log",
"compliance_dossier.event_replay",
],
evidence_locations: ["manifest.events", "manifest.override_audit", "manifest.stats"],
notes: "Every gate decision (allow/block/bypass/dry-run/error) is appended to ~/.sunaiva/audit/audit.jsonl with structured event_type, timestamp, artifact_id, and reason fields.",
},
"13": {
article: "13",
name: "Transparency and information to deployers",
clauses: ["13(1) interpretability", "13(3)(b)(iii) decision logic disclosure"],
gate_features: [
"explain_decision",
"ship_confidence_gate.stamp",
"validate_action.reason",
],
evidence_locations: ["manifest.events[*].reason", "explain_decision.output"],
notes: "Every event carries a structured reason field. Per-block self-explanation API exposes the rule, evidence, alternatives, and bypass path.",
},
"14": {
article: "14",
name: "Human oversight",
clauses: [
"14(1) effective oversight",
"14(4)(a) interpret outputs correctly",
"14(4)(b) override or disregard",
"14(4)(d) intervene or interrupt",
],
gate_features: [
"ship_confidence_gate.dual_tier_authorization",
"ship_confidence_gate.time_lock",
"validate_action.constitutional_immutability",
"log_bypass",
"rollback.engine",
],
evidence_locations: [
"manifest.override_audit",
"manifest.constitutional_rules",
"manifest.events[event_type=ship_confidence_block]",
],
notes: "Mandatory pre-publish blocking gate. Constitutional rules cannot be disabled. Time-locked publish-class actions allow human cancellation within window. Bypasses require explicit reason recorded to ledger.",
},
"15": {
article: "15",
name: "Accuracy, robustness and cybersecurity",
clauses: [
"15(1) appropriate level of accuracy",
"15(4) resilience to errors and adversarial behaviour",
"15(5) cybersecurity",
],
gate_features: [
"property_layer.invariant_tests",
"adversarial_layer.atlas_probes",
"cross_provider_decorrelation",
"hmac_signed_verdict_chain",
"paranoia_mode.outbound_allowlist",
],
evidence_locations: [
"manifest.verdicts",
"manifest.verdicts[*].property_layer",
"manifest.verdicts[*].adversarial_layer",
"manifest.verdicts[*].cross_provider",
],
notes: "Property-based invariant tests (Hypothesis), MITRE ATLAS-mapped adversarial probes, and cross-provider decorrelation (Patent A Pillar 3) supply independent verification. HMAC-SHA256 tamper-evident chain. Paranoia mode supplies cyber Layer 5 outbound default-deny.",
},
"72": {
article: "72",
name: "Post-market monitoring",
clauses: ["72(1) post-market monitoring system", "72(2) incident reporting"],
gate_features: ["failure_evolution_protocol", "audit_ledger.replay"],
evidence_locations: ["manifest.events", "manifest.override_audit"],
notes: "Compliance dossier acts as the periodic post-market monitoring artifact. failure_051 cure (paranoia mode + git_subtree_push pattern) is itself documented as Rule 14 root-cause evolution.",
},
};
/** Feature → list of Articles it supports (inverse index). */
export function featuresIndex() {
const index = {};
for (const [article, entry] of Object.entries(EU_AI_ACT_MAPPING)) {
for (const feat of entry.gate_features) {
if (!index[feat])
index[feat] = [];
index[feat].push(article);
}
}
return index;
}
/** Get all Article clauses covered by Sunaiva Gate. */
export function coveredClauses() {
const out = [];
for (const [article, entry] of Object.entries(EU_AI_ACT_MAPPING)) {
for (const clause of entry.clauses) {
out.push({ article: article, clause });
}
}
return out;
}
//# sourceMappingURL=eu-ai-act.js.map
{"version":3,"file":"eu-ai-act.js","sourceRoot":"","sources":["../../../src/compliance/mappings/eu-ai-act.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH,MAAM,CAAC,MAAM,iBAAiB,GAAgD;IAC5E,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,CAAC,iCAAiC,EAAE,iCAAiC,CAAC;QAC/E,aAAa,EAAE;YACb,mCAAmC;YACnC,2BAA2B;YAC3B,iCAAiC;SAClC;QACD,kBAAkB,EAAE,CAAC,iBAAiB,EAAE,yBAAyB,EAAE,gBAAgB,CAAC;QACpF,KAAK,EACH,2KAA2K;KAC9K;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,2CAA2C;QACjD,OAAO,EAAE,CAAC,wBAAwB,EAAE,yCAAyC,CAAC;QAC9E,aAAa,EAAE;YACb,kBAAkB;YAClB,4BAA4B;YAC5B,wBAAwB;SACzB;QACD,kBAAkB,EAAE,CAAC,2BAA2B,EAAE,yBAAyB,CAAC;QAC5E,KAAK,EACH,0IAA0I;KAC7I;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,iBAAiB;QACvB,OAAO,EAAE;YACP,2BAA2B;YAC3B,sCAAsC;YACtC,gCAAgC;YAChC,iCAAiC;SAClC;QACD,aAAa,EAAE;YACb,8CAA8C;YAC9C,gCAAgC;YAChC,6CAA6C;YAC7C,YAAY;YACZ,iBAAiB;SAClB;QACD,kBAAkB,EAAE;YAClB,yBAAyB;YACzB,+BAA+B;YAC/B,mDAAmD;SACpD;QACD,KAAK,EACH,8MAA8M;KACjN;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,wCAAwC;QAC9C,OAAO,EAAE;YACP,qCAAqC;YACrC,sDAAsD;YACtD,qBAAqB;SACtB;QACD,aAAa,EAAE;YACb,gCAAgC;YAChC,gCAAgC;YAChC,8BAA8B;YAC9B,2BAA2B;YAC3B,kCAAkC;SACnC;QACD,kBAAkB,EAAE;YAClB,mBAAmB;YACnB,qCAAqC;YACrC,wCAAwC;YACxC,qCAAqC;SACtC;QACD,KAAK,EACH,yQAAyQ;KAC5Q;IACD,IAAI,EAAE;QACJ,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,wBAAwB;QAC9B,OAAO,EAAE,CAAC,qCAAqC,EAAE,0BAA0B,CAAC;QAC5E,aAAa,EAAE,CAAC,4BAA4B,EAAE,qBAAqB,CAAC;QACpE,kBAAkB,EAAE,CAAC,iBAAiB,EAAE,yBAAyB,CAAC;QAClE,KAAK,EACH,4LAA4L;KAC/L;CACF,CAAC;AAEF,8DAA8D;AAC9D,MAAM,UAAU,aAAa;IAC3B,MAAM,KAAK,GAAqC,EAAE,CAAC;IACnD,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACjE,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAyB,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,cAAc;IAC5B,MAAM,GAAG,GAAkD,EAAE,CAAC;IAC9D,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACjE,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACnC,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,OAAyB,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
/**
* MITRE ATLAS (Adversarial Threat Landscape for AI Systems) → Sunaiva Gate
* adversarial probe mapping (Tier-1 T04).
*
* Source: MITRE ATLAS v5.1 (https://atlas.mitre.org).
*
* The dossier exporter looks up each adversarial probe's technique ID here
* to render the EU AI Act Article 15(5) cybersecurity evidence and the
* NIST AI RMF Measure 2.7 evidence in a procurement-grade way.
*/
export type AtlasTechniqueId = string;
export interface AtlasTechnique {
id: AtlasTechniqueId;
name: string;
tactic: string;
description: string;
gate_probe_names: string[];
countermeasures: string[];
}
export declare const MITRE_ATLAS_MAPPING: Record<AtlasTechniqueId, AtlasTechnique>;
/** Lookup technique by probe-name (the dossier's adversarial_layer reports probes by name). */
export declare function techniqueByProbe(probeName: string): AtlasTechnique | null;
/** Tag a list of probe results with their ATLAS techniques. */
export interface TaggedProbeResult {
probe: string;
result: "caught" | "escaped" | "indeterminate";
atlas_technique_id?: AtlasTechniqueId;
atlas_technique_name?: string;
atlas_tactic?: string;
}
export declare function tagProbes(probes: {
probe: string;
result: "caught" | "escaped" | "indeterminate";
}[]): TaggedProbeResult[];
//# sourceMappingURL=mitre-atlas.d.ts.map
{"version":3,"file":"mitre-atlas.d.ts","sourceRoot":"","sources":["../../../src/compliance/mappings/mitre-atlas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,gBAAgB,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,gBAAgB,EAAE,cAAc,CA+ExE,CAAC;AAEF,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAKzE;AAED,+DAA+D;AAC/D,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,eAAe,CAAC;IAC/C,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;IACtC,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,SAAS,CACvB,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,eAAe,CAAA;CAAE,EAAE,GAC1E,iBAAiB,EAAE,CAWrB"}
/**
* MITRE ATLAS (Adversarial Threat Landscape for AI Systems) → Sunaiva Gate
* adversarial probe mapping (Tier-1 T04).
*
* Source: MITRE ATLAS v5.1 (https://atlas.mitre.org).
*
* The dossier exporter looks up each adversarial probe's technique ID here
* to render the EU AI Act Article 15(5) cybersecurity evidence and the
* NIST AI RMF Measure 2.7 evidence in a procurement-grade way.
*/
export const MITRE_ATLAS_MAPPING = {
"AML.T0051": {
id: "AML.T0051",
name: "LLM Prompt Injection",
tactic: "Initial Access",
description: "Adversary crafts prompts that override system instructions, exfiltrate context, or trigger harmful tool calls.",
gate_probe_names: [
"prompt_injection_basic",
"prompt_injection_jailbreak",
"prompt_injection_indirect",
],
countermeasures: [
"validate_action.pattern_matcher",
"constitutional_rules.ai-safety",
],
},
"AML.T0048": {
id: "AML.T0048",
name: "External Harms",
tactic: "Impact",
description: "Adversary uses an AI system to cause harm beyond the system itself (e.g., unauthorized network calls, data exfiltration).",
gate_probe_names: [
"exfil_curl_to_attacker",
"exfil_git_push_to_attacker_repo",
],
countermeasures: [
"paranoia_mode.outbound_allowlist",
"constitutional_rules.fin-001",
"constitutional_rules.dat-001",
],
},
"AML.T0040": {
id: "AML.T0040",
name: "ML Model Inference API Access",
tactic: "ML Model Access",
description: "Adversary accesses the model inference API to harvest model behavior or run repeated queries for budget exhaustion.",
gate_probe_names: ["budget_exhaustion_probe"],
countermeasures: [
"check_cost",
"cost_gate.monthly_cap",
],
},
"AML.T0043": {
id: "AML.T0043",
name: "Craft Adversarial Data",
tactic: "ML Attack Staging",
description: "Adversary crafts adversarial inputs to cause incorrect classification or to bypass validation.",
gate_probe_names: [
"obfuscation_unicode_lookalike",
"obfuscation_base64_eval",
"obfuscation_split_command",
],
countermeasures: ["pattern_matcher.normalization"],
},
"AML.T0044": {
id: "AML.T0044",
name: "Full ML Model Access",
tactic: "ML Model Access",
description: "Adversary gains full read/write access to the agent's runtime model, instructions, or memory.",
gate_probe_names: ["constitutional_rule_disable_attempt"],
countermeasures: ["immutability_guard"],
},
"AML.T0050": {
id: "AML.T0050",
name: "Command and Control",
tactic: "Command and Control",
description: "Adversary uses the AI system to establish persistent communication with an external attacker-controlled endpoint.",
gate_probe_names: [
"exfil_curl_to_attacker",
"reverse_shell_attempt",
],
countermeasures: ["paranoia_mode.outbound_allowlist"],
},
};
/** Lookup technique by probe-name (the dossier's adversarial_layer reports probes by name). */
export function techniqueByProbe(probeName) {
for (const tech of Object.values(MITRE_ATLAS_MAPPING)) {
if (tech.gate_probe_names.includes(probeName))
return tech;
}
return null;
}
export function tagProbes(probes) {
return probes.map((p) => {
const tech = techniqueByProbe(p.probe);
return {
probe: p.probe,
result: p.result,
atlas_technique_id: tech?.id,
atlas_technique_name: tech?.name,
atlas_tactic: tech?.tactic,
};
});
}
//# sourceMappingURL=mitre-atlas.js.map
{"version":3,"file":"mitre-atlas.js","sourceRoot":"","sources":["../../../src/compliance/mappings/mitre-atlas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAaH,MAAM,CAAC,MAAM,mBAAmB,GAA6C;IAC3E,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,gBAAgB;QACxB,WAAW,EACT,gHAAgH;QAClH,gBAAgB,EAAE;YAChB,wBAAwB;YACxB,4BAA4B;YAC5B,2BAA2B;SAC5B;QACD,eAAe,EAAE;YACf,iCAAiC;YACjC,gCAAgC;SACjC;KACF;IACD,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,gBAAgB;QACtB,MAAM,EAAE,QAAQ;QAChB,WAAW,EACT,2HAA2H;QAC7H,gBAAgB,EAAE;YAChB,wBAAwB;YACxB,iCAAiC;SAClC;QACD,eAAe,EAAE;YACf,kCAAkC;YAClC,8BAA8B;YAC9B,8BAA8B;SAC/B;KACF;IACD,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,+BAA+B;QACrC,MAAM,EAAE,iBAAiB;QACzB,WAAW,EACT,qHAAqH;QACvH,gBAAgB,EAAE,CAAC,yBAAyB,CAAC;QAC7C,eAAe,EAAE;YACf,YAAY;YACZ,uBAAuB;SACxB;KACF;IACD,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,wBAAwB;QAC9B,MAAM,EAAE,mBAAmB;QAC3B,WAAW,EACT,gGAAgG;QAClG,gBAAgB,EAAE;YAChB,+BAA+B;YAC/B,yBAAyB;YACzB,2BAA2B;SAC5B;QACD,eAAe,EAAE,CAAC,+BAA+B,CAAC;KACnD;IACD,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,iBAAiB;QACzB,WAAW,EACT,+FAA+F;QACjG,gBAAgB,EAAE,CAAC,qCAAqC,CAAC;QACzD,eAAe,EAAE,CAAC,oBAAoB,CAAC;KACxC;IACD,WAAW,EAAE;QACX,EAAE,EAAE,WAAW;QACf,IAAI,EAAE,qBAAqB;QAC3B,MAAM,EAAE,qBAAqB;QAC7B,WAAW,EACT,mHAAmH;QACrH,gBAAgB,EAAE;YAChB,wBAAwB;YACxB,uBAAuB;SACxB;QACD,eAAe,EAAE,CAAC,kCAAkC,CAAC;KACtD;CACF,CAAC;AAEF,+FAA+F;AAC/F,MAAM,UAAU,gBAAgB,CAAC,SAAiB;IAChD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,EAAE,CAAC;QACtD,IAAI,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,SAAS,CAAC;YAAE,OAAO,IAAI,CAAC;IAC7D,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAWD,MAAM,UAAU,SAAS,CACvB,MAA2E;IAE3E,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO;YACL,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,kBAAkB,EAAE,IAAI,EAAE,EAAE;YAC5B,oBAAoB,EAAE,IAAI,EAAE,IAAI;YAChC,YAAY,EAAE,IAAI,EAAE,MAAM;SAC3B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
/**
* NIST AI Risk Management Framework (NIST AI 100-1) → Sunaiva Gate feature mapping (Tier-1 T04).
*
* Source: NIST AI Risk Management Framework v1.0 (Jan 2023), Generative AI
* Profile (NIST AI 600-1, July 2024).
*
* Genesis Strategic Positioning v2 §4 Bet 2 names NIST AI RMF Measure 2.7
* and 2.9 as the procurement noun-phrase to own. This mapping makes the
* mapping machine-readable so the dossier renders it verbatim.
*
* NOT legal advice / not a formal NIST conformance claim.
*/
export type NistFunction = "GOVERN" | "MAP" | "MEASURE" | "MANAGE";
export interface NistMappingEntry {
function: NistFunction;
category: string;
subcategory: string;
/** Plain-English description of the NIST control */
description: string;
gate_features: string[];
evidence_locations: string[];
notes: string;
}
export declare const NIST_AI_RMF_MAPPING: Record<string, NistMappingEntry>;
export declare function nistFeatureIndex(): Record<string, string[]>;
//# sourceMappingURL=nist-ai-rmf.d.ts.map
{"version":3,"file":"nist-ai-rmf.d.ts","sourceRoot":"","sources":["../../../src/compliance/mappings/nist-ai-rmf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CA4FhE,CAAC;AAEF,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAS3D"}
/**
* NIST AI Risk Management Framework (NIST AI 100-1) → Sunaiva Gate feature mapping (Tier-1 T04).
*
* Source: NIST AI Risk Management Framework v1.0 (Jan 2023), Generative AI
* Profile (NIST AI 600-1, July 2024).
*
* Genesis Strategic Positioning v2 §4 Bet 2 names NIST AI RMF Measure 2.7
* and 2.9 as the procurement noun-phrase to own. This mapping makes the
* mapping machine-readable so the dossier renders it verbatim.
*
* NOT legal advice / not a formal NIST conformance claim.
*/
export const NIST_AI_RMF_MAPPING = {
"MEASURE-2.7": {
function: "MEASURE",
category: "Measure 2",
subcategory: "MEASURE 2.7",
description: "AI system security and resilience — as identified in MAP 2.3 — are evaluated and documented.",
gate_features: [
"adversarial_layer.atlas_probes",
"paranoia_mode.outbound_allowlist",
"hmac_signed_verdict_chain",
],
evidence_locations: [
"manifest.verdicts[*].adversarial_layer",
"manifest.constitutional_rules",
],
notes: "MITRE ATLAS-mapped adversarial probes generated per release. Cross-provider verifier (Patent A Pillar 3) supplies independent attack surface.",
},
"MEASURE-2.9": {
function: "MEASURE",
category: "Measure 2",
subcategory: "MEASURE 2.9",
description: "The AI model is explained, validated, and documented, and AI system output is interpreted within its context — as identified in MAP 3.5 — to inform responsible use and governance.",
gate_features: [
"explain_decision",
"ship_confidence_gate.stamp",
"compliance_dossier",
],
evidence_locations: [
"manifest.events[*].reason",
"explain_decision.output",
],
notes: "Every gate decision exposes structured reason + alternatives + bypass path via explain_decision MCP tool. Compliance dossier is the periodic interpretation artifact.",
},
"MEASURE-2.11": {
function: "MEASURE",
category: "Measure 2",
subcategory: "MEASURE 2.11",
description: "Fairness and bias — as identified in MAP 2.3 — is evaluated and results are documented.",
gate_features: ["validate_action.constitutional_rules"],
evidence_locations: ["manifest.constitutional_rules"],
notes: "Constitutional rule set documented as the bias-evaluation baseline. Sunaiva Gate is policy-neutral on fairness rules themselves — deployers configure.",
},
"MANAGE-4.1": {
function: "MANAGE",
category: "Manage 4",
subcategory: "MANAGE 4.1",
description: "Post-deployment AI system monitoring plans are implemented, including mechanisms for capturing and evaluating input from users and other relevant AI actors, appeal and override, decommissioning, incident response, recovery, and change management.",
gate_features: [
"audit_ledger",
"log_bypass",
"rollback.engine",
"time_lock.cancel",
],
evidence_locations: [
"manifest.events",
"manifest.override_audit",
],
notes: "Continuous audit ledger of every decision. Override + appeal via bypass mechanism (constitutional rules cannot be bypassed). Recovery via post-hoc rollback engine. Change management via time-lock cancellation window.",
},
"GOVERN-1.3": {
function: "GOVERN",
category: "Govern 1",
subcategory: "GOVERN 1.3",
description: "Processes, procedures, and practices are in place to determine the needed level of risk management activities based on the organization's risk tolerance.",
gate_features: [
"preset_configuration",
"constitutional_immutability",
],
evidence_locations: ["manifest.constitutional_rules"],
notes: "Presets (minimal / balanced / strict / paranoid) supply risk-tolerance tiers. Constitutional rules supply absolute floor.",
},
"GOVERN-1.4": {
function: "GOVERN",
category: "Govern 1",
subcategory: "GOVERN 1.4",
description: "The risk management process and its outcomes are established through transparent policies, procedures, and other controls based on organizational risk priorities.",
gate_features: ["compliance_dossier", "explain_decision"],
evidence_locations: ["compliance_dossier.signed_bundle"],
notes: "Compliance dossier is the periodic transparency artifact. Explain_decision is the per-event transparency artifact.",
},
};
export function nistFeatureIndex() {
const idx = {};
for (const [sub, entry] of Object.entries(NIST_AI_RMF_MAPPING)) {
for (const feat of entry.gate_features) {
if (!idx[feat])
idx[feat] = [];
idx[feat].push(sub);
}
}
return idx;
}
//# sourceMappingURL=nist-ai-rmf.js.map
{"version":3,"file":"nist-ai-rmf.js","sourceRoot":"","sources":["../../../src/compliance/mappings/nist-ai-rmf.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAeH,MAAM,CAAC,MAAM,mBAAmB,GAAqC;IACnE,aAAa,EAAE;QACb,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,aAAa;QAC1B,WAAW,EACT,8FAA8F;QAChG,aAAa,EAAE;YACb,gCAAgC;YAChC,kCAAkC;YAClC,2BAA2B;SAC5B;QACD,kBAAkB,EAAE;YAClB,wCAAwC;YACxC,+BAA+B;SAChC;QACD,KAAK,EACH,+IAA+I;KAClJ;IACD,aAAa,EAAE;QACb,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,aAAa;QAC1B,WAAW,EACT,qLAAqL;QACvL,aAAa,EAAE;YACb,kBAAkB;YAClB,4BAA4B;YAC5B,oBAAoB;SACrB;QACD,kBAAkB,EAAE;YAClB,2BAA2B;YAC3B,yBAAyB;SAC1B;QACD,KAAK,EACH,uKAAuK;KAC1K;IACD,cAAc,EAAE;QACd,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,WAAW;QACrB,WAAW,EAAE,cAAc;QAC3B,WAAW,EACT,yFAAyF;QAC3F,aAAa,EAAE,CAAC,sCAAsC,CAAC;QACvD,kBAAkB,EAAE,CAAC,+BAA+B,CAAC;QACrD,KAAK,EACH,wJAAwJ;KAC3J;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,YAAY;QACzB,WAAW,EACT,wPAAwP;QAC1P,aAAa,EAAE;YACb,cAAc;YACd,YAAY;YACZ,iBAAiB;YACjB,kBAAkB;SACnB;QACD,kBAAkB,EAAE;YAClB,iBAAiB;YACjB,yBAAyB;SAC1B;QACD,KAAK,EACH,0NAA0N;KAC7N;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,YAAY;QACzB,WAAW,EACT,2JAA2J;QAC7J,aAAa,EAAE;YACb,sBAAsB;YACtB,6BAA6B;SAC9B;QACD,kBAAkB,EAAE,CAAC,+BAA+B,CAAC;QACrD,KAAK,EACH,2HAA2H;KAC9H;IACD,YAAY,EAAE;QACZ,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,UAAU;QACpB,WAAW,EAAE,YAAY;QACzB,WAAW,EACT,oKAAoK;QACtK,aAAa,EAAE,CAAC,oBAAoB,EAAE,kBAAkB,CAAC;QACzD,kBAAkB,EAAE,CAAC,kCAAkC,CAAC;QACxD,KAAK,EACH,oHAAoH;KACvH;CACF,CAAC;AAEF,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAA6B,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/D,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,aAAa,EAAE,CAAC;YACvC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
/**
* src/cost/budget.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* Per-agent budget tracker. Daily + monthly cap enforcement.
*
* Per R6 § 3 G11: "Per-agent monthly token cap with auto-pause on exceed."
*
* Design:
* - File-backed persistence in cross-platform tempdir, sibling to session
* state and baseline store.
* - Daily counters auto-reset on date rollover.
* - Monthly counters auto-reset on month rollover.
* - Status: 'ok' | 'soft-warning' (>80% of cap) | 'hard-stop' (>= cap).
* - Caps default to env-driven values:
* SUNAIVA_COST_DAILY_CAP_USD (default $10)
* SUNAIVA_COST_MONTHLY_CAP_USD (default $100)
* - Fail-OPEN on disk errors — budget tracking is operational, not a hard
* security gate (the per-call ceiling is the hard security gate).
*
* BUSL-1.1. TypeScript strict.
*/
export interface BudgetSnapshot {
agent_id: string;
daily_spent_usd: number;
monthly_spent_usd: number;
daily_cap_usd: number;
monthly_cap_usd: number;
status: "ok" | "soft-warning" | "hard-stop";
/** YYYY-MM-DD when daily counter started. */
daily_period: string;
/** YYYY-MM when monthly counter started. */
monthly_period: string;
}
/** Read the current budget snapshot for an agent, creating one if missing. */
export declare function checkBudget(agent_id: string): Promise<BudgetSnapshot>;
/** Record spend for an agent. Returns the updated snapshot. */
export declare function recordSpend(agent_id: string, usd: number): Promise<BudgetSnapshot>;
/**
* Set explicit caps for an agent. Overrides env-default caps.
* If the caller passes zero or negative, falls back to env defaults.
*/
export declare function setCaps(agent_id: string, caps: {
daily_cap_usd?: number;
monthly_cap_usd?: number;
}): Promise<BudgetSnapshot>;
/** Test/cleanup helper. NOT exported in public API. */
export declare function _resetBudgetStore(): void;
//# sourceMappingURL=budget.d.ts.map
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/cost/budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAWH,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,IAAI,GAAG,cAAc,GAAG,WAAW,CAAC;IAC5C,6CAA6C;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,4CAA4C;IAC5C,cAAc,EAAE,MAAM,CAAC;CACxB;AA8FD,8EAA8E;AAC9E,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAgB3E;AAED,+DAA+D;AAC/D,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAaxF;AAED;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,GACzD,OAAO,CAAC,cAAc,CAAC,CASzB;AAED,uDAAuD;AACvD,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
/**
* src/cost/budget.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* Per-agent budget tracker. Daily + monthly cap enforcement.
*
* Per R6 § 3 G11: "Per-agent monthly token cap with auto-pause on exceed."
*
* Design:
* - File-backed persistence in cross-platform tempdir, sibling to session
* state and baseline store.
* - Daily counters auto-reset on date rollover.
* - Monthly counters auto-reset on month rollover.
* - Status: 'ok' | 'soft-warning' (>80% of cap) | 'hard-stop' (>= cap).
* - Caps default to env-driven values:
* SUNAIVA_COST_DAILY_CAP_USD (default $10)
* SUNAIVA_COST_MONTHLY_CAP_USD (default $100)
* - Fail-OPEN on disk errors — budget tracking is operational, not a hard
* security gate (the per-call ceiling is the hard security gate).
*
* BUSL-1.1. TypeScript strict.
*/
import { readFileSync, writeFileSync, existsSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
const BUDGET_FILE = join(tmpdir(), "sunaiva_gate_budgets.json");
const DEFAULT_DAILY_CAP = 10;
const DEFAULT_MONTHLY_CAP = 100;
const SOFT_WARNING_THRESHOLD = 0.8;
function emptyStore() {
return { byAgent: {} };
}
function readStore() {
try {
if (!existsSync(BUDGET_FILE))
return emptyStore();
const raw = readFileSync(BUDGET_FILE, "utf-8");
const parsed = JSON.parse(raw);
if (!parsed ||
typeof parsed !== "object" ||
typeof parsed.byAgent !== "object") {
return emptyStore();
}
return parsed;
}
catch {
return emptyStore();
}
}
function writeStore(s) {
try {
writeFileSync(BUDGET_FILE, JSON.stringify(s, null, 2));
}
catch {
/* fail-OPEN */
}
}
function todayUTC() {
return new Date().toISOString().slice(0, 10);
}
function thisMonthUTC() {
return new Date().toISOString().slice(0, 7);
}
function envCap(name, fallback) {
const v = process.env[name];
if (!v)
return fallback;
const n = parseFloat(v);
if (!Number.isFinite(n) || n <= 0)
return fallback;
return n;
}
function defaultSnapshot(agent_id) {
return {
agent_id,
daily_spent_usd: 0,
monthly_spent_usd: 0,
daily_cap_usd: envCap("SUNAIVA_COST_DAILY_CAP_USD", DEFAULT_DAILY_CAP),
monthly_cap_usd: envCap("SUNAIVA_COST_MONTHLY_CAP_USD", DEFAULT_MONTHLY_CAP),
status: "ok",
daily_period: todayUTC(),
monthly_period: thisMonthUTC(),
};
}
function computeStatus(s) {
if (s.daily_spent_usd >= s.daily_cap_usd || s.monthly_spent_usd >= s.monthly_cap_usd) {
return "hard-stop";
}
if (s.daily_spent_usd >= s.daily_cap_usd * SOFT_WARNING_THRESHOLD ||
s.monthly_spent_usd >= s.monthly_cap_usd * SOFT_WARNING_THRESHOLD) {
return "soft-warning";
}
return "ok";
}
/** Roll-over counters if the date or month has changed since last update. */
function rollover(s) {
const day = todayUTC();
const month = thisMonthUTC();
if (s.daily_period !== day) {
s.daily_spent_usd = 0;
s.daily_period = day;
}
if (s.monthly_period !== month) {
s.monthly_spent_usd = 0;
s.monthly_period = month;
}
s.status = computeStatus(s);
return s;
}
/** Read the current budget snapshot for an agent, creating one if missing. */
export async function checkBudget(agent_id) {
if (!agent_id || typeof agent_id !== "string") {
throw new Error(`agent_id must be a non-empty string, got: ${typeof agent_id}`);
}
const store = readStore();
let snap = store.byAgent[agent_id];
if (!snap) {
snap = defaultSnapshot(agent_id);
store.byAgent[agent_id] = snap;
writeStore(store);
}
else {
snap = rollover(snap);
store.byAgent[agent_id] = snap;
writeStore(store);
}
return snap;
}
/** Record spend for an agent. Returns the updated snapshot. */
export async function recordSpend(agent_id, usd) {
if (!Number.isFinite(usd) || usd < 0) {
throw new Error(`usd must be a non-negative finite number, got: ${usd}`);
}
const store = readStore();
let snap = store.byAgent[agent_id] ?? defaultSnapshot(agent_id);
snap = rollover(snap);
snap.daily_spent_usd = Math.round((snap.daily_spent_usd + usd) * 1_000_000) / 1_000_000;
snap.monthly_spent_usd = Math.round((snap.monthly_spent_usd + usd) * 1_000_000) / 1_000_000;
snap.status = computeStatus(snap);
store.byAgent[agent_id] = snap;
writeStore(store);
return snap;
}
/**
* Set explicit caps for an agent. Overrides env-default caps.
* If the caller passes zero or negative, falls back to env defaults.
*/
export async function setCaps(agent_id, caps) {
const store = readStore();
let snap = store.byAgent[agent_id] ?? defaultSnapshot(agent_id);
if (caps.daily_cap_usd && caps.daily_cap_usd > 0)
snap.daily_cap_usd = caps.daily_cap_usd;
if (caps.monthly_cap_usd && caps.monthly_cap_usd > 0)
snap.monthly_cap_usd = caps.monthly_cap_usd;
snap = rollover(snap);
store.byAgent[agent_id] = snap;
writeStore(store);
return snap;
}
/** Test/cleanup helper. NOT exported in public API. */
export function _resetBudgetStore() {
writeStore(emptyStore());
}
//# sourceMappingURL=budget.js.map
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/cost/budget.ts"],"names":[],"mappings":"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"}
/**
* src/cost/estimator.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* Pre-flight cost estimator for LLM calls. Used by the `check_cost` MCP tool
* and the validate_action audit pipeline.
*
* Per R6 § 3 G11 (HIGH importance): blocks expensive Opus calls > $1 unless
* an approval token is present. Per-agent monthly token cap with auto-pause
* on exceed.
*
* Design:
* - Pure function — no I/O. Budget tracking lives in budget.ts.
* - Returns `ceiling` so the caller knows the per-call soft warning value.
* - `would_exceed_monthly` is informational only — the budget tracker
* enforces the hard-stop.
*
* BUSL-1.1. TypeScript strict.
*/
import { type ModelPricing } from "./pricing.js";
export type Model = "claude-opus-4-7" | "claude-opus-4-6" | "claude-sonnet-4-6" | "claude-haiku-4" | "gpt-4o" | "gpt-4o-mini" | "o4-mini" | "gemini-2.5-pro" | "gemini-2.5-flash" | "gemini-2.5-flash-lite" | string;
export interface CostEstimate {
model: Model;
display: string;
family: ModelPricing["family"];
estimated_usd: number;
tokens_in: number;
tokens_out_estimate: number;
/** Per-call soft-warning ceiling. Above this, the gate emits a warning. */
ceiling: number;
/** Whether this single call would push the agent over its monthly cap. */
would_exceed_monthly: boolean;
/** Whether extended_context (1M-context Anthropic tier) is in effect. */
extended_context: boolean;
}
export interface EstimateOptions {
/** Required for would_exceed_monthly calculation. */
monthly_cap_usd?: number;
/** Required for would_exceed_monthly calculation. */
monthly_spent_so_far_usd?: number;
/** 2x multiplier for Anthropic 1M-context tier. Default false. */
extended_context?: boolean;
}
/**
* Estimate USD cost for an LLM call.
*
* @param model Model identifier (Anthropic / OpenAI / Google).
* @param tokens_in Input tokens.
* @param tokens_out_estimate Estimated output tokens (caller best-guess).
* @param opts Optional budget context.
*/
export declare function estimateCost(model: Model, tokens_in: number, tokens_out_estimate: number, opts?: EstimateOptions): CostEstimate;
export interface CostDecision {
decision: "allow" | "warn" | "block";
reason: string;
estimate: CostEstimate;
approval_token_required: boolean;
}
/**
* Decide whether a candidate LLM call is allowed. Used by the `check_cost`
* MCP tool and any validate_action that bundles a cost predicate.
*
* Logic:
* - estimated_usd > ceiling AND no approval_token → BLOCK
* - estimated_usd > ceiling AND approval_token present → ALLOW with reason
* - would_exceed_monthly → BLOCK regardless of approval_token (hard-stop)
* - else → WARN if > 50% of ceiling, ALLOW otherwise.
*/
export declare function decideCost(estimate: CostEstimate, opts?: {
approval_token?: string;
}): CostDecision;
//# sourceMappingURL=estimator.d.ts.map
{"version":3,"file":"estimator.d.ts","sourceRoot":"","sources":["../../src/cost/estimator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAA8C,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAE7F,MAAM,MAAM,KAAK,GACb,iBAAiB,GACjB,iBAAiB,GACjB,mBAAmB,GACnB,gBAAgB,GAChB,QAAQ,GACR,aAAa,GACb,SAAS,GACT,gBAAgB,GAChB,kBAAkB,GAClB,uBAAuB,GACvB,MAAM,CAAC;AAEX,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,oBAAoB,EAAE,OAAO,CAAC;IAC9B,yEAAyE;IACzE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qDAAqD;IACrD,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAOD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,KAAK,EAAE,KAAK,EACZ,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,MAAM,EAC3B,IAAI,GAAE,eAAoB,GACzB,YAAY,CA+Bd;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,YAAY,CAAC;IACvB,uBAAuB,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,YAAY,EACtB,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GACrC,YAAY,CA6Cd"}
/**
* src/cost/estimator.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* Pre-flight cost estimator for LLM calls. Used by the `check_cost` MCP tool
* and the validate_action audit pipeline.
*
* Per R6 § 3 G11 (HIGH importance): blocks expensive Opus calls > $1 unless
* an approval token is present. Per-agent monthly token cap with auto-pause
* on exceed.
*
* Design:
* - Pure function — no I/O. Budget tracking lives in budget.ts.
* - Returns `ceiling` so the caller knows the per-call soft warning value.
* - `would_exceed_monthly` is informational only — the budget tracker
* enforces the hard-stop.
*
* BUSL-1.1. TypeScript strict.
*/
import { lookupPricing, EXTENDED_CONTEXT_MULTIPLIER } from "./pricing.js";
/** Round to cent precision for downstream display. */
function round2(n) {
return Math.round(n * 100) / 100;
}
/**
* Estimate USD cost for an LLM call.
*
* @param model Model identifier (Anthropic / OpenAI / Google).
* @param tokens_in Input tokens.
* @param tokens_out_estimate Estimated output tokens (caller best-guess).
* @param opts Optional budget context.
*/
export function estimateCost(model, tokens_in, tokens_out_estimate, opts = {}) {
if (!Number.isFinite(tokens_in) || tokens_in < 0) {
throw new Error(`tokens_in must be a non-negative finite number, got: ${tokens_in}`);
}
if (!Number.isFinite(tokens_out_estimate) || tokens_out_estimate < 0) {
throw new Error(`tokens_out_estimate must be a non-negative finite number, got: ${tokens_out_estimate}`);
}
const pricing = lookupPricing(model);
const multiplier = opts.extended_context ? EXTENDED_CONTEXT_MULTIPLIER : 1;
const costIn = (tokens_in / 1_000_000) * pricing.per_million_in * multiplier;
const costOut = (tokens_out_estimate / 1_000_000) * pricing.per_million_out * multiplier;
const total = round2(costIn + costOut);
const monthlyCap = opts.monthly_cap_usd ?? Infinity;
const monthlySpent = opts.monthly_spent_so_far_usd ?? 0;
const wouldExceed = monthlySpent + total > monthlyCap;
return {
model,
display: pricing.display,
family: pricing.family,
estimated_usd: total,
tokens_in,
tokens_out_estimate,
ceiling: pricing.per_call_ceiling_usd,
would_exceed_monthly: wouldExceed,
extended_context: opts.extended_context === true,
};
}
/**
* Decide whether a candidate LLM call is allowed. Used by the `check_cost`
* MCP tool and any validate_action that bundles a cost predicate.
*
* Logic:
* - estimated_usd > ceiling AND no approval_token → BLOCK
* - estimated_usd > ceiling AND approval_token present → ALLOW with reason
* - would_exceed_monthly → BLOCK regardless of approval_token (hard-stop)
* - else → WARN if > 50% of ceiling, ALLOW otherwise.
*/
export function decideCost(estimate, opts = {}) {
// Hard-stop: monthly budget never bypassable by a single call.
if (estimate.would_exceed_monthly) {
return {
decision: "block",
reason: `would exceed monthly budget cap`,
estimate,
approval_token_required: false,
};
}
// Per-call ceiling.
if (estimate.estimated_usd > estimate.ceiling) {
if (opts.approval_token && opts.approval_token.trim().length > 0) {
return {
decision: "allow",
reason: `over per-call ceiling ($${estimate.ceiling}) but approval_token present`,
estimate,
approval_token_required: false,
};
}
return {
decision: "block",
reason: `estimated_usd ($${estimate.estimated_usd}) exceeds per-call ceiling ($${estimate.ceiling}) — approval token required`,
estimate,
approval_token_required: true,
};
}
// Soft warning at 50% of ceiling.
if (estimate.estimated_usd > estimate.ceiling * 0.5) {
return {
decision: "warn",
reason: `>50% of per-call ceiling; consider downgrading model`,
estimate,
approval_token_required: false,
};
}
return {
decision: "allow",
reason: "within budget",
estimate,
approval_token_required: false,
};
}
//# sourceMappingURL=estimator.js.map
{"version":3,"file":"estimator.js","sourceRoot":"","sources":["../../src/cost/estimator.ts"],"names":[],"mappings":"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"}
/**
* src/cost/pricing.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* Static pricing snapshot — 2026-05. NO live API calls per R6 § 3 G11 design
* (cost gates must work offline; pricing tables stay in-bundle).
*
* Prices are USD per 1M tokens (per public 2026-05 schedules):
* - Anthropic: https://www.anthropic.com/pricing (Opus 4.x / Sonnet 4.x)
* - OpenAI: https://openai.com/api/pricing (gpt-4o)
* - Google: https://ai.google.dev/pricing (Gemini 2.5 family)
*
* Update cadence: bump these on major price changes. Tests reference fixed
* values so a future price change requires explicit test updates — by design.
*
* BUSL-1.1. TypeScript strict.
*/
export interface ModelPricing {
/** USD per 1M input tokens. */
per_million_in: number;
/** USD per 1M output tokens. */
per_million_out: number;
/** Friendly display name. */
display: string;
/** Family classifier — useful for budget grouping. */
family: "anthropic" | "openai" | "google" | "openrouter" | "other";
/** Approximate ceiling per single call ($USD) — soft warning above this. */
per_call_ceiling_usd: number;
}
/**
* Pricing snapshot — values pinned to 2026-05 published rates.
* The "1M context" Opus variants carry a 2x premium past 200K tokens; we
* conservatively quote the base rate here. Callers that know they will burn
* >200K context should pass `extended_context: true` to estimateCost().
*/
export declare const PRICING: Record<string, ModelPricing>;
/** Default pricing for unknown models — assumes a mid-tier rate. */
export declare const UNKNOWN_MODEL_PRICING: ModelPricing;
/** 2x multiplier applied when extended_context=true (Anthropic 1M-context tier). */
export declare const EXTENDED_CONTEXT_MULTIPLIER = 2;
/** Look up pricing for a model name; falls back to UNKNOWN_MODEL_PRICING. */
export declare function lookupPricing(model: string): ModelPricing;
//# sourceMappingURL=pricing.d.ts.map
{"version":3,"file":"pricing.d.ts","sourceRoot":"","sources":["../../src/cost/pricing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,WAAW,YAAY;IAC3B,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,YAAY,GAAG,OAAO,CAAC;IACnE,4EAA4E;IAC5E,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;GAKG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CA0EhD,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,qBAAqB,EAAE,YAMnC,CAAC;AAEF,oFAAoF;AACpF,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,CAiBzD"}
/**
* src/cost/pricing.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* Static pricing snapshot — 2026-05. NO live API calls per R6 § 3 G11 design
* (cost gates must work offline; pricing tables stay in-bundle).
*
* Prices are USD per 1M tokens (per public 2026-05 schedules):
* - Anthropic: https://www.anthropic.com/pricing (Opus 4.x / Sonnet 4.x)
* - OpenAI: https://openai.com/api/pricing (gpt-4o)
* - Google: https://ai.google.dev/pricing (Gemini 2.5 family)
*
* Update cadence: bump these on major price changes. Tests reference fixed
* values so a future price change requires explicit test updates — by design.
*
* BUSL-1.1. TypeScript strict.
*/
/**
* Pricing snapshot — values pinned to 2026-05 published rates.
* The "1M context" Opus variants carry a 2x premium past 200K tokens; we
* conservatively quote the base rate here. Callers that know they will burn
* >200K context should pass `extended_context: true` to estimateCost().
*/
export const PRICING = {
// ---------- Anthropic ----------
"claude-opus-4-7": {
per_million_in: 15,
per_million_out: 75,
display: "Claude Opus 4.7",
family: "anthropic",
per_call_ceiling_usd: 1.0,
},
"claude-opus-4-6": {
per_million_in: 15,
per_million_out: 75,
display: "Claude Opus 4.6",
family: "anthropic",
per_call_ceiling_usd: 1.0,
},
"claude-sonnet-4-6": {
per_million_in: 3,
per_million_out: 15,
display: "Claude Sonnet 4.6",
family: "anthropic",
per_call_ceiling_usd: 0.5,
},
"claude-haiku-4": {
per_million_in: 0.8,
per_million_out: 4,
display: "Claude Haiku 4",
family: "anthropic",
per_call_ceiling_usd: 0.1,
},
// ---------- OpenAI ----------
"gpt-4o": {
per_million_in: 2.5,
per_million_out: 10,
display: "GPT-4o",
family: "openai",
per_call_ceiling_usd: 0.5,
},
"gpt-4o-mini": {
per_million_in: 0.15,
per_million_out: 0.6,
display: "GPT-4o mini",
family: "openai",
per_call_ceiling_usd: 0.05,
},
"o4-mini": {
per_million_in: 4,
per_million_out: 16,
display: "OpenAI o4-mini (reasoning)",
family: "openai",
per_call_ceiling_usd: 0.5,
},
// ---------- Google ----------
"gemini-2.5-pro": {
per_million_in: 1.25,
per_million_out: 5,
display: "Gemini 2.5 Pro",
family: "google",
per_call_ceiling_usd: 0.5,
},
"gemini-2.5-flash": {
per_million_in: 0.1,
per_million_out: 0.4,
display: "Gemini 2.5 Flash",
family: "google",
per_call_ceiling_usd: 0.1,
},
"gemini-2.5-flash-lite": {
per_million_in: 0.05,
per_million_out: 0.2,
display: "Gemini 2.5 Flash Lite",
family: "google",
per_call_ceiling_usd: 0.05,
},
};
/** Default pricing for unknown models — assumes a mid-tier rate. */
export const UNKNOWN_MODEL_PRICING = {
per_million_in: 5,
per_million_out: 20,
display: "(unknown model — mid-tier estimate)",
family: "other",
per_call_ceiling_usd: 0.5,
};
/** 2x multiplier applied when extended_context=true (Anthropic 1M-context tier). */
export const EXTENDED_CONTEXT_MULTIPLIER = 2;
/** Look up pricing for a model name; falls back to UNKNOWN_MODEL_PRICING. */
export function lookupPricing(model) {
const direct = PRICING[model];
if (direct)
return direct;
// Normalise common aliases.
const lower = model.toLowerCase();
if (lower.startsWith("claude-opus"))
return PRICING["claude-opus-4-7"];
if (lower.startsWith("claude-sonnet"))
return PRICING["claude-sonnet-4-6"];
if (lower.startsWith("claude-haiku"))
return PRICING["claude-haiku-4"];
if (lower.startsWith("gpt-4o-mini"))
return PRICING["gpt-4o-mini"];
if (lower.startsWith("gpt-4"))
return PRICING["gpt-4o"];
if (lower.startsWith("o4"))
return PRICING["o4-mini"];
if (lower.startsWith("gemini-2.5-flash-lite"))
return PRICING["gemini-2.5-flash-lite"];
if (lower.startsWith("gemini-2.5-flash"))
return PRICING["gemini-2.5-flash"];
if (lower.startsWith("gemini"))
return PRICING["gemini-2.5-pro"];
return UNKNOWN_MODEL_PRICING;
}
//# sourceMappingURL=pricing.js.map
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/cost/pricing.ts"],"names":[],"mappings":"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"}
/**
* src/cost/tool.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* `check_cost` MCP tool handler. Wraps estimator + budget into the MCP
* response contract used by validate.ts / index.ts.
*
* Per §5.5 of the sprint plan, also exposes the CLI subcommand:
* sunaiva-gate check-cost <model> <tokens_in> <tokens_out>
*
* BUSL-1.1. TypeScript strict.
*/
import { estimateCost, type CostDecision, type Model } from "./estimator.js";
import { checkBudget } from "./budget.js";
export interface CheckCostArgs {
/** Model identifier — anthropic / openai / google. */
model: Model;
/** Estimated input tokens. */
tokens_in: number;
/** Estimated output tokens. */
tokens_out_estimate: number;
/** Agent identifier — required for budget enforcement. */
agent_id?: string;
/** Optional approval token — allows calls above the per-call ceiling. */
approval_token?: string;
/** Optional override of monthly cap (USD). */
monthly_cap_usd?: number;
/** Optional 2x multiplier for Anthropic 1M-context tier. */
extended_context?: boolean;
/**
* If true, record this spend immediately on `allow`. Useful for caller-
* driven bookkeeping. Default false — bookkeeping is normally an explicit
* post-call step via recordSpend().
*/
record_on_allow?: boolean;
}
export interface CheckCostResult {
allowed: boolean;
decision: CostDecision["decision"];
reason: string;
estimate: ReturnType<typeof estimateCost>;
budget: Awaited<ReturnType<typeof checkBudget>> | null;
gate_version: string;
hook_name: string;
message: string;
}
/**
* Core check-cost handler. Returns a structured decision; the MCP wrapper
* formats it as a tool response.
*/
export declare function performCostCheck(args: CheckCostArgs): Promise<CheckCostResult>;
/** MCP tool handler — formats result as `content` array. */
export declare function handleCheckCost(args: CheckCostArgs): Promise<{
content: {
type: "text";
text: string;
}[];
}>;
//# sourceMappingURL=tool.d.ts.map
{"version":3,"file":"tool.d.ts","sourceRoot":"","sources":["../../src/cost/tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,YAAY,EAAc,KAAK,YAAY,EAAE,KAAK,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACzF,OAAO,EAAE,WAAW,EAAe,MAAM,aAAa,CAAC;AAKvD,MAAM,WAAW,aAAa;IAC5B,sDAAsD;IACtD,KAAK,EAAE,KAAK,CAAC;IACb,8BAA8B;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IAC1C,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CA6EpF;AAED,4DAA4D;AAC5D,wBAAsB,eAAe,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;IAClE,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C,CAAC,CAiCD"}
/**
* src/cost/tool.ts — W2-B6 / T09 (cost gates)
* --------------------------------------------------------------------------
* `check_cost` MCP tool handler. Wraps estimator + budget into the MCP
* response contract used by validate.ts / index.ts.
*
* Per §5.5 of the sprint plan, also exposes the CLI subcommand:
* sunaiva-gate check-cost <model> <tokens_in> <tokens_out>
*
* BUSL-1.1. TypeScript strict.
*/
import { estimateCost, decideCost } from "./estimator.js";
import { checkBudget, recordSpend } from "./budget.js";
const PKG_VERSION = "1.2.0";
const HOOK_NAME = "sunaiva-gate";
/**
* Core check-cost handler. Returns a structured decision; the MCP wrapper
* formats it as a tool response.
*/
export async function performCostCheck(args) {
// Kill-switch parity with validate_action.
if (process.env.DISABLE_SUNAIVA_GATE === "1") {
const estimate = estimateCost(args.model, args.tokens_in ?? 0, args.tokens_out_estimate ?? 0, {
extended_context: args.extended_context,
});
return {
allowed: true,
decision: "allow",
reason: "DISABLE_SUNAIVA_GATE=1",
estimate,
budget: null,
gate_version: PKG_VERSION,
hook_name: HOOK_NAME,
message: `[${HOOK_NAME} v${PKG_VERSION}] DISABLED via DISABLE_SUNAIVA_GATE=1 — cost check allow-all.`,
};
}
let budget = null;
let monthlyCap = args.monthly_cap_usd;
let monthlySpent = 0;
if (args.agent_id) {
budget = await checkBudget(args.agent_id);
if (!monthlyCap)
monthlyCap = budget.monthly_cap_usd;
monthlySpent = budget.monthly_spent_usd;
}
const estimate = estimateCost(args.model, args.tokens_in, args.tokens_out_estimate, {
monthly_cap_usd: monthlyCap,
monthly_spent_so_far_usd: monthlySpent,
extended_context: args.extended_context,
});
// Hard-stop on budget exhaustion regardless of approval token.
if (budget && budget.status === "hard-stop") {
return {
allowed: false,
decision: "block",
reason: `agent budget hard-stop (status=hard-stop, daily=$${budget.daily_spent_usd}/$${budget.daily_cap_usd}, monthly=$${budget.monthly_spent_usd}/$${budget.monthly_cap_usd})`,
estimate,
budget,
gate_version: PKG_VERSION,
hook_name: HOOK_NAME,
message: `[${HOOK_NAME} v${PKG_VERSION}] BLOCKED — agent ${args.agent_id} is at budget hard-stop.`,
};
}
const dec = decideCost(estimate, { approval_token: args.approval_token });
// Optional bookkeeping. Only record spend on `allow`.
if (args.record_on_allow && args.agent_id && dec.decision === "allow") {
budget = await recordSpend(args.agent_id, estimate.estimated_usd);
}
let stamp = `[${HOOK_NAME} v${PKG_VERSION}]`;
if (dec.decision === "block") {
stamp += ` BLOCKED cost-gate — ${dec.reason}`;
if (dec.approval_token_required) {
stamp += ` — pass approval_token to override per-call ceiling.`;
}
}
else if (dec.decision === "warn") {
stamp += ` WARN cost-gate — ${dec.reason}. Estimated $${estimate.estimated_usd}.`;
}
else {
stamp += ` allow cost-gate — estimated $${estimate.estimated_usd}.`;
}
return {
allowed: dec.decision !== "block",
decision: dec.decision,
reason: dec.reason,
estimate,
budget,
gate_version: PKG_VERSION,
hook_name: HOOK_NAME,
message: stamp,
};
}
/** MCP tool handler — formats result as `content` array. */
export async function handleCheckCost(args) {
try {
const result = await performCostCheck(args);
return {
content: [
{
type: "text",
text: JSON.stringify(result, null, 2),
},
],
};
}
catch (err) {
// Fail-CLOSED on internal errors per top-level contract (B3 — Findings C5).
return {
content: [
{
type: "text",
text: JSON.stringify({
allowed: false,
decision: "block",
reason: `internal error: ${err instanceof Error ? err.message : String(err)}`,
gate_version: PKG_VERSION,
hook_name: HOOK_NAME,
message: `[${HOOK_NAME} v${PKG_VERSION}] FAIL-CLOSED — check_cost internal error.`,
}, null, 2),
},
],
};
}
}
//# sourceMappingURL=tool.js.map
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/cost/tool.ts"],"names":[],"mappings":"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"}
/** Shape returned by createBaseline + persisted to disk. */
export interface Baseline {
token: string;
session_id: string;
created_at: string;
tools_called: string[];
files_touched: string[];
}
/**
* Create a new baseline snapshot for the current session state.
* Optional initial tools/files seed the baseline (e.g. when called mid-session).
*/
export declare function createBaseline(session_id: string, opts?: {
tools_called?: string[];
files_touched?: string[];
}): Promise<Baseline>;
/** Lookup a baseline by token. Returns null if not found (fail-OPEN). */
export declare function getBaseline(token: string): Baseline | null;
export interface DeltaResult {
/** True when the baseline existed and delta is meaningful. */
baseline_found: boolean;
/** Tools present in `current` but not in baseline. */
new_tools: string[];
/** Files present in `current` but not in baseline. */
new_files: string[];
}
/**
* Compute the delta of tools/files since a baseline. If the baseline is
* missing or corrupted, returns baseline_found=false and `current` data
* verbatim so the caller can decide whether to fail-OPEN (full re-eval).
*/
export declare function deltaFromBaseline(baseline_token: string, current: {
tools_called: string[];
files_touched: string[];
}): Promise<DeltaResult>;
/**
* Update a baseline to fold-in the most recent observations. Useful when a
* caller wants a rolling baseline rather than a point-in-time one.
*/
export declare function extendBaseline(token: string, add: {
tools_called?: string[];
files_touched?: string[];
}): Promise<Baseline | null>;
/** Test/cleanup helper — wipe the baseline store. NOT exported in public API. */
export declare function _resetBaselineStore(): void;
//# sourceMappingURL=baseline.d.ts.map
{"version":3,"file":"baseline.d.ts","sourceRoot":"","sources":["../../src/diff/baseline.ts"],"names":[],"mappings":"AAkCA,4DAA4D;AAC5D,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAyCD;;;GAGG;AACH,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GAC3D,OAAO,CAAC,QAAQ,CAAC,CAmBnB;AAED,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,IAAI,CAG1D;AAED,MAAM,WAAW,WAAW;IAC1B,8DAA8D;IAC9D,cAAc,EAAE,OAAO,CAAC;IACxB,sDAAsD;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,sDAAsD;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,EACtB,OAAO,EAAE;IAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,GAC3D,OAAO,CAAC,WAAW,CAAC,CAkBtB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,GACzD,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAa1B;AAED,iFAAiF;AACjF,wBAAgB,mBAAmB,IAAI,IAAI,CAE1C"}
/**
* src/diff/baseline.ts — W2-B6 / T08 (diff-aware scope)
* --------------------------------------------------------------------------
* Baseline token + delta computation for diff-aware rule evaluation.
*
* The premium ruleset evaluates against deltas — what changed since a
* baseline — rather than re-evaluating the entire session every call.
* This is the primitive R3 §3 names that AI gates currently lack.
*
* Design:
* - Tokens are opaque ULIDs (or fallback ts+rnd hex) the caller passes back.
* - Baselines are persisted to the same cross-platform tempdir as session
* state. We deliberately do NOT extend SessionState (no-touch zone for
* other builders) — instead we use a sibling file.
* - Fail-OPEN on disk errors: a missing baseline cannot be a security gate.
* Caller falls back to full evaluation.
*
* BUSL-1.1. No live network calls. TypeScript strict.
*/
import { readFileSync, writeFileSync, existsSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { randomBytes } from "node:crypto";
const BASELINE_FILE = join(tmpdir(), "sunaiva_gate_baselines.json");
/** Maximum number of baselines retained on disk before the LRU evicts. */
const MAX_BASELINES = 64;
function emptyStore() {
return { order: [], byToken: {} };
}
function readStore() {
try {
if (!existsSync(BASELINE_FILE))
return emptyStore();
const raw = readFileSync(BASELINE_FILE, "utf-8");
const parsed = JSON.parse(raw);
// Defensive — corrupted store reverts to empty (fail-OPEN).
if (!parsed ||
typeof parsed !== "object" ||
!Array.isArray(parsed.order) ||
typeof parsed.byToken !== "object") {
return emptyStore();
}
return parsed;
}
catch {
return emptyStore();
}
}
function writeStore(store) {
try {
writeFileSync(BASELINE_FILE, JSON.stringify(store, null, 2));
}
catch {
/* fail-OPEN: never crash because baseline store is unwritable */
}
}
/** Generate an opaque token. ULID-ish; collision-safe for in-process use. */
function newToken() {
const ts = Date.now().toString(36).toUpperCase();
const rnd = randomBytes(8).toString("hex").toUpperCase();
return `BL_${ts}_${rnd}`;
}
/**
* Create a new baseline snapshot for the current session state.
* Optional initial tools/files seed the baseline (e.g. when called mid-session).
*/
export async function createBaseline(session_id, opts) {
const token = newToken();
const baseline = {
token,
session_id,
created_at: new Date().toISOString(),
tools_called: Array.from(new Set(opts?.tools_called ?? [])),
files_touched: Array.from(new Set(opts?.files_touched ?? [])),
};
const store = readStore();
store.byToken[token] = baseline;
store.order.push(token);
// LRU evict — keep store bounded.
while (store.order.length > MAX_BASELINES) {
const drop = store.order.shift();
if (drop)
delete store.byToken[drop];
}
writeStore(store);
return baseline;
}
/** Lookup a baseline by token. Returns null if not found (fail-OPEN). */
export function getBaseline(token) {
const store = readStore();
return store.byToken[token] ?? null;
}
/**
* Compute the delta of tools/files since a baseline. If the baseline is
* missing or corrupted, returns baseline_found=false and `current` data
* verbatim so the caller can decide whether to fail-OPEN (full re-eval).
*/
export async function deltaFromBaseline(baseline_token, current) {
const baseline = getBaseline(baseline_token);
if (!baseline) {
return {
baseline_found: false,
new_tools: Array.from(new Set(current.tools_called)),
new_files: Array.from(new Set(current.files_touched)),
};
}
const baseTools = new Set(baseline.tools_called);
const baseFiles = new Set(baseline.files_touched);
const new_tools = current.tools_called.filter((t) => !baseTools.has(t));
const new_files = current.files_touched.filter((f) => !baseFiles.has(f));
return {
baseline_found: true,
new_tools: Array.from(new Set(new_tools)),
new_files: Array.from(new Set(new_files)),
};
}
/**
* Update a baseline to fold-in the most recent observations. Useful when a
* caller wants a rolling baseline rather than a point-in-time one.
*/
export async function extendBaseline(token, add) {
const store = readStore();
const b = store.byToken[token];
if (!b)
return null;
b.tools_called = Array.from(new Set([...b.tools_called, ...(add.tools_called ?? [])]));
b.files_touched = Array.from(new Set([...b.files_touched, ...(add.files_touched ?? [])]));
store.byToken[token] = b;
writeStore(store);
return b;
}
/** Test/cleanup helper — wipe the baseline store. NOT exported in public API. */
export function _resetBaselineStore() {
writeStore(emptyStore());
}
//# sourceMappingURL=baseline.js.map
{"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/diff/baseline.ts"],"names":[],"mappings":"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"}
export type ScopeDecision = "delta" | "full";
export interface DiffScopeResult {
decision: ScopeDecision;
baseline_token?: string;
baseline_found: boolean;
/** Tools/files net-new since baseline (empty arrays when full eval). */
new_tools: string[];
new_files: string[];
reason: string;
}
export interface DiffScopeInput {
baseline_token?: string;
/** Tools the current action touches (e.g. ["Edit"]). */
current_tools: string[];
/** Files the current action touches. */
current_files: string[];
}
/**
* Compute the scope decision for the current action.
*
* Returns `delta` only when:
* 1. A baseline token was supplied, AND
* 2. The baseline exists, AND
* 3. There is at least one new tool OR new file (otherwise nothing changed
* and the action would be a no-op for diff-aware rules — we still
* return `delta` with empty arrays so the caller can short-circuit).
*
* Returns `full` whenever there is uncertainty.
*/
export declare function computeScope(input: DiffScopeInput): Promise<DiffScopeResult>;
/**
* Given a rule's scope flag and the diff result, decide whether this rule
* should run. Only rules tagged `scope: 'diff-aware'` honor the delta
* filtering; all others always run.
*/
export declare function shouldRuleRun(ruleScope: "diff-aware" | "always" | undefined, scope: DiffScopeResult): boolean;
//# sourceMappingURL=scope.d.ts.map
{"version":3,"file":"scope.d.ts","sourceRoot":"","sources":["../../src/diff/scope.ts"],"names":[],"mappings":"AAqBA,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,OAAO,CAAC;IACxB,wEAAwE;IACxE,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,wCAAwC;IACxC,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,cAAc,GACpB,OAAO,CAAC,eAAe,CAAC,CAuC1B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,YAAY,GAAG,QAAQ,GAAG,SAAS,EAC9C,KAAK,EAAE,eAAe,GACrB,OAAO,CAKT"}
/**
* src/diff/scope.ts — W2-B6 / T08 (diff-aware scope)
* --------------------------------------------------------------------------
* Diff-aware rule filtering. Given a baseline token + a candidate action,
* decide whether the action falls inside the "delta" scope.
*
* R3 §3 / R4 — diff-awareness is a primitive AI gates lack. Reduces
* evaluation cost on long sessions (a single 8h coding session may evaluate
* 10K events; only ~1K of those touch new files/tools).
*
* Design:
* - This module does NOT short-circuit constitutional rules. Even on
* diff-aware eval, ALL constitutional rules still run on every action.
* - It only filters PREMIUM rules whose `scope: 'diff-aware'` flag is set.
* - When a baseline is missing, scope decision is `'full'` (fail-OPEN to
* re-evaluate the entire action — never silently allow more).
*
* BUSL-1.1. TypeScript strict. No live network calls.
*/
import { deltaFromBaseline } from "./baseline.js";
/**
* Compute the scope decision for the current action.
*
* Returns `delta` only when:
* 1. A baseline token was supplied, AND
* 2. The baseline exists, AND
* 3. There is at least one new tool OR new file (otherwise nothing changed
* and the action would be a no-op for diff-aware rules — we still
* return `delta` with empty arrays so the caller can short-circuit).
*
* Returns `full` whenever there is uncertainty.
*/
export async function computeScope(input) {
if (!input.baseline_token) {
return {
decision: "full",
baseline_found: false,
new_tools: input.current_tools.slice(),
new_files: input.current_files.slice(),
reason: "no baseline_token supplied — full evaluation",
};
}
const delta = await deltaFromBaseline(input.baseline_token, {
tools_called: input.current_tools,
files_touched: input.current_files,
});
if (!delta.baseline_found) {
return {
decision: "full",
baseline_token: input.baseline_token,
baseline_found: false,
new_tools: input.current_tools.slice(),
new_files: input.current_files.slice(),
reason: "baseline not found in store — full evaluation (fail-OPEN to re-eval)",
};
}
return {
decision: "delta",
baseline_token: input.baseline_token,
baseline_found: true,
new_tools: delta.new_tools,
new_files: delta.new_files,
reason: delta.new_tools.length === 0 && delta.new_files.length === 0
? "delta is empty — no diff-aware rules need to run"
: `delta scope: ${delta.new_tools.length} new tool(s), ${delta.new_files.length} new file(s)`,
};
}
/**
* Given a rule's scope flag and the diff result, decide whether this rule
* should run. Only rules tagged `scope: 'diff-aware'` honor the delta
* filtering; all others always run.
*/
export function shouldRuleRun(ruleScope, scope) {
if (ruleScope !== "diff-aware")
return true; // default: always run
if (scope.decision === "full")
return true; // fail-OPEN to re-eval
// delta scope, no changes → rule can skip
return scope.new_tools.length > 0 || scope.new_files.length > 0;
}
//# sourceMappingURL=scope.js.map
{"version":3,"file":"scope.js","sourceRoot":"","sources":["../../src/diff/scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAsBlD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAqB;IAErB,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,cAAc,EAAE,KAAK;YACrB,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE;YACtC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE;YACtC,MAAM,EAAE,8CAA8C;SACvD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,iBAAiB,CAAC,KAAK,CAAC,cAAc,EAAE;QAC1D,YAAY,EAAE,KAAK,CAAC,aAAa;QACjC,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC,CAAC;IAEH,IAAI,CAAC,KAAK,CAAC,cAAc,EAAE,CAAC;QAC1B,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,cAAc,EAAE,KAAK;YACrB,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE;YACtC,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE;YACtC,MAAM,EACJ,sEAAsE;SACzE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,OAAO;QACjB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,cAAc,EAAE,IAAI;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,MAAM,EACJ,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;YAC1D,CAAC,CAAC,kDAAkD;YACpD,CAAC,CAAC,gBAAgB,KAAK,CAAC,SAAS,CAAC,MAAM,iBAAiB,KAAK,CAAC,SAAS,CAAC,MAAM,cAAc;KAClG,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,SAA8C,EAC9C,KAAsB;IAEtB,IAAI,SAAS,KAAK,YAAY;QAAE,OAAO,IAAI,CAAC,CAAC,sBAAsB;IACnE,IAAI,KAAK,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,CAAC,uBAAuB;IACnE,0CAA0C;IAC1C,OAAO,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;AAClE,CAAC"}
/**
* --mcp-bridge decision wiring (failure_051 / failure_053 cure — production path).
*
* The installer writes every host-agent hook as
* `npx @sunaiva/gate --mcp-bridge <agent>` (see src/installer/agents/*.ts).
* That is THE production gate path for real customer deployments. Prior to
* this module the bridge handler in src/index.ts emitted a HARDCODED
* `decision: "allow"` — so the gate was a complete no-op in every installed
* deployment. failure_051's cure (the paranoia outbound gate + rule engine)
* existed but was NEVER reached from the production path.
*
* This module closes that gap by running the bridge through the SAME wired
* evaluation pipeline that the `validate_action` MCP tool uses
* (`handleValidateAction` → paranoia outbound gate → rule engine + bypass +
* fingerprint → audit). We deliberately REUSE `handleValidateAction` rather
* than re-implement the chain so the bridge and the MCP tool can never drift
* out of sync again — a single function is the one source of truth for "did
* this action pass the gate?".
*
* Contract preserved:
* - fail-OPEN on internal error (a gate bug must never block a benign tool),
* - fail-CLOSED on a confirmed-dangerous match (paranoia deny / constitutional
* violation produce a real `deny`/`ask`),
* - `SUNAIVA_PARANOIA=outbound` honored (handleValidateAction reads it),
* - DISABLE_SUNAIVA_GATE=1 kill-switch honored (handleValidateAction short-
* circuits to allowed:true),
* - the per-agent envelope SHAPE is unchanged — only the `decision` value
* becomes real, plus an additive `reason` field for audit/UX.
*
* This module is pure logic + one call into validate.ts. No process.exit, no
* stdin reading — that stays in index.ts so this is unit-testable.
*/
import type { AgentName } from "../installer/detect.js";
import { type NormalizedEvent } from "./taxonomy.js";
/**
* Canonical bridge decision. We map the gate's binary allowed/blocked plus
* the warn-ladder into the tri-state every host agent's shim can consume:
* - allow : the action passes
* - deny : the gate blocked it (paranoia deny OR rule violation)
* - ask : the gate warned (next match would block — surface to the user)
*/
export type BridgeDecision = "allow" | "deny" | "ask";
export interface BridgeVerdict {
decision: BridgeDecision;
/** Human-readable reason, drawn from the gate's self-stamped message. */
reason: string;
/** True when the decision came from the fail-OPEN error path. */
fail_open: boolean;
}
/**
* Run a normalized event through the REAL wired evaluation pipeline and
* return a tri-state bridge verdict.
*
* Drift-proof: this calls `handleValidateAction` — the exact same function
* the `validate_action` MCP tool dispatches to — so the bridge and the MCP
* tool can never diverge. There is exactly ONE evaluation chain in the
* codebase and both entry points consume it.
*
* NEVER throws. Internal errors → fail-OPEN allow (logged in `reason`).
*/
export declare function evaluateBridgeEvent(ev: NormalizedEvent): Promise<BridgeVerdict>;
/**
* End-to-end bridge entry: take a raw host-agent event payload + the agent
* name, normalize it, evaluate it through the wired pipeline, and return the
* full response envelope the shims expect.
*
* The envelope SHAPE is byte-for-byte the same fields the prior stub emitted
* (`ok`, `event`, `source_agent`, `tool`, `action`, `session_id`, `decision`,
* `gate_version`) PLUS an additive `reason` (and `fail_open` flag) — additive
* fields are safe because every shim parses by key, never by position. The
* load-bearing change is that `decision` is now REAL.
*/
export declare function runBridge(raw: unknown, agent: AgentName, gateVersion: string): Promise<{
ok: true;
event: string;
source_agent: string;
tool: string | undefined;
action: string | undefined;
session_id: string | undefined;
decision: BridgeDecision;
reason: string;
fail_open: boolean;
gate_version: string;
}>;
//# sourceMappingURL=bridge.d.ts.map
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/events/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAqB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAGxE;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,cAAc,CAAC;IACzB,yEAAyE;IACzE,MAAM,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,SAAS,EAAE,OAAO,CAAC;CACpB;AA2FD;;;;;;;;;;GAUG;AACH,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,eAAe,GAClB,OAAO,CAAC,aAAa,CAAC,CAgDxB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAC7B,GAAG,EAAE,OAAO,EACZ,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;IACT,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC,CAeD"}
/**
* --mcp-bridge decision wiring (failure_051 / failure_053 cure — production path).
*
* The installer writes every host-agent hook as
* `npx @sunaiva/gate --mcp-bridge <agent>` (see src/installer/agents/*.ts).
* That is THE production gate path for real customer deployments. Prior to
* this module the bridge handler in src/index.ts emitted a HARDCODED
* `decision: "allow"` — so the gate was a complete no-op in every installed
* deployment. failure_051's cure (the paranoia outbound gate + rule engine)
* existed but was NEVER reached from the production path.
*
* This module closes that gap by running the bridge through the SAME wired
* evaluation pipeline that the `validate_action` MCP tool uses
* (`handleValidateAction` → paranoia outbound gate → rule engine + bypass +
* fingerprint → audit). We deliberately REUSE `handleValidateAction` rather
* than re-implement the chain so the bridge and the MCP tool can never drift
* out of sync again — a single function is the one source of truth for "did
* this action pass the gate?".
*
* Contract preserved:
* - fail-OPEN on internal error (a gate bug must never block a benign tool),
* - fail-CLOSED on a confirmed-dangerous match (paranoia deny / constitutional
* violation produce a real `deny`/`ask`),
* - `SUNAIVA_PARANOIA=outbound` honored (handleValidateAction reads it),
* - DISABLE_SUNAIVA_GATE=1 kill-switch honored (handleValidateAction short-
* circuits to allowed:true),
* - the per-agent envelope SHAPE is unchanged — only the `decision` value
* becomes real, plus an additive `reason` field for audit/UX.
*
* This module is pure logic + one call into validate.ts. No process.exit, no
* stdin reading — that stays in index.ts so this is unit-testable.
*/
import { normalizeIncoming } from "./taxonomy.js";
import { handleValidateAction } from "../tools/validate.js";
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
/**
* Parse the JSON verdict body that `handleValidateAction` returns inside its
* MCP `content[0].text` envelope. Total — never throws. On any parse failure
* we fail-OPEN (allow) because a malformed gate response must not block a
* benign tool (failure mode contract §). The failure is still surfaced in
* `reason` so the audit trail records that the gate response was unreadable.
*/
function parseValidateVerdict(toolResult) {
try {
const r = toolResult;
const text = r?.content?.[0]?.text;
if (typeof text !== "string") {
return {
allowed: true,
message: "gate response had no text body (fail-OPEN)",
hasWarnings: false,
parsed: false,
};
}
const body = JSON.parse(text);
const allowed = body.allowed === true;
const message = typeof body.message === "string" ? body.message : "";
const hasWarnings = Array.isArray(body.warnings) && body.warnings.length > 0;
return { allowed, message, hasWarnings, parsed: true };
}
catch (err) {
return {
allowed: true,
message: `gate response unparseable (fail-OPEN): ${err instanceof Error ? err.message : String(err)}`,
hasWarnings: false,
parsed: false,
};
}
}
/**
* Build the `ValidateActionArgs` the wired pipeline expects from a normalized
* event. The rule engine + paranoia gate both operate on the `action` string,
* so we feed them the best-effort action the taxonomy extracted (command
* preview / tool+input JSON / prompt). We also pass `tool_name` so the
* PostToolUse rollback path can engage when the host sent a PostToolUse event.
*
* If the taxonomy could not extract an action (e.g. a bare SessionStart with
* no payload), there is nothing outbound to gate — we return null and the
* caller emits a plain allow. This preserves 1.1.0 behaviour for lifecycle
* events that carry no tool action.
*/
function toValidateArgs(ev) {
if (typeof ev.action !== "string" || ev.action.length === 0)
return null;
const args = {
action: ev.action,
};
if (ev.tool)
args.tool_name = ev.tool;
// Map the canonical lifecycle event onto the validate hook_phase so the
// PostToolUse rollback engine can engage for post-mutation blocks.
if (ev.event === "PostToolUse" || ev.event === "PostToolUseFailure") {
args.hook_phase = "PostToolUse";
}
else {
args.hook_phase = "PreToolUse";
}
return args;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
* Run a normalized event through the REAL wired evaluation pipeline and
* return a tri-state bridge verdict.
*
* Drift-proof: this calls `handleValidateAction` — the exact same function
* the `validate_action` MCP tool dispatches to — so the bridge and the MCP
* tool can never diverge. There is exactly ONE evaluation chain in the
* codebase and both entry points consume it.
*
* NEVER throws. Internal errors → fail-OPEN allow (logged in `reason`).
*/
export async function evaluateBridgeEvent(ev) {
// Lifecycle events with no extractable action: nothing to gate.
const args = toValidateArgs(ev);
if (args === null) {
return {
decision: "allow",
reason: "no gateable action in event",
fail_open: false,
};
}
try {
const toolResult = await handleValidateAction(args);
const { allowed, message, hasWarnings, parsed } = parseValidateVerdict(toolResult);
if (!parsed) {
// Unreadable gate response → fail-OPEN (a gate bug must not block a tool).
return { decision: "allow", reason: message, fail_open: true };
}
if (!allowed) {
// Real block — paranoia deny OR rule violation. fail-CLOSED as designed.
return {
decision: "deny",
reason: message || "blocked by sunaiva-gate",
fail_open: false,
};
}
if (hasWarnings) {
// Warn-ladder: allowed for now, but the host should confirm.
return {
decision: "ask",
reason: message || "sunaiva-gate warning",
fail_open: false,
};
}
return { decision: "allow", reason: message || "allow", fail_open: false };
}
catch (err) {
// Fail-OPEN: a crash inside the gate must never block a benign tool.
// The error is still surfaced in `reason` so the audit trail captures it.
return {
decision: "allow",
reason: `gate internal error (fail-OPEN): ${err instanceof Error ? err.message : String(err)}`,
fail_open: true,
};
}
}
/**
* End-to-end bridge entry: take a raw host-agent event payload + the agent
* name, normalize it, evaluate it through the wired pipeline, and return the
* full response envelope the shims expect.
*
* The envelope SHAPE is byte-for-byte the same fields the prior stub emitted
* (`ok`, `event`, `source_agent`, `tool`, `action`, `session_id`, `decision`,
* `gate_version`) PLUS an additive `reason` (and `fail_open` flag) — additive
* fields are safe because every shim parses by key, never by position. The
* load-bearing change is that `decision` is now REAL.
*/
export async function runBridge(raw, agent, gateVersion) {
const normalized = normalizeIncoming(raw, agent);
const verdict = await evaluateBridgeEvent(normalized);
return {
ok: true,
event: normalized.event,
source_agent: normalized.source_agent,
tool: normalized.tool,
action: normalized.action,
session_id: normalized.session_id,
decision: verdict.decision,
reason: verdict.reason,
fail_open: verdict.fail_open,
gate_version: gateVersion,
};
}
//# sourceMappingURL=bridge.js.map
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/events/bridge.ts"],"names":[],"mappings":"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"}
/**
* 14-event Tier-1 normalization taxonomy (T02).
*
* Source: R1 §1 (28-event canon, of which the 14 most safety-relevant are
* implemented in 1.2.0). Each hook shim — regardless of source agent — emits
* a NormalizedEvent on the same shape so the single rule engine evaluates
* every event identically.
*
* Strategy: each source agent has its own raw event shape (Claude Code uses
* `{ hookEventName, tool_name, tool_input }`, Cursor uses
* `{ event, tool, parameters }`, etc.). We coerce all of them into the
* canonical NormalizedEvent envelope below. Unknown / unmapped raw events
* fall back to event=Notification with full raw payload preserved in
* `context.raw` for audit fidelity (Rule 32 — no lossy compression).
*
* IMPORTANT: this module MUST stay pure (no I/O, no clock). All normalization
* is deterministic so tests can pin behaviour without mocks.
*/
import type { AgentDetection } from "../installer/detect.js";
/**
* Tier-1 lifecycle events. Drawn from the 28-event canon (R1 §1) — the 14 most
* safety-relevant for 1.2.0. Other events (PreSubmit, SessionResume,
* MCPToolListChanged, etc.) deferred to 1.3.0.
*/
export type TierOneEvent = "SessionStart" | "UserPromptSubmit" | "PreToolUse" | "PermissionRequest" | "PostToolUse" | "PostToolUseFailure" | "SubagentStart" | "SubagentStop" | "Stop" | "FileChanged" | "ConfigChange" | "PreCompact" | "Notification" | "SessionEnd";
export declare const TIER_ONE_EVENTS: readonly TierOneEvent[];
export interface NormalizedEvent {
/** Canonical Tier-1 event name. */
event: TierOneEvent;
/** Source agent that emitted the raw event. */
source_agent: AgentDetection["agent"];
/** Tool the agent intended to invoke (PreToolUse / PostToolUse / PermissionRequest). */
tool?: string;
/**
* Best-effort action string suitable for the rule engine. For tool-use events
* this is the command preview (e.g. "git push origin main"). For others it
* may be the prompt text or a structured summary.
*/
action?: string;
/** Arbitrary additional context preserved from the source event. */
context?: Record<string, unknown>;
/** Session identifier if the source agent provided one. */
session_id?: string;
/** Original raw payload, opaque — never mutated. */
raw?: unknown;
}
/**
* Normalize a raw event from a specific source agent into the canonical
* envelope. Total function — never throws. Unknown event names fall back to
* `Notification` (the catch-all bucket per R1 §1).
*
* @param raw the raw event payload from the agent's hook
* @param sourceAgent which agent emitted it
*/
export declare function normalizeIncoming(raw: unknown, sourceAgent: AgentDetection["agent"]): NormalizedEvent;
/** Test helper: does the source agent know about this raw event name? */
export declare function isKnownRawEvent(rawName: string, sourceAgent: AgentDetection["agent"]): boolean;
/** Test helper: list every raw event name a given agent knows about. */
export declare function listRawEventNames(sourceAgent: AgentDetection["agent"]): readonly string[];
//# sourceMappingURL=taxonomy.d.ts.map
{"version":3,"file":"taxonomy.d.ts","sourceRoot":"","sources":["../../src/events/taxonomy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GACpB,cAAc,GACd,kBAAkB,GAClB,YAAY,GACZ,mBAAmB,GACnB,aAAa,GACb,oBAAoB,GACpB,eAAe,GACf,cAAc,GACd,MAAM,GACN,aAAa,GACb,cAAc,GACd,YAAY,GACZ,cAAc,GACd,YAAY,CAAC;AAEjB,eAAO,MAAM,eAAe,EAAE,SAAS,YAAY,EAejD,CAAC;AAEH,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,KAAK,EAAE,YAAY,CAAC;IACpB,+CAA+C;IAC/C,YAAY,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC;IACtC,wFAAwF;IACxF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAoMD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,OAAO,EACZ,WAAW,EAAE,cAAc,CAAC,OAAO,CAAC,GACnC,eAAe,CA8CjB;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,cAAc,CAAC,OAAO,CAAC,GACnC,OAAO,CAGT;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,cAAc,CAAC,OAAO,CAAC,GACnC,SAAS,MAAM,EAAE,CAEnB"}
/**
* 14-event Tier-1 normalization taxonomy (T02).
*
* Source: R1 §1 (28-event canon, of which the 14 most safety-relevant are
* implemented in 1.2.0). Each hook shim — regardless of source agent — emits
* a NormalizedEvent on the same shape so the single rule engine evaluates
* every event identically.
*
* Strategy: each source agent has its own raw event shape (Claude Code uses
* `{ hookEventName, tool_name, tool_input }`, Cursor uses
* `{ event, tool, parameters }`, etc.). We coerce all of them into the
* canonical NormalizedEvent envelope below. Unknown / unmapped raw events
* fall back to event=Notification with full raw payload preserved in
* `context.raw` for audit fidelity (Rule 32 — no lossy compression).
*
* IMPORTANT: this module MUST stay pure (no I/O, no clock). All normalization
* is deterministic so tests can pin behaviour without mocks.
*/
export const TIER_ONE_EVENTS = Object.freeze([
"SessionStart",
"UserPromptSubmit",
"PreToolUse",
"PermissionRequest",
"PostToolUse",
"PostToolUseFailure",
"SubagentStart",
"SubagentStop",
"Stop",
"FileChanged",
"ConfigChange",
"PreCompact",
"Notification",
"SessionEnd",
]);
// ---------------------------------------------------------------------------
// Per-agent raw → canonical event mappings.
// Kept exhaustive so adding agent N+1 is a single switch arm + a mapping
// table. New mappings MUST be deterministic and total (never throw on
// unknown shapes — fall back to Notification with raw preserved).
// ---------------------------------------------------------------------------
/**
* Claude Code hook payload reference: Anthropic Claude Code Hooks spec, May 2026.
* Examples: `hookEventName: "PreToolUse"` / `"PostToolUse"` / `"SessionStart"`.
*/
const CLAUDE_CODE_EVENT_MAP = {
SessionStart: "SessionStart",
UserPromptSubmit: "UserPromptSubmit",
PreToolUse: "PreToolUse",
PermissionRequest: "PermissionRequest",
PostToolUse: "PostToolUse",
PostToolUseFailure: "PostToolUseFailure",
SubagentStart: "SubagentStart",
SubagentStop: "SubagentStop",
Stop: "Stop",
FileChanged: "FileChanged",
ConfigChange: "ConfigChange",
PreCompact: "PreCompact",
Notification: "Notification",
SessionEnd: "SessionEnd",
};
/** Cursor 1.7+ hooks emit kebab-case event names (per R4 §4 docs). */
const CURSOR_EVENT_MAP = {
"session-start": "SessionStart",
"user-prompt-submit": "UserPromptSubmit",
"pre-tool-use": "PreToolUse",
"permission-request": "PermissionRequest",
"post-tool-use": "PostToolUse",
"post-tool-use-failure": "PostToolUseFailure",
"subagent-start": "SubagentStart",
"subagent-stop": "SubagentStop",
stop: "Stop",
"file-changed": "FileChanged",
"config-change": "ConfigChange",
"pre-compact": "PreCompact",
notification: "Notification",
"session-end": "SessionEnd",
};
/** OpenAI Codex CLI envelope (stdin/stdout JSON). */
const CODEX_EVENT_MAP = {
on_start: "SessionStart",
on_prompt: "UserPromptSubmit",
on_tool_call: "PreToolUse",
on_tool_call_result: "PostToolUse",
on_tool_call_error: "PostToolUseFailure",
on_stop: "Stop",
on_end: "SessionEnd",
};
/** GitHub Copilot CLI envelope (preview). */
const COPILOT_EVENT_MAP = {
session_start: "SessionStart",
prompt_submitted: "UserPromptSubmit",
before_tool: "PreToolUse",
after_tool: "PostToolUse",
tool_failed: "PostToolUseFailure",
permission_prompt: "PermissionRequest",
session_end: "SessionEnd",
};
/** Gemini CLI middleware envelope. */
const GEMINI_EVENT_MAP = {
start: "SessionStart",
prompt: "UserPromptSubmit",
preTool: "PreToolUse",
postTool: "PostToolUse",
toolError: "PostToolUseFailure",
permission: "PermissionRequest",
notify: "Notification",
end: "SessionEnd",
};
/** Cline (VS Code) MCP-only — events arrive as MCP tool calls. */
const CLINE_EVENT_MAP = {
"session.start": "SessionStart",
"prompt.submit": "UserPromptSubmit",
"tool.pre": "PreToolUse",
"tool.post": "PostToolUse",
"tool.fail": "PostToolUseFailure",
"session.end": "SessionEnd",
};
/** Aider `--lint-cmd` is best-effort — emits a synthetic PostToolUse per change. */
const AIDER_EVENT_MAP = {
start: "SessionStart",
pre_change: "PreToolUse",
post_change: "PostToolUse",
lint: "PostToolUse",
end: "SessionEnd",
};
/** Per-agent dispatch table. */
const AGENT_MAPS = {
"claude-code": CLAUDE_CODE_EVENT_MAP,
cursor: CURSOR_EVENT_MAP,
codex: CODEX_EVENT_MAP,
copilot: COPILOT_EVENT_MAP,
gemini: GEMINI_EVENT_MAP,
cline: CLINE_EVENT_MAP,
aider: AIDER_EVENT_MAP,
};
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function getString(obj, ...keys) {
if (!obj || typeof obj !== "object")
return undefined;
const rec = obj;
for (const k of keys) {
const v = rec[k];
if (typeof v === "string" && v.length > 0)
return v;
}
return undefined;
}
function getRecord(obj, ...keys) {
if (!obj || typeof obj !== "object")
return undefined;
const rec = obj;
for (const k of keys) {
const v = rec[k];
if (v && typeof v === "object" && !Array.isArray(v)) {
return v;
}
}
return undefined;
}
/**
* Build the canonical action string for the rule engine. Prefers an explicit
* command preview, then falls back to a tool+input concat, then the prompt
* text. NEVER throws — returns undefined if nothing extractable.
*/
function extractAction(raw, tool) {
if (!raw || typeof raw !== "object")
return undefined;
const r = raw;
// 1. explicit command preview
const direct = getString(r, "command", "command_preview", "action", "preview") ?? undefined;
if (direct)
return direct;
// 2. tool input bundle
const toolInput = getRecord(r, "tool_input", "parameters", "args", "arguments", "input");
if (toolInput) {
const inner = getString(toolInput, "command", "cmd", "shell", "action", "url") ?? undefined;
if (inner)
return inner;
// Best-effort: stringify shallow input as JSON for the rule engine
try {
const json = JSON.stringify(toolInput);
if (tool)
return `${tool} ${json}`;
return json;
}
catch {
/* swallow */
}
}
// 3. user prompt body
const prompt = getString(r, "prompt", "user_prompt", "text", "message");
if (prompt)
return prompt;
return tool;
}
function extractSessionId(raw) {
return getString(raw, "session_id", "sessionId", "session", "sid", "conversation_id", "conversationId");
}
function extractTool(raw) {
return getString(raw, "tool_name", "tool", "name", "function", "command_name");
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
* Normalize a raw event from a specific source agent into the canonical
* envelope. Total function — never throws. Unknown event names fall back to
* `Notification` (the catch-all bucket per R1 §1).
*
* @param raw the raw event payload from the agent's hook
* @param sourceAgent which agent emitted it
*/
export function normalizeIncoming(raw, sourceAgent) {
const eventName = getString(raw, "hookEventName", "event", "type", "name", "phase", "kind");
const map = AGENT_MAPS[sourceAgent] ?? {};
let canonical = eventName !== undefined ? map[eventName] : undefined;
if (!canonical) {
// If the event name matches a Tier-1 canonical name directly, accept it.
if (eventName && TIER_ONE_EVENTS.includes(eventName)) {
canonical = eventName;
}
else {
canonical = "Notification";
}
}
const tool = extractTool(raw);
const action = extractAction(raw, tool);
const session_id = extractSessionId(raw);
const context = {};
if (eventName && eventName !== canonical) {
context.source_event = eventName;
}
// Surface any user-provided context block verbatim for audit fidelity (Rule 32)
const userContext = getRecord(raw, "context", "metadata", "meta");
if (userContext)
context.user_context = userContext;
const out = {
event: canonical,
source_agent: sourceAgent,
raw,
};
if (tool !== undefined)
out.tool = tool;
if (action !== undefined)
out.action = action;
if (session_id !== undefined)
out.session_id = session_id;
if (Object.keys(context).length > 0)
out.context = context;
return out;
}
/** Test helper: does the source agent know about this raw event name? */
export function isKnownRawEvent(rawName, sourceAgent) {
const map = AGENT_MAPS[sourceAgent] ?? {};
return Object.prototype.hasOwnProperty.call(map, rawName);
}
/** Test helper: list every raw event name a given agent knows about. */
export function listRawEventNames(sourceAgent) {
return Object.freeze(Object.keys(AGENT_MAPS[sourceAgent] ?? {}));
}
//# sourceMappingURL=taxonomy.js.map
{"version":3,"file":"taxonomy.js","sourceRoot":"","sources":["../../src/events/taxonomy.ts"],"names":[],"mappings":"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"}
export interface ExplanationRule {
id: string;
name: string;
description: string;
severity: string;
category?: string;
enforcement?: string;
}
export interface Explanation {
block_id: string;
rule: ExplanationRule;
evidence: string;
alternatives: string[];
bypass_path?: string;
eu_ai_act_article: 13;
/** When this block occurred (ISO). */
timestamp?: string;
/** Action excerpt that was blocked. */
action_preview?: string;
/** Severity tier from rule-engine (HARD / SOFT / WARN). */
severity_tier?: string;
}
export interface ExplainOptions {
/** Test override for audit log path. */
auditLogPath?: string;
/** Test override for rules.json path. */
rulesPath?: string;
/** Test override for the constitutional rule ID set. */
constitutionalRuleIds?: Set<string>;
}
export declare function explain(block_id: string, opts?: ExplainOptions): Promise<Explanation>;
/** List candidate block_ids in the current audit log (helper for users / tests). */
export declare function listBlockIds(opts?: {
auditLogPath?: string;
limit?: number;
}): Array<{
block_id: string;
timestamp?: string;
rule_id?: string;
type?: string;
}>;
//# sourceMappingURL=engine.d.ts.map
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/explain/engine.ts"],"names":[],"mappings":"AAwCA,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,eAAe,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,EAAE,CAAC;IACtB,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,2DAA2D;IAC3D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,wCAAwC;IACxC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,qBAAqB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACrC;AA+MD,wBAAsB,OAAO,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,WAAW,CAAC,CA6GtB;AAED,oFAAoF;AACpF,wBAAgB,YAAY,CAC1B,IAAI,GAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAO,GACnD,KAAK,CAAC;IACP,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC,CAmBD"}
/**
* Self-Explanation Engine — Sprint 1.2.0 (T12, builder W2-B4).
*
* Implements EU AI Act Article 13 (transparency) requirement: every gate
* decision must be interpretable. The explain() function takes a block_id
* (audit-log entry identifier) and returns a structured Explanation object
* with rule details, evidence, alternative actions, and bypass guidance.
*
* The audit log (~/.sunaiva/audit/audit.jsonl) does NOT assign per-entry IDs
* by default — entries are positional. We support two block_id shapes:
*
* 1. `audit_<timestamp>` — locate the entry by exact ISO timestamp.
* 2. `audit_<sha256-of-line>` — first-12 hex chars of the line's sha256.
*
* Both shapes are computed at lookup time from the live audit log, so older
* entries do not need migration. Tests use fixture audit logs via opts.auditLogPath.
*/
import { existsSync, readFileSync } from "node:fs";
import { join } from "node:path";
import { homedir } from "node:os";
import { createHash } from "node:crypto";
const DEFAULT_AUDIT_PATH = join(homedir(), ".sunaiva", "audit", "audit.jsonl");
const DEFAULT_RULES_PATH_CANDIDATES = [
// dist/rules/rules.json (post-build)
join(process.cwd(), "dist", "rules", "rules.json"),
// rules/rules.json (dev / repo root)
join(process.cwd(), "rules", "rules.json"),
];
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
function computeBlockHashId(line) {
return "audit_" + createHash("sha256").update(line).digest("hex").slice(0, 12);
}
function computeBlockTsId(timestamp) {
// Sanitize timestamp for use in an id
return "audit_ts_" + timestamp.replace(/[^A-Za-z0-9_.-]/g, "_");
}
function loadAuditEntries(auditPath) {
if (!existsSync(auditPath))
return [];
const raw = readFileSync(auditPath, "utf-8");
const out = [];
for (const line of raw.split(/\r?\n/)) {
const trimmed = line.trim();
if (!trimmed)
continue;
let entry;
try {
entry = JSON.parse(trimmed);
}
catch {
continue;
}
const ts_id = entry.timestamp ? computeBlockTsId(entry.timestamp) : undefined;
out.push({
line: trimmed,
entry,
hash_id: computeBlockHashId(trimmed),
ts_id,
});
}
return out;
}
function loadRules(rulesPath) {
const candidates = rulesPath ? [rulesPath] : DEFAULT_RULES_PATH_CANDIDATES;
for (const p of candidates) {
if (existsSync(p)) {
try {
const parsed = JSON.parse(readFileSync(p, "utf-8"));
if (Array.isArray(parsed))
return parsed;
}
catch {
// try next candidate
}
}
}
return [];
}
function isConstitutionalRule(ruleId, constSet) {
if (constSet)
return constSet.has(ruleId);
// Try to lazily import from compiled defaults.
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const mod = require("../config/defaults.js");
if (mod?.CONSTITUTIONAL_RULE_IDS instanceof Set) {
return mod.CONSTITUTIONAL_RULE_IDS.has(ruleId);
}
if (Array.isArray(mod?.CONSTITUTIONAL_RULE_IDS)) {
return mod.CONSTITUTIONAL_RULE_IDS.includes(ruleId);
}
}
catch {
// ignore
}
return false;
}
function buildAlternatives(rule, action, ruleId) {
const alts = [];
if (rule?.example_allowed) {
alts.push(`Allowed pattern: ${rule.example_allowed}`);
}
// Rule 42 (ship_confidence_gate) is special-cased — it's not in rules.json
// but is the constitutional publish-class gate.
if (ruleId === "rule-42") {
alts.push("Run the ship_confidence_check MCP tool to obtain a signed verdict (paid tier) before publishing.");
alts.push("Create a fresh approval token at data/deploy_queue/APPROVAL_TOKENS/ (free tier) for time-boxed authorization.");
alts.push("Re-run the dogfood verdict and ensure level=GREEN within the 60-min freshness window.");
return alts;
}
// Category-specific advice
const cat = rule?.category;
if (cat === "financial-safety") {
alts.push("Present pricing/scope to the user and obtain explicit approval before proceeding.");
alts.push("Use a test-mode key (e.g., Stripe TEST_KEY) and document the approval flow.");
}
else if (cat === "data-protection") {
alts.push("Use environment variable references rather than literal credentials.");
alts.push("Move the secret into a managed secrets store (e.g., 1Password, Vault).");
}
else if (cat === "action-governance") {
alts.push("Stage the action as a dry-run first: set SUNAIVA_GATE_DRY_RUN=1 to verify intent.");
alts.push("Confirm the destructive operation with the user before executing.");
}
else if (cat === "ai-safety") {
alts.push("Ask the user for explicit guidance on the agentic decision point.");
alts.push("Log the agent's reasoning trace before taking any irreversible action.");
}
else if (cat === "publish-class") {
alts.push("Run the ship_confidence_check tool to obtain a signed verdict.");
alts.push("Create an approval token at data/deploy_queue/APPROVAL_TOKENS/ to grant time-boxed authorization.");
}
else {
alts.push("Ask the user how to proceed in light of the blocked rule.");
}
// action param kept for future use — suppress unused warning
void action;
return alts;
}
function buildBypassPath(ruleId, isConstitutional) {
// Rule 42 (Ship Confidence Gate) is constitutional by design — the gate itself
// is the constitutional enforcement layer. Never offer a SUNAIVA_SKIP path for it.
if (ruleId === "rule-42") {
return undefined;
}
if (isConstitutional) {
return undefined; // Constitutional rules cannot be bypassed
}
return ("Non-constitutional rule. You may grant a one-shot bypass via the log_bypass MCP tool " +
"(record reason for audit), or skip this rule for the session via `SUNAIVA_SKIP=" +
ruleId +
"`. " +
"Both options are audit-logged.");
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
export async function explain(block_id, opts = {}) {
if (!block_id || typeof block_id !== "string") {
throw new Error("explain: block_id is required");
}
const auditPath = opts.auditLogPath ?? DEFAULT_AUDIT_PATH;
const entries = loadAuditEntries(auditPath);
if (entries.length === 0) {
throw new Error(`explain: audit log empty or missing at ${auditPath}`);
}
// Find by hash_id or ts_id
let matched = entries.find((e) => e.hash_id === block_id || e.ts_id === block_id);
if (!matched) {
// Allow a raw ISO timestamp shorthand
matched = entries.find((e) => e.entry.timestamp === block_id);
}
if (!matched) {
throw new Error(`explain: no audit entry matched block_id '${block_id}'`);
}
const auditEntry = matched.entry;
// Determine which rule applied. Prefer the first violation; fall back to rule_id.
let ruleId;
if (Array.isArray(auditEntry.violations) &&
auditEntry.violations.length > 0) {
ruleId = auditEntry.violations[0];
}
else if (typeof auditEntry.rule_id === "string") {
ruleId = auditEntry.rule_id;
}
// For ship_confidence_block entries, the rule is Rule 42.
if (!ruleId && auditEntry.event_type === "ship_confidence_block") {
ruleId = "rule-42";
}
if (!ruleId) {
throw new Error(`explain: audit entry at block_id '${block_id}' has no rule_id / violations`);
}
// Look up rule definition
const rules = loadRules(opts.rulesPath);
const ruleSpec = rules.find((r) => r.id === ruleId) ?? null;
const isConst = isConstitutionalRule(ruleId, opts.constitutionalRuleIds);
// Rule 42 is constitutional by design even though it's not in rules.json
const isRule42 = ruleId === "rule-42";
const rule = {
id: ruleId,
name: isRule42
? "Rule 42 — Ship Confidence Gate"
: (ruleSpec?.name ?? "Unknown rule"),
description: isRule42
? "Constitutional publish-class gate. Requires either a signed verdict (paid tier) OR a fresh approval token (free tier) before any publish/deploy action proceeds."
: (ruleSpec?.description ??
`Rule ${ruleId} (no description available in current rule set)`),
severity: ruleSpec?.severity ?? "block",
category: ruleSpec?.category ?? (isRule42 ? "publish-class" : undefined),
enforcement: isRule42
? "constitutional"
: (ruleSpec?.enforcement ?? (isConst ? "constitutional" : "configurable")),
};
const evidence = typeof auditEntry.reason === "string" && auditEntry.reason
? auditEntry.reason
: typeof auditEntry.detection_pattern === "string"
? auditEntry.detection_pattern
: ruleSpec?.example_blocked
? `Pattern matched: ${ruleSpec.example_blocked}`
: `Action triggered rule ${ruleId}`;
return {
block_id,
rule,
evidence,
alternatives: buildAlternatives(ruleSpec, typeof auditEntry.action === "string" ? auditEntry.action : undefined, ruleId),
bypass_path: buildBypassPath(ruleId, isConst),
eu_ai_act_article: 13,
timestamp: typeof auditEntry.timestamp === "string"
? auditEntry.timestamp
: undefined,
action_preview: typeof auditEntry.action === "string"
? auditEntry.action.slice(0, 200)
: typeof auditEntry.artifact_id === "string"
? `[artifact: ${auditEntry.artifact_id}]`
: undefined,
severity_tier: typeof auditEntry.severity_tier === "string"
? auditEntry.severity_tier
: undefined,
};
}
/** List candidate block_ids in the current audit log (helper for users / tests). */
export function listBlockIds(opts = {}) {
const entries = loadAuditEntries(opts.auditLogPath ?? DEFAULT_AUDIT_PATH);
const limit = opts.limit ?? 50;
return entries.slice(-limit).map((e) => ({
block_id: e.hash_id,
timestamp: e.entry.timestamp,
rule_id: Array.isArray(e.entry.violations) && e.entry.violations.length > 0
? e.entry.violations[0]
: typeof e.entry.rule_id === "string"
? e.entry.rule_id
: undefined,
type: typeof e.entry.type === "string"
? e.entry.type
: typeof e.entry.event_type === "string"
? e.entry.event_type
: undefined,
}));
}
//# sourceMappingURL=engine.js.map
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/explain/engine.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
/**
* Aider shim writer (<50 LoC core).
*
* Strategy: Aider has no hook system but DOES support `--lint-cmd` which runs
* after every code change. We hijack lint-cmd to invoke our gate on every
* change as a synthetic PostToolUse event. Coverage is partial (no PreToolUse,
* no PermissionRequest) — Aider's PostToolUse blocking is best-effort.
*
* Future: a native fork would add proper hook events. Deferred to 1.3.0
* per strategic plan §1.3.
*/
import type { AgentDetection } from "../detect.js";
import type { ShimWriteResult } from "./claude-code.js";
export declare function buildShimEntry(mcpEndpoint?: string): string;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=aider.d.ts.map
{"version":3,"file":"aider.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/aider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAa3D;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CA4BjB"}
/**
* Aider shim writer (<50 LoC core).
*
* Strategy: Aider has no hook system but DOES support `--lint-cmd` which runs
* after every code change. We hijack lint-cmd to invoke our gate on every
* change as a synthetic PostToolUse event. Coverage is partial (no PreToolUse,
* no PermissionRequest) — Aider's PostToolUse blocking is best-effort.
*
* Future: a native fork would add proper hook events. Deferred to 1.3.0
* per strategic plan §1.3.
*/
import * as fs from "node:fs";
import * as path from "node:path";
const LINT_COMMAND = "npx @sunaiva/gate --mcp-bridge aider";
export function buildShimEntry(mcpEndpoint) {
const envHeader = mcpEndpoint
? `# SUNAIVA_GATE_MCP_ENDPOINT=${mcpEndpoint}\n# (set as an environment variable before running aider)\n`
: "";
return `${envHeader}# Sunaiva Gate — Aider integration (partial coverage)
# Runs after every code change as a synthetic PostToolUse event.
# Pre-change blocking requires a native Aider fork (1.3.0+).
lint-cmd:
- "${LINT_COMMAND}"
# Set 'auto-lint: true' so aider invokes the gate without prompting
auto-lint: true
`;
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
let existing = "";
try {
existing = fs.readFileSync(target, "utf-8");
}
catch {
existing = "";
}
// Idempotent: only append our block if it isn't already present
const block = buildShimEntry(opts.mcpEndpoint);
let payload;
if (existing.includes("Sunaiva Gate")) {
payload = existing; // no-op rewrite (still report bytes for the result)
}
else {
payload = existing
? existing.replace(/\s+$/, "") + "\n\n" + block
: block;
}
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: block,
};
}
//# sourceMappingURL=aider.js.map
{"version":3,"file":"aider.js","sourceRoot":"","sources":["../../../src/installer/agents/aider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAE5D,MAAM,UAAU,cAAc,CAAC,WAAoB;IACjD,MAAM,SAAS,GAAG,WAAW;QAC3B,CAAC,CAAC,+BAA+B,WAAW,6DAA6D;QACzG,CAAC,CAAC,EAAE,CAAC;IACP,OAAO,GAAG,SAAS;;;;;OAKd,YAAY;;;CAGlB,CAAC;AACF,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,SAAyB,EACzB,OAAmD,EAAE;IAErD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC;IACrC,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,IAAI,CAAC;QACH,QAAQ,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,GAAG,EAAE,CAAC;IAChB,CAAC;IACD,gEAAgE;IAChE,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,IAAI,OAAe,CAAC;IACpB,IAAI,QAAQ,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;QACtC,OAAO,GAAG,QAAQ,CAAC,CAAC,oDAAoD;IAC1E,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,QAAQ;YAChB,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,GAAG,KAAK;YAC/C,CAAC,CAAC,KAAK,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
/**
* Claude Code shim writer (<50 LoC core).
*
* Strategy: register the hook command in ~/.claude/settings.json under the
* `hooks` block. We use the `npx @sunaiva/gate --mcp-bridge claude-code`
* sub-invocation that pipes the raw event payload through normalizeIncoming()
* and into the MCP `validate_action` tool. Verdict is returned via stdout JSON
* so we sidestep Anthropic issue #24327 (idle on exit-2 stderr).
*/
import type { AgentDetection } from "../detect.js";
export interface ShimWriteResult {
written_to: string;
bytes: number;
dry_run: boolean;
/** What the shim entry looks like — useful for verification + dry-run preview. */
preview: unknown;
}
/**
* Build the JSON patch that should appear in ~/.claude/settings.json under
* `hooks`. Exported separately for tests + dry-run preview.
*/
export declare function buildShimEntry(mcpEndpoint?: string): Record<string, unknown>;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=claude-code.d.ts.map
{"version":3,"file":"claude-code.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/claude-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAInD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,kFAAkF;IAClF,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAoBzB;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CA8BjB"}
/**
* Claude Code shim writer (<50 LoC core).
*
* Strategy: register the hook command in ~/.claude/settings.json under the
* `hooks` block. We use the `npx @sunaiva/gate --mcp-bridge claude-code`
* sub-invocation that pipes the raw event payload through normalizeIncoming()
* and into the MCP `validate_action` tool. Verdict is returned via stdout JSON
* so we sidestep Anthropic issue #24327 (idle on exit-2 stderr).
*/
import * as fs from "node:fs";
import * as path from "node:path";
const HOOK_COMMAND = "npx @sunaiva/gate --mcp-bridge claude-code";
/**
* Build the JSON patch that should appear in ~/.claude/settings.json under
* `hooks`. Exported separately for tests + dry-run preview.
*/
export function buildShimEntry(mcpEndpoint) {
const env = {};
if (mcpEndpoint)
env["SUNAIVA_GATE_MCP_ENDPOINT"] = mcpEndpoint;
return {
PreToolUse: [
{ matcher: "*", hooks: [{ type: "command", command: HOOK_COMMAND, env }] },
],
PostToolUse: [
{ matcher: "*", hooks: [{ type: "command", command: HOOK_COMMAND, env }] },
],
UserPromptSubmit: [
{ hooks: [{ type: "command", command: HOOK_COMMAND, env }] },
],
SessionStart: [
{ hooks: [{ type: "command", command: HOOK_COMMAND, env }] },
],
SessionEnd: [{ hooks: [{ type: "command", command: HOOK_COMMAND, env }] }],
PreCompact: [{ hooks: [{ type: "command", command: HOOK_COMMAND, env }] }],
Stop: [{ hooks: [{ type: "command", command: HOOK_COMMAND, env }] }],
};
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
const entry = buildShimEntry(opts.mcpEndpoint);
let existing = {};
try {
existing = JSON.parse(fs.readFileSync(target, "utf-8"));
}
catch {
existing = {};
}
const next = {
...existing,
hooks: {
...existing["hooks"],
...entry,
},
};
const payload = JSON.stringify(next, null, 2);
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: entry,
};
}
//# sourceMappingURL=claude-code.js.map
{"version":3,"file":"claude-code.js","sourceRoot":"","sources":["../../../src/installer/agents/claude-code.ts"],"names":[],"mappings":"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"}
/**
* Cline (VS Code) shim writer (<50 LoC core).
*
* Strategy: Cline has NO native hook system — it's MCP-only. We register
* @sunaiva/gate as an MCP server in the workspace's .vscode/settings.json
* under `cline.mcpServers`. Cline then calls the `validate_action` tool
* directly via MCP protocol, no shell shim needed.
*/
import type { AgentDetection } from "../detect.js";
import type { ShimWriteResult } from "./claude-code.js";
export declare function buildShimEntry(mcpEndpoint?: string): Record<string, unknown>;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=cline.d.ts.map
{"version":3,"file":"cline.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/cline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CAkCjB"}
/**
* Cline (VS Code) shim writer (<50 LoC core).
*
* Strategy: Cline has NO native hook system — it's MCP-only. We register
* @sunaiva/gate as an MCP server in the workspace's .vscode/settings.json
* under `cline.mcpServers`. Cline then calls the `validate_action` tool
* directly via MCP protocol, no shell shim needed.
*/
import * as fs from "node:fs";
import * as path from "node:path";
export function buildShimEntry(mcpEndpoint) {
return {
"cline.mcpServers": {
"sunaiva-gate": {
command: "npx",
args: ["-y", "@sunaiva/gate"],
env: mcpEndpoint ? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint } : {},
},
},
};
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
let existing = {};
try {
existing = JSON.parse(fs.readFileSync(target, "utf-8"));
}
catch {
existing = {};
}
const patch = buildShimEntry(opts.mcpEndpoint);
// Merge cline.mcpServers preserving any sibling servers the user has set up
const existingServers = existing["cline.mcpServers"] ?? {};
const patchServers = patch["cline.mcpServers"];
const next = {
...existing,
"cline.mcpServers": {
...existingServers,
...patchServers,
},
};
const payload = JSON.stringify(next, null, 2);
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: patch,
};
}
//# sourceMappingURL=cline.js.map
{"version":3,"file":"cline.js","sourceRoot":"","sources":["../../../src/installer/agents/cline.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,MAAM,UAAU,cAAc,CAC5B,WAAoB;IAEpB,OAAO;QACL,kBAAkB,EAAE;YAClB,cAAc,EAAE;gBACd,OAAO,EAAE,KAAK;gBACd,IAAI,EAAE,CAAC,IAAI,EAAE,eAAe,CAAC;gBAC7B,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;aACnE;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,SAAyB,EACzB,OAAmD,EAAE;IAErD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC;IACrC,IAAI,QAAQ,GAA4B,EAAE,CAAC;IAC3C,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAGrD,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ,GAAG,EAAE,CAAC;IAChB,CAAC;IACD,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,4EAA4E;IAC5E,MAAM,eAAe,GAClB,QAAQ,CAAC,kBAAkB,CAAyC,IAAI,EAAE,CAAC;IAC9E,MAAM,YAAY,GAAG,KAAK,CAAC,kBAAkB,CAA4B,CAAC;IAC1E,MAAM,IAAI,GAAG;QACX,GAAG,QAAQ;QACX,kBAAkB,EAAE;YAClB,GAAG,eAAe;YAClB,GAAG,YAAY;SAChB;KACF,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
/**
* OpenAI Codex CLI shim writer (<50 LoC core).
*
* Strategy: write ~/.codex/hooks.toml. Codex CLI uses TOML for its hook
* configuration. The hook command receives the raw event on stdin and is
* expected to write its verdict to stdout as JSON. We bridge that into our
* MCP layer via `--mcp-bridge codex`.
*
* NOTE: Codex CLI hooks are PREVIEW status (May 2026). README will flag this.
*/
import type { AgentDetection } from "../detect.js";
import type { ShimWriteResult } from "./claude-code.js";
export declare function buildShimEntry(mcpEndpoint?: string): string;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=codex.d.ts.map
{"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAgB,cAAc,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CA+B3D;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CAajB"}
/**
* OpenAI Codex CLI shim writer (<50 LoC core).
*
* Strategy: write ~/.codex/hooks.toml. Codex CLI uses TOML for its hook
* configuration. The hook command receives the raw event on stdin and is
* expected to write its verdict to stdout as JSON. We bridge that into our
* MCP layer via `--mcp-bridge codex`.
*
* NOTE: Codex CLI hooks are PREVIEW status (May 2026). README will flag this.
*/
import * as fs from "node:fs";
import * as path from "node:path";
const HOOK_COMMAND = "npx @sunaiva/gate --mcp-bridge codex";
export function buildShimEntry(mcpEndpoint) {
const envLine = mcpEndpoint
? `\nenv = { SUNAIVA_GATE_MCP_ENDPOINT = "${mcpEndpoint}" }`
: "";
return `# Sunaiva Gate — Codex CLI hook (preview, 1.2.0)
# Routes all Tier-1 lifecycle events into the MCP validate_action tool.
[[hooks]]
event = "on_tool_call"
command = "${HOOK_COMMAND}"${envLine}
[[hooks]]
event = "on_tool_call_result"
command = "${HOOK_COMMAND}"${envLine}
[[hooks]]
event = "on_tool_call_error"
command = "${HOOK_COMMAND}"${envLine}
[[hooks]]
event = "on_prompt"
command = "${HOOK_COMMAND}"${envLine}
[[hooks]]
event = "on_start"
command = "${HOOK_COMMAND}"${envLine}
[[hooks]]
event = "on_end"
command = "${HOOK_COMMAND}"${envLine}
`;
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
const payload = buildShimEntry(opts.mcpEndpoint);
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: payload,
};
}
//# sourceMappingURL=codex.js.map
{"version":3,"file":"codex.js","sourceRoot":"","sources":["../../../src/installer/agents/codex.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,MAAM,YAAY,GAAG,sCAAsC,CAAC;AAE5D,MAAM,UAAU,cAAc,CAAC,WAAoB;IACjD,MAAM,OAAO,GAAG,WAAW;QACzB,CAAC,CAAC,0CAA0C,WAAW,KAAK;QAC5D,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;;;;;aAKI,YAAY,IAAI,OAAO;;;;aAIvB,YAAY,IAAI,OAAO;;;;aAIvB,YAAY,IAAI,OAAO;;;;aAIvB,YAAY,IAAI,OAAO;;;;aAIvB,YAAY,IAAI,OAAO;;;;aAIvB,YAAY,IAAI,OAAO;CACnC,CAAC;AACF,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,SAAyB,EACzB,OAAmD,EAAE;IAErD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC;IACrC,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACjD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACtB,OAAO,EAAE,OAAO;KACjB,CAAC;AACJ,CAAC"}
/**
* GitHub Copilot CLI shim writer (<50 LoC core).
*
* Strategy: write ~/.config/github-copilot/hooks.json (preview, May 2026).
* Copilot CLI sends a JSON event on stdin and reads a JSON decision from
* stdout — same envelope shape as Codex.
*
* STATUS: PREVIEW (R4 §1 — Copilot CLI hooks are May 2026-recent). README
* flags this as preview-only.
*/
import type { AgentDetection } from "../detect.js";
import type { ShimWriteResult } from "./claude-code.js";
export declare function buildShimEntry(mcpEndpoint?: string): Record<string, unknown>;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=copilot.d.ts.map
{"version":3,"file":"copilot.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/copilot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiBzB;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CAcjB"}
/**
* GitHub Copilot CLI shim writer (<50 LoC core).
*
* Strategy: write ~/.config/github-copilot/hooks.json (preview, May 2026).
* Copilot CLI sends a JSON event on stdin and reads a JSON decision from
* stdout — same envelope shape as Codex.
*
* STATUS: PREVIEW (R4 §1 — Copilot CLI hooks are May 2026-recent). README
* flags this as preview-only.
*/
import * as fs from "node:fs";
import * as path from "node:path";
const HOOK_COMMAND = "npx @sunaiva/gate --mcp-bridge copilot";
export function buildShimEntry(mcpEndpoint) {
const env = mcpEndpoint
? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint }
: {};
return {
version: 1,
sunaiva_gate_preview: true,
hooks: [
{ on: "session_start", run: HOOK_COMMAND, env },
{ on: "prompt_submitted", run: HOOK_COMMAND, env },
{ on: "before_tool", run: HOOK_COMMAND, env, blocking: true },
{ on: "after_tool", run: HOOK_COMMAND, env },
{ on: "tool_failed", run: HOOK_COMMAND, env },
{ on: "permission_prompt", run: HOOK_COMMAND, env, blocking: true },
{ on: "session_end", run: HOOK_COMMAND, env },
],
};
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
const entry = buildShimEntry(opts.mcpEndpoint);
const payload = JSON.stringify(entry, null, 2);
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: entry,
};
}
//# sourceMappingURL=copilot.js.map
{"version":3,"file":"copilot.js","sourceRoot":"","sources":["../../../src/installer/agents/copilot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,MAAM,YAAY,GAAG,wCAAwC,CAAC;AAE9D,MAAM,UAAU,cAAc,CAC5B,WAAoB;IAEpB,MAAM,GAAG,GAA2B,WAAW;QAC7C,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE;QAC5C,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,OAAO,EAAE,CAAC;QACV,oBAAoB,EAAE,IAAI;QAC1B,KAAK,EAAE;YACL,EAAE,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE;YAC/C,EAAE,EAAE,EAAE,kBAAkB,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE;YAClD,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;YAC7D,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE;YAC5C,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE;YAC7C,EAAE,EAAE,EAAE,mBAAmB,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE;YACnE,EAAE,EAAE,EAAE,aAAa,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE;SAC9C;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,SAAyB,EACzB,OAAmD,EAAE;IAErD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC;IACrC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
/**
* Cursor 1.7+ shim writer (<50 LoC core).
*
* Strategy: write ~/.cursor/hooks.json with a `validate_action` hook that
* shells out to `npx @sunaiva/gate --mcp-bridge cursor`. Cursor 1.7+ supports
* `permissionDecision: 'deny'` in the hook response which lets us BLOCK
* without exit-code shenanigans.
*/
import type { AgentDetection } from "../detect.js";
import type { ShimWriteResult } from "./claude-code.js";
export declare function buildShimEntry(mcpEndpoint?: string): Record<string, unknown>;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=cursor.d.ts.map
{"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA2BzB;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CAcjB"}
/**
* Cursor 1.7+ shim writer (<50 LoC core).
*
* Strategy: write ~/.cursor/hooks.json with a `validate_action` hook that
* shells out to `npx @sunaiva/gate --mcp-bridge cursor`. Cursor 1.7+ supports
* `permissionDecision: 'deny'` in the hook response which lets us BLOCK
* without exit-code shenanigans.
*/
import * as fs from "node:fs";
import * as path from "node:path";
const HOOK_COMMAND = "npx @sunaiva/gate --mcp-bridge cursor";
export function buildShimEntry(mcpEndpoint) {
return {
version: 1,
hooks: {
"pre-tool-use": {
command: HOOK_COMMAND,
env: mcpEndpoint ? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint } : {},
decision: "permission",
},
"post-tool-use": {
command: HOOK_COMMAND,
env: mcpEndpoint ? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint } : {},
},
"user-prompt-submit": {
command: HOOK_COMMAND,
env: mcpEndpoint ? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint } : {},
},
"session-start": {
command: HOOK_COMMAND,
env: mcpEndpoint ? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint } : {},
},
"session-end": {
command: HOOK_COMMAND,
env: mcpEndpoint ? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint } : {},
},
},
};
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
const entry = buildShimEntry(opts.mcpEndpoint);
const payload = JSON.stringify(entry, null, 2);
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: entry,
};
}
//# sourceMappingURL=cursor.js.map
{"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../src/installer/agents/cursor.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D,MAAM,UAAU,cAAc,CAC5B,WAAoB;IAEpB,OAAO;QACL,OAAO,EAAE,CAAC;QACV,KAAK,EAAE;YACL,cAAc,EAAE;gBACd,OAAO,EAAE,YAAY;gBACrB,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;gBAClE,QAAQ,EAAE,YAAY;aACvB;YACD,eAAe,EAAE;gBACf,OAAO,EAAE,YAAY;gBACrB,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;aACnE;YACD,oBAAoB,EAAE;gBACpB,OAAO,EAAE,YAAY;gBACrB,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;aACnE;YACD,eAAe,EAAE;gBACf,OAAO,EAAE,YAAY;gBACrB,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;aACnE;YACD,aAAa,EAAE;gBACb,OAAO,EAAE,YAAY;gBACrB,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE;aACnE;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,SAAyB,EACzB,OAAmD,EAAE;IAErD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC;IACrC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
/**
* Gemini CLI middleware shim writer (<50 LoC core).
*
* Strategy: write ~/.gemini/middleware.json. Gemini CLI's middleware system
* wraps tool invocations with pre/post handlers — we register the gate as
* the first middleware so it sees every event.
*/
import type { AgentDetection } from "../detect.js";
import type { ShimWriteResult } from "./claude-code.js";
export declare function buildShimEntry(mcpEndpoint?: string): Record<string, unknown>;
export declare function writeShim(detection: AgentDetection, opts?: {
dryRun?: boolean;
mcpEndpoint?: string;
}): ShimWriteResult;
//# sourceMappingURL=gemini.d.ts.map
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/installer/agents/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIxD,wBAAgB,cAAc,CAC5B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA0BzB;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,cAAc,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,eAAe,CAcjB"}
/**
* Gemini CLI middleware shim writer (<50 LoC core).
*
* Strategy: write ~/.gemini/middleware.json. Gemini CLI's middleware system
* wraps tool invocations with pre/post handlers — we register the gate as
* the first middleware so it sees every event.
*/
import * as fs from "node:fs";
import * as path from "node:path";
const HOOK_COMMAND = "npx @sunaiva/gate --mcp-bridge gemini";
export function buildShimEntry(mcpEndpoint) {
const env = mcpEndpoint
? { SUNAIVA_GATE_MCP_ENDPOINT: mcpEndpoint }
: {};
return {
middlewares: [
{
name: "sunaiva-gate",
priority: 1,
events: [
"preTool",
"postTool",
"toolError",
"prompt",
"start",
"end",
"permission",
"notify",
],
command: HOOK_COMMAND,
env,
timeout_ms: 5000,
on_timeout: "block",
},
],
};
}
export function writeShim(detection, opts = {}) {
const target = detection.config_path;
const entry = buildShimEntry(opts.mcpEndpoint);
const payload = JSON.stringify(entry, null, 2);
if (!opts.dryRun) {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.writeFileSync(target, payload, "utf-8");
}
return {
written_to: target,
bytes: Buffer.byteLength(payload, "utf-8"),
dry_run: !!opts.dryRun,
preview: entry,
};
}
//# sourceMappingURL=gemini.js.map
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/installer/agents/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D,MAAM,UAAU,cAAc,CAC5B,WAAoB;IAEpB,MAAM,GAAG,GAA2B,WAAW;QAC7C,CAAC,CAAC,EAAE,yBAAyB,EAAE,WAAW,EAAE;QAC5C,CAAC,CAAC,EAAE,CAAC;IACP,OAAO;QACL,WAAW,EAAE;YACX;gBACE,IAAI,EAAE,cAAc;gBACpB,QAAQ,EAAE,CAAC;gBACX,MAAM,EAAE;oBACN,SAAS;oBACT,UAAU;oBACV,WAAW;oBACX,QAAQ;oBACR,OAAO;oBACP,KAAK;oBACL,YAAY;oBACZ,QAAQ;iBACT;gBACD,OAAO,EAAE,YAAY;gBACrB,GAAG;gBACH,UAAU,EAAE,IAAI;gBAChB,UAAU,EAAE,OAAO;aACpB;SACF;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,SAAS,CACvB,SAAyB,EACzB,OAAmD,EAAE;IAErD,MAAM,MAAM,GAAG,SAAS,CAAC,WAAW,CAAC;IACrC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO;QACL,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC;QAC1C,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACtB,OAAO,EAAE,KAAK;KACf,CAAC;AACJ,CAAC"}
/**
* in-toto Statement v1 envelope serializer (W2-B3 / T03).
*
* Produces SLSA Provenance v1.0-conformant `_type: in-toto.io/Statement/v1`
* payloads that wrap a {@link SignedVerdict} and the artifact whose
* ship-confidence the verdict authorizes.
*
* The output is a JSONL line conforming to the in-toto v1 envelope shape:
*
* {"payloadType":"application/vnd.in-toto+json",
* "payload":"<base64(canonical-json(statement))>",
* "signatures":[{"keyid":"<id>","sig":"<base64-or-hex>"}]}
*
* This module does ONLY offline / pre-keyed signing per R-01:
* - No Fulcio (CA) issuance.
* - No Rekor (transparency log) submission.
* - HMAC-SHA256 canonical-JSON signature (matching §5.4 of the sprint plan)
* OR an externally-injected detached signature, depending on caller.
*
* Verification: any cosign / sigstore verifier that accepts the in-toto
* envelope shape can verify against the provided public-key material when
* the caller signs with an asymmetric scheme. For the 1.2.0 sprint, the
* default sign path is HMAC-SHA256 to stay consistent with the rest of
* Sunaiva Gate's signature scheme (§5.4 of SPRINT_1_2_0_PLAN.md) — this
* keeps the bundle dependency-free.
*/
/** SLSA v1.0 builder block. */
export interface SlsaBuilder {
id: string;
version?: Record<string, string>;
builderDependencies?: Array<{
uri: string;
digest?: Record<string, string>;
}>;
}
/** SLSA v1.0 buildType-agnostic predicate. */
export interface SlsaProvenance {
buildDefinition: {
buildType: string;
externalParameters: Record<string, unknown>;
internalParameters?: Record<string, unknown>;
resolvedDependencies?: Array<{
uri?: string;
digest?: Record<string, string>;
name?: string;
}>;
};
runDetails: {
builder: SlsaBuilder;
metadata?: {
invocationId?: string;
startedOn?: string;
finishedOn?: string;
};
byproducts?: Array<{
name?: string;
uri?: string;
digest?: Record<string, string>;
content?: string;
}>;
};
}
/** in-toto Statement v1 envelope (payload-side). */
export interface InTotoStatement {
_type: "https://in-toto.io/Statement/v1";
subject: Array<{
name: string;
digest: {
sha256: string;
};
}>;
predicateType: "https://slsa.dev/provenance/v1";
predicate: SlsaProvenance;
}
/** SignedVerdict shape — mirrors §5.3 of SPRINT_1_2_0_PLAN.md. */
export interface SignedVerdictLike {
verdict_id: string;
artifact_id: string;
level: "GREEN" | "YELLOW" | "RED" | string;
signature: string;
signing_key_id?: string;
freshness_window_minutes?: number;
signed_at: string;
ruleset_version?: string;
findings?: unknown[];
}
/**
* Build a SLSA Provenance v1.0 in-toto Statement v1 payload from a signed
* verdict and the artifact it authorizes.
*
* The returned object is JSON-canonicalizable; callers should pass it
* through {@link envelopeToJsonl} together with a signature to obtain the
* final `.intoto.jsonl` line.
*
* Throws TypeError if any required input is missing.
*/
export declare function buildInTotoStatement(verdict: SignedVerdictLike, artifact: {
name: string;
sha256: string;
}): InTotoStatement;
/**
* Sign a statement with an HMAC-SHA256 key, returning hex.
*
* For asymmetric signing (cosign/sigstore offline keys), callers should
* sign the canonical JSON externally and pass the result into
* {@link envelopeToJsonl} directly via the `signature` parameter.
*/
export declare function signStatementHmac(stmt: InTotoStatement, key: Buffer): string;
/**
* Wrap a signed statement into a JSONL line per the in-toto envelope shape.
*
* The output is exactly ONE line of JSON terminated by '\n', as expected by
* tools that consume `.intoto.jsonl`:
*
* {"payloadType":"application/vnd.in-toto+json",
* "payload":"<base64>",
* "signatures":[{"keyid":"<keyid>","sig":"<signature>"}]}
*
* The signature is taken verbatim (caller's responsibility to base64 it
* if their verifier requires base64-only signatures; we accept hex for
* HMAC signing convenience).
*/
export declare function envelopeToJsonl(stmt: InTotoStatement, signature: string, keyid: string): string;
/**
* Decode a previously-produced JSONL envelope back into its parts. Used in
* tests + tooling to verify that the envelope round-trips cleanly.
*/
export declare function parseEnvelopeJsonl(line: string): {
statement: InTotoStatement;
signature: string;
keyid: string;
payloadB64: string;
};
//# sourceMappingURL=intoto.d.ts.map
{"version":3,"file":"intoto.d.ts","sourceRoot":"","sources":["../../../src/installer/attestation/intoto.ts"],"names":[],"mappings":"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"}
/**
* in-toto Statement v1 envelope serializer (W2-B3 / T03).
*
* Produces SLSA Provenance v1.0-conformant `_type: in-toto.io/Statement/v1`
* payloads that wrap a {@link SignedVerdict} and the artifact whose
* ship-confidence the verdict authorizes.
*
* The output is a JSONL line conforming to the in-toto v1 envelope shape:
*
* {"payloadType":"application/vnd.in-toto+json",
* "payload":"<base64(canonical-json(statement))>",
* "signatures":[{"keyid":"<id>","sig":"<base64-or-hex>"}]}
*
* This module does ONLY offline / pre-keyed signing per R-01:
* - No Fulcio (CA) issuance.
* - No Rekor (transparency log) submission.
* - HMAC-SHA256 canonical-JSON signature (matching §5.4 of the sprint plan)
* OR an externally-injected detached signature, depending on caller.
*
* Verification: any cosign / sigstore verifier that accepts the in-toto
* envelope shape can verify against the provided public-key material when
* the caller signs with an asymmetric scheme. For the 1.2.0 sprint, the
* default sign path is HMAC-SHA256 to stay consistent with the rest of
* Sunaiva Gate's signature scheme (§5.4 of SPRINT_1_2_0_PLAN.md) — this
* keeps the bundle dependency-free.
*/
import { createHash } from "node:crypto";
import { canonicalJson, signPayload } from "../../engine/hmac-verifier.js";
// ---------------------------------------------------------------------------
// Builder type constants
// ---------------------------------------------------------------------------
const BUILD_TYPE = "https://sunaiva.ai/buildtypes/ship-confidence/v1";
const BUILDER_ID = "https://sunaiva.ai/builders/sunaiva-gate@v1.2.0";
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
* Build a SLSA Provenance v1.0 in-toto Statement v1 payload from a signed
* verdict and the artifact it authorizes.
*
* The returned object is JSON-canonicalizable; callers should pass it
* through {@link envelopeToJsonl} together with a signature to obtain the
* final `.intoto.jsonl` line.
*
* Throws TypeError if any required input is missing.
*/
export function buildInTotoStatement(verdict, artifact) {
if (!verdict || typeof verdict !== "object") {
throw new TypeError("buildInTotoStatement: verdict is required");
}
if (!artifact || !artifact.name || !artifact.sha256) {
throw new TypeError("buildInTotoStatement: artifact.name and artifact.sha256 are required");
}
if (!/^[0-9a-f]{64}$/i.test(artifact.sha256)) {
throw new TypeError("buildInTotoStatement: artifact.sha256 must be a 64-char hex string");
}
if (!verdict.verdict_id || !verdict.signed_at || !verdict.level) {
throw new TypeError("buildInTotoStatement: verdict.verdict_id, verdict.level, and verdict.signed_at are required");
}
const predicate = {
buildDefinition: {
buildType: BUILD_TYPE,
externalParameters: {
artifact_id: verdict.artifact_id,
ruleset_version: verdict.ruleset_version ?? null,
},
internalParameters: {
gate_version: "1.2.0",
verdict_level: verdict.level,
freshness_window_minutes: verdict.freshness_window_minutes ?? null,
},
resolvedDependencies: [
{
name: "sunaiva-ship-confidence-verdict",
uri: `sunaiva://verdict/${verdict.verdict_id}`,
digest: { sha256: hashHex(verdict.verdict_id) },
},
],
},
runDetails: {
builder: {
id: BUILDER_ID,
version: { "@sunaiva/gate": "1.2.0" },
},
metadata: {
invocationId: verdict.verdict_id,
startedOn: verdict.signed_at,
finishedOn: verdict.signed_at,
},
byproducts: [
{
name: "verdict.signed.json",
uri: `sunaiva://verdict/${verdict.verdict_id}.signed.json`,
},
],
},
};
return {
_type: "https://in-toto.io/Statement/v1",
subject: [
{
name: artifact.name,
digest: { sha256: artifact.sha256.toLowerCase() },
},
],
predicateType: "https://slsa.dev/provenance/v1",
predicate,
};
}
/**
* Sign a statement with an HMAC-SHA256 key, returning hex.
*
* For asymmetric signing (cosign/sigstore offline keys), callers should
* sign the canonical JSON externally and pass the result into
* {@link envelopeToJsonl} directly via the `signature` parameter.
*/
export function signStatementHmac(stmt, key) {
const payload = canonicalJson(stmt);
return signPayload(payload, key);
}
/**
* Wrap a signed statement into a JSONL line per the in-toto envelope shape.
*
* The output is exactly ONE line of JSON terminated by '\n', as expected by
* tools that consume `.intoto.jsonl`:
*
* {"payloadType":"application/vnd.in-toto+json",
* "payload":"<base64>",
* "signatures":[{"keyid":"<keyid>","sig":"<signature>"}]}
*
* The signature is taken verbatim (caller's responsibility to base64 it
* if their verifier requires base64-only signatures; we accept hex for
* HMAC signing convenience).
*/
export function envelopeToJsonl(stmt, signature, keyid) {
if (typeof signature !== "string" || signature.length === 0) {
throw new TypeError("envelopeToJsonl: signature must be a non-empty string");
}
if (typeof keyid !== "string" || keyid.length === 0) {
throw new TypeError("envelopeToJsonl: keyid must be a non-empty string");
}
const payloadJson = canonicalJson(stmt).toString("utf-8");
const payloadB64 = Buffer.from(payloadJson, "utf-8").toString("base64");
const envelope = {
payloadType: "application/vnd.in-toto+json",
payload: payloadB64,
signatures: [{ keyid, sig: signature }],
};
return JSON.stringify(envelope) + "\n";
}
/**
* Decode a previously-produced JSONL envelope back into its parts. Used in
* tests + tooling to verify that the envelope round-trips cleanly.
*/
export function parseEnvelopeJsonl(line) {
const trimmed = line.replace(/\n+$/, "");
const env = JSON.parse(trimmed);
if (env.payloadType !== "application/vnd.in-toto+json") {
throw new Error(`parseEnvelopeJsonl: unexpected payloadType ${env.payloadType}`);
}
if (!env.signatures || env.signatures.length === 0) {
throw new Error("parseEnvelopeJsonl: envelope has no signatures");
}
const payloadJson = Buffer.from(env.payload, "base64").toString("utf-8");
const statement = JSON.parse(payloadJson);
return {
statement,
signature: env.signatures[0].sig,
keyid: env.signatures[0].keyid,
payloadB64: env.payload,
};
}
// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
/** SHA-256 hex of an arbitrary UTF-8 string. */
function hashHex(value) {
return createHash("sha256").update(value, "utf-8").digest("hex");
}
//# sourceMappingURL=intoto.js.map
{"version":3,"file":"intoto.js","sourceRoot":"","sources":["../../../src/installer/attestation/intoto.ts"],"names":[],"mappings":"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"}
/**
* Sigstore bundle wrapper — OFFLINE SIGNING ONLY (W2-B3 / T03 / risk R-01).
*
* Sigstore "bundles" (v0.3 / Sigstore Bundle spec) wrap a DSSE envelope
* plus verification material (cert chain or public-key reference) in a
* single JSON document. The canonical online flow involves Fulcio (CA)
* + Rekor (transparency log); we defer BOTH to 1.3.0 per sprint R-01.
*
* For 1.2.0 we emit a minimal bundle that:
* - Includes the DSSE envelope (the in-toto JSONL line, base64-decoded
* back into the structured shape).
* - References a caller-provided public-key fingerprint in the
* `publicKey` slot (in lieu of Fulcio cert chain).
* - Has NO Rekor `tlogEntries` block.
*
* Output bundle shape (subset of sigstore-bundle.proto v0.3):
* {
* "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.3",
* "verificationMaterial": {
* "publicKey": { "hint": "<key fingerprint>" }
* },
* "dsseEnvelope": {
* "payloadType": "application/vnd.in-toto+json",
* "payload": "<base64-payload>",
* "signatures": [{"keyid": "<id>", "sig": "<sig>"}]
* }
* }
*
* Verifier compatibility: any sigstore-js / cosign v2+ that accepts
* `--key <pubkey>` for verification can verify this bundle's DSSE
* envelope. The lack of Rekor entries means verifiers that REQUIRE
* transparency-log inclusion will reject — that is expected behaviour
* for 1.2.0 (we document this in the README polish step).
*/
import { type InTotoStatement } from "./intoto.js";
/** Minimal sigstore bundle v0.3 shape (offline-only subset). */
export interface SigstoreBundle {
mediaType: "application/vnd.dev.sigstore.bundle+json;version=0.3";
verificationMaterial: {
publicKey: {
hint: string;
};
};
dsseEnvelope: {
payloadType: "application/vnd.in-toto+json";
payload: string;
signatures: Array<{
keyid: string;
sig: string;
}>;
};
}
/** Result of wrapping a JSONL envelope into a sigstore bundle. */
export interface SigstoreWrapResult {
bundle: SigstoreBundle;
/** The decoded in-toto statement, exposed for inspection. */
statement: InTotoStatement;
}
/**
* Wrap an in-toto JSONL envelope line into a sigstore bundle v0.3
* offline structure.
*
* @param envelopeLine One JSONL line produced by {@link envelopeToJsonl}.
* @param publicKeyHint A short identifier for the public key (e.g. a hex
* thumbprint or `cosign verify --key`-friendly hint).
* The caller is responsible for binding this hint to
* a real public key out-of-band.
*/
export declare function wrapAsSigstoreBundle(envelopeLine: string, publicKeyHint: string): SigstoreWrapResult;
/**
* Defensive shape check: returns true iff `value` looks like a sigstore
* bundle v0.3 offline structure we emit. Does NOT verify signature.
*/
export declare function isSigstoreBundle(value: unknown): value is SigstoreBundle;
/**
* Serialize a bundle to a JSON string. Convenience helper for callers
* writing the bundle to disk.
*/
export declare function bundleToJson(bundle: SigstoreBundle, pretty?: boolean): string;
//# sourceMappingURL=sigstore-bundle.d.ts.map
{"version":3,"file":"sigstore-bundle.d.ts","sourceRoot":"","sources":["../../../src/installer/attestation/sigstore-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAEvE,gEAAgE;AAChE,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,sDAAsD,CAAC;IAClE,oBAAoB,EAAE;QACpB,SAAS,EAAE;YACT,IAAI,EAAE,MAAM,CAAC;SACd,CAAC;KACH,CAAC;IACF,YAAY,EAAE;QACZ,WAAW,EAAE,8BAA8B,CAAC;QAC5C,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,KAAK,CAAC;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnD,CAAC;CACH;AAED,kEAAkE;AAClE,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,cAAc,CAAC;IACvB,6DAA6D;IAC7D,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,GACpB,kBAAkB,CA8BpB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAexE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,UAAO,GAAG,MAAM,CAE1E"}
/**
* Sigstore bundle wrapper — OFFLINE SIGNING ONLY (W2-B3 / T03 / risk R-01).
*
* Sigstore "bundles" (v0.3 / Sigstore Bundle spec) wrap a DSSE envelope
* plus verification material (cert chain or public-key reference) in a
* single JSON document. The canonical online flow involves Fulcio (CA)
* + Rekor (transparency log); we defer BOTH to 1.3.0 per sprint R-01.
*
* For 1.2.0 we emit a minimal bundle that:
* - Includes the DSSE envelope (the in-toto JSONL line, base64-decoded
* back into the structured shape).
* - References a caller-provided public-key fingerprint in the
* `publicKey` slot (in lieu of Fulcio cert chain).
* - Has NO Rekor `tlogEntries` block.
*
* Output bundle shape (subset of sigstore-bundle.proto v0.3):
* {
* "mediaType": "application/vnd.dev.sigstore.bundle+json;version=0.3",
* "verificationMaterial": {
* "publicKey": { "hint": "<key fingerprint>" }
* },
* "dsseEnvelope": {
* "payloadType": "application/vnd.in-toto+json",
* "payload": "<base64-payload>",
* "signatures": [{"keyid": "<id>", "sig": "<sig>"}]
* }
* }
*
* Verifier compatibility: any sigstore-js / cosign v2+ that accepts
* `--key <pubkey>` for verification can verify this bundle's DSSE
* envelope. The lack of Rekor entries means verifiers that REQUIRE
* transparency-log inclusion will reject — that is expected behaviour
* for 1.2.0 (we document this in the README polish step).
*/
import { parseEnvelopeJsonl } from "./intoto.js";
/**
* Wrap an in-toto JSONL envelope line into a sigstore bundle v0.3
* offline structure.
*
* @param envelopeLine One JSONL line produced by {@link envelopeToJsonl}.
* @param publicKeyHint A short identifier for the public key (e.g. a hex
* thumbprint or `cosign verify --key`-friendly hint).
* The caller is responsible for binding this hint to
* a real public key out-of-band.
*/
export function wrapAsSigstoreBundle(envelopeLine, publicKeyHint) {
if (typeof envelopeLine !== "string" || envelopeLine.length === 0) {
throw new TypeError("wrapAsSigstoreBundle: envelopeLine must be a non-empty string");
}
if (typeof publicKeyHint !== "string" || publicKeyHint.length === 0) {
throw new TypeError("wrapAsSigstoreBundle: publicKeyHint must be a non-empty string");
}
const { statement, signature, keyid, payloadB64 } = parseEnvelopeJsonl(envelopeLine);
const bundle = {
mediaType: "application/vnd.dev.sigstore.bundle+json;version=0.3",
verificationMaterial: {
publicKey: {
hint: publicKeyHint,
},
},
dsseEnvelope: {
payloadType: "application/vnd.in-toto+json",
payload: payloadB64,
signatures: [{ keyid, sig: signature }],
},
};
return { bundle, statement };
}
/**
* Defensive shape check: returns true iff `value` looks like a sigstore
* bundle v0.3 offline structure we emit. Does NOT verify signature.
*/
export function isSigstoreBundle(value) {
if (!value || typeof value !== "object")
return false;
const v = value;
const mediaType = v["mediaType"];
if (!mediaType?.startsWith("application/vnd.dev.sigstore.bundle+json"))
return false;
const vm = v["verificationMaterial"];
if (!vm?.publicKey?.hint)
return false;
const dsse = v["dsseEnvelope"];
if (!dsse?.payload || !Array.isArray(dsse.signatures))
return false;
return true;
}
/**
* Serialize a bundle to a JSON string. Convenience helper for callers
* writing the bundle to disk.
*/
export function bundleToJson(bundle, pretty = true) {
return JSON.stringify(bundle, null, pretty ? 2 : 0);
}
//# sourceMappingURL=sigstore-bundle.js.map
{"version":3,"file":"sigstore-bundle.js","sourceRoot":"","sources":["../../../src/installer/attestation/sigstore-bundle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,EAAE,kBAAkB,EAAwB,MAAM,aAAa,CAAC;AAwBvE;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAClC,YAAoB,EACpB,aAAqB;IAErB,IAAI,OAAO,YAAY,KAAK,QAAQ,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClE,MAAM,IAAI,SAAS,CACjB,+DAA+D,CAChE,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,SAAS,CACjB,gEAAgE,CACjE,CAAC;IACJ,CAAC;IAED,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,GAC/C,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAmB;QAC7B,SAAS,EAAE,sDAAsD;QACjE,oBAAoB,EAAE;YACpB,SAAS,EAAE;gBACT,IAAI,EAAE,aAAa;aACpB;SACF;QACD,YAAY,EAAE;YACZ,WAAW,EAAE,8BAA8B;YAC3C,OAAO,EAAE,UAAU;YACnB,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;SACxC;KACF,CAAC;IAEF,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAC/B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,MAAM,SAAS,GAAG,CAAC,CAAC,WAAW,CAAuB,CAAC;IACvD,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,0CAA0C,CAAC;QACpE,OAAO,KAAK,CAAC;IACf,MAAM,EAAE,GAAG,CAAC,CAAC,sBAAsB,CAEtB,CAAC;IACd,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,CAEhB,CAAC;IACd,IAAI,CAAC,IAAI,EAAE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAsB,EAAE,MAAM,GAAG,IAAI;IAChE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC"}
/**
* SLSA Provenance v1.0 statement builder (W2-B3 / T03).
*
* Thin wrapper around {@link buildInTotoStatement} that exposes a more
* opinionated, sunaiva-flavoured constructor: callers provide the verdict
* + artifact + (optional) extra metadata, and this module fills in
* sensible SLSA fields without leaking the in-toto types to the caller.
*
* This module is the "public" entry point for code that wants to produce
* a SLSA Provenance v1.0 statement — `intoto.ts` is the lower-level
* serializer.
*/
import { type InTotoStatement, type SignedVerdictLike, type SlsaProvenance } from "./intoto.js";
/** Input for {@link buildSlsaProvenance}. */
export interface SlsaProvenanceInput {
verdict: SignedVerdictLike;
artifact: {
/** Subject name. Convention: package or oci ref, e.g. "pkg:npm/%40sunaiva/gate@1.2.0". */
name: string;
/** Lower-case hex SHA-256 of the artifact bytes. */
sha256: string;
};
/**
* Optional extra metadata that gets recorded under
* predicate.runDetails.metadata for auditors.
*/
metadata?: {
/** ISO timestamp; defaults to verdict.signed_at. */
startedOn?: string;
/** ISO timestamp; defaults to verdict.signed_at. */
finishedOn?: string;
/** Override the invocationId. Defaults to verdict.verdict_id. */
invocationId?: string;
};
}
/** Result envelope returned by {@link buildSlsaProvenance}. */
export interface SlsaProvenanceResult {
/** Full in-toto Statement v1 ready for signing. */
statement: InTotoStatement;
/** The SLSA predicate, exposed for inspection. */
predicate: SlsaProvenance;
/** The artifact subject as it ended up in the statement. */
subject: InTotoStatement["subject"][0];
}
/**
* Build a SLSA Provenance v1.0 statement from a Sunaiva signed verdict.
*
* Caller responsibilities:
* - Provide the lower-case hex SHA-256 of the artifact bytes (we do not
* re-hash here — the artifact may live anywhere from local disk to a
* remote registry, and double-hashing risks integrity surprises).
* - Pass the verdict in its canonical SignedVerdict shape (§5.3).
*
* Returns a SlsaProvenanceResult; pass `.statement` to {@link signStatementHmac}
* or any sigstore signer, then wrap with {@link envelopeToJsonl}.
*/
export declare function buildSlsaProvenance(input: SlsaProvenanceInput): SlsaProvenanceResult;
/**
* Verify that a statement conforms to the SLSA Provenance v1.0 shape we
* emit. This is a defensive shape check — it does NOT verify the
* cryptographic signature; use the verifier in `intoto.ts` for that.
*/
export declare function isSlsaProvenanceStatement(value: unknown): value is InTotoStatement;
//# sourceMappingURL=slsa-provenance.d.ts.map
{"version":3,"file":"slsa-provenance.d.ts","sourceRoot":"","sources":["../../../src/installer/attestation/slsa-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,cAAc,EACpB,MAAM,aAAa,CAAC;AAErB,6CAA6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,EAAE;QACR,0FAA0F;QAC1F,IAAI,EAAE,MAAM,CAAC;QACb,oDAAoD;QACpD,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF;;;OAGG;IACH,QAAQ,CAAC,EAAE;QACT,oDAAoD;QACpD,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,oDAAoD;QACpD,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,iEAAiE;QACjE,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAED,+DAA+D;AAC/D,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,SAAS,EAAE,eAAe,CAAC;IAC3B,kDAAkD;IAClD,SAAS,EAAE,cAAc,CAAC;IAC1B,4DAA4D;IAC5D,OAAO,EAAE,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;CACxC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,mBAAmB,GACzB,oBAAoB,CA8CtB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,eAAe,CAU1B"}
/**
* SLSA Provenance v1.0 statement builder (W2-B3 / T03).
*
* Thin wrapper around {@link buildInTotoStatement} that exposes a more
* opinionated, sunaiva-flavoured constructor: callers provide the verdict
* + artifact + (optional) extra metadata, and this module fills in
* sensible SLSA fields without leaking the in-toto types to the caller.
*
* This module is the "public" entry point for code that wants to produce
* a SLSA Provenance v1.0 statement — `intoto.ts` is the lower-level
* serializer.
*/
import { buildInTotoStatement, } from "./intoto.js";
/**
* Build a SLSA Provenance v1.0 statement from a Sunaiva signed verdict.
*
* Caller responsibilities:
* - Provide the lower-case hex SHA-256 of the artifact bytes (we do not
* re-hash here — the artifact may live anywhere from local disk to a
* remote registry, and double-hashing risks integrity surprises).
* - Pass the verdict in its canonical SignedVerdict shape (§5.3).
*
* Returns a SlsaProvenanceResult; pass `.statement` to {@link signStatementHmac}
* or any sigstore signer, then wrap with {@link envelopeToJsonl}.
*/
export function buildSlsaProvenance(input) {
if (!input.verdict) {
throw new TypeError("buildSlsaProvenance: input.verdict is required");
}
if (!input.artifact) {
throw new TypeError("buildSlsaProvenance: input.artifact is required");
}
// Allow metadata override of signed_at — useful when re-attesting an old
// verdict from an audit ledger replay.
let verdictForBuild = input.verdict;
if (input.metadata?.startedOn || input.metadata?.finishedOn) {
verdictForBuild = {
...input.verdict,
signed_at: input.metadata.finishedOn ?? input.verdict.signed_at,
};
}
const stmt = buildInTotoStatement(verdictForBuild, input.artifact);
// Apply optional invocationId override.
if (input.metadata?.invocationId) {
stmt.predicate.runDetails.metadata = {
...stmt.predicate.runDetails.metadata,
invocationId: input.metadata.invocationId,
};
}
if (input.metadata?.startedOn) {
stmt.predicate.runDetails.metadata = {
...stmt.predicate.runDetails.metadata,
startedOn: input.metadata.startedOn,
};
}
if (input.metadata?.finishedOn) {
stmt.predicate.runDetails.metadata = {
...stmt.predicate.runDetails.metadata,
finishedOn: input.metadata.finishedOn,
};
}
return {
statement: stmt,
predicate: stmt.predicate,
subject: stmt.subject[0],
};
}
/**
* Verify that a statement conforms to the SLSA Provenance v1.0 shape we
* emit. This is a defensive shape check — it does NOT verify the
* cryptographic signature; use the verifier in `intoto.ts` for that.
*/
export function isSlsaProvenanceStatement(value) {
if (!value || typeof value !== "object")
return false;
const s = value;
if (s["_type"] !== "https://in-toto.io/Statement/v1")
return false;
if (s["predicateType"] !== "https://slsa.dev/provenance/v1")
return false;
if (!Array.isArray(s["subject"]) || s["subject"].length === 0)
return false;
const pred = s["predicate"];
if (!pred || !pred["buildDefinition"] || !pred["runDetails"])
return false;
return true;
}
//# sourceMappingURL=slsa-provenance.js.map
{"version":3,"file":"slsa-provenance.js","sourceRoot":"","sources":["../../../src/installer/attestation/slsa-provenance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,oBAAoB,GAIrB,MAAM,aAAa,CAAC;AAmCrB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAA0B;IAE1B,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,IAAI,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACpB,MAAM,IAAI,SAAS,CAAC,iDAAiD,CAAC,CAAC;IACzE,CAAC;IAED,yEAAyE;IACzE,uCAAuC;IACvC,IAAI,eAAe,GAAG,KAAK,CAAC,OAAO,CAAC;IACpC,IAAI,KAAK,CAAC,QAAQ,EAAE,SAAS,IAAI,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;QAC5D,eAAe,GAAG;YAChB,GAAG,KAAK,CAAC,OAAO;YAChB,SAAS,EACP,KAAK,CAAC,QAAQ,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS;SACvD,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,oBAAoB,CAAC,eAAe,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEnE,wCAAwC;IACxC,IAAI,KAAK,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;QACjC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,GAAG;YACnC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ;YACrC,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,YAAY;SAC1C,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,GAAG;YACnC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ;YACrC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,SAAS;SACpC,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,GAAG;YACnC,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ;YACrC,UAAU,EAAE,KAAK,CAAC,QAAQ,CAAC,UAAU;SACtC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAI;QACf,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;KACzB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACvC,KAAc;IAEd,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,iCAAiC;QAAE,OAAO,KAAK,CAAC;IACnE,IAAI,CAAC,CAAC,eAAe,CAAC,KAAK,gCAAgC;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAK,CAAC,CAAC,SAAS,CAAe,CAAC,MAAM,KAAK,CAAC;QAC1E,OAAO,KAAK,CAAC;IACf,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,CAAwC,CAAC;IACnE,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;QAAE,OAAO,KAAK,CAAC;IAC3E,OAAO,IAAI,CAAC;AACd,CAAC"}
/**
* Cross-agent detection (T01).
*
* Probes the user's filesystem for evidence that each of seven Tier-A agents
* is installed. Detection is read-only — never writes, never mutates settings.
* Detection failures (permission denied, file not found, malformed JSON) are
* swallowed as `installed: false`. NEVER throws.
*
* Where each agent stores its hook config (canonical paths, May 2026):
*
* claude-code : ~/.claude/settings.json (or project-local .claude/settings.json)
* cursor : ~/.cursor/hooks.json (1.7+; per R4 §4)
* codex : ~/.codex/hooks.toml or CODEX_HOOKS env var
* copilot : ~/.config/github-copilot/hooks.json (preview)
* gemini : ~/.gemini/middleware.json
* cline : VS Code workspace .vscode/settings.json (MCP-only via mcpServers)
* aider : ~/.aider.conf.yml (lint-cmd hijack)
*/
export type AgentName = "claude-code" | "cursor" | "codex" | "copilot" | "gemini" | "cline" | "aider";
export declare const SUPPORTED_AGENTS: readonly AgentName[];
export interface AgentDetection {
agent: AgentName;
config_path: string;
installed: boolean;
/** Optional version string if the agent exposes one. */
version?: string;
}
export interface DetectOptions {
/** Override CWD root for project-local detection. Defaults to process.cwd(). */
cwd?: string;
/** Override HOME for user-global detection. Defaults to os.homedir(). */
home?: string;
}
/**
* Probe the filesystem for evidence of each supported agent. Read-only.
*
* @returns an array with one entry per supported agent, in stable order
* (matches SUPPORTED_AGENTS). `installed=false` means the agent's
* config files are absent — the installer will still produce a
* dry-run shim for it but won't write unless explicitly requested.
*/
export declare function detectAgents(opts?: DetectOptions): Promise<AgentDetection[]>;
/**
* Synchronous convenience helper used by tests and the CLI `--install-detect`
* flag. Identical semantics to detectAgents() but without the async wrapper.
*/
export declare function detectAgentsSync(opts?: DetectOptions): AgentDetection[];
//# sourceMappingURL=detect.d.ts.map
{"version":3,"file":"detect.d.ts","sourceRoot":"","sources":["../../src/installer/detect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,MAAM,MAAM,SAAS,GACjB,aAAa,GACb,QAAQ,GACR,OAAO,GACP,SAAS,GACT,QAAQ,GACR,OAAO,GACP,OAAO,CAAC;AAEZ,eAAO,MAAM,gBAAgB,EAAE,SAAS,SAAS,EAQ/C,CAAC;AAEH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAqHD;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,IAAI,GAAE,aAAkB,GACvB,OAAO,CAAC,cAAc,EAAE,CAAC,CAgD3B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,aAAkB,GAAG,cAAc,EAAE,CA+C3E"}
/**
* Cross-agent detection (T01).
*
* Probes the user's filesystem for evidence that each of seven Tier-A agents
* is installed. Detection is read-only — never writes, never mutates settings.
* Detection failures (permission denied, file not found, malformed JSON) are
* swallowed as `installed: false`. NEVER throws.
*
* Where each agent stores its hook config (canonical paths, May 2026):
*
* claude-code : ~/.claude/settings.json (or project-local .claude/settings.json)
* cursor : ~/.cursor/hooks.json (1.7+; per R4 §4)
* codex : ~/.codex/hooks.toml or CODEX_HOOKS env var
* copilot : ~/.config/github-copilot/hooks.json (preview)
* gemini : ~/.gemini/middleware.json
* cline : VS Code workspace .vscode/settings.json (MCP-only via mcpServers)
* aider : ~/.aider.conf.yml (lint-cmd hijack)
*/
import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
export const SUPPORTED_AGENTS = Object.freeze([
"claude-code",
"cursor",
"codex",
"copilot",
"gemini",
"cline",
"aider",
]);
// ---------------------------------------------------------------------------
// Internal helpers
// ---------------------------------------------------------------------------
function safeReadJson(p) {
try {
const raw = fs.readFileSync(p, "utf-8");
return JSON.parse(raw);
}
catch {
return undefined;
}
}
function safeExists(p) {
try {
return fs.existsSync(p);
}
catch {
return false;
}
}
function probeClaudeCode(home, cwd) {
// Prefer user-global; fall back to project-local. Either presence counts.
const globalPath = path.join(home, ".claude", "settings.json");
const projectPath = path.join(cwd, ".claude", "settings.json");
const config_path = safeExists(globalPath) ? globalPath : globalPath; // installer writes to global
const installed = safeExists(globalPath) || safeExists(projectPath);
let version;
const parsed = safeReadJson(globalPath) || safeReadJson(projectPath);
if (parsed && typeof parsed === "object") {
const v = parsed["version"];
if (typeof v === "string")
version = v;
}
return version === undefined
? { installed, config_path }
: { installed, config_path, version };
}
function probeCursor(home) {
// Cursor 1.7+ uses ~/.cursor/hooks.json (R4 §4).
// Older Cursor versions don't expose hooks, so absence == not installed-for-our-purposes.
const config_path = path.join(home, ".cursor", "hooks.json");
const installed = safeExists(config_path);
return { installed, config_path };
}
function probeCodex(home) {
// OpenAI Codex CLI: ~/.codex/hooks.toml (per official CLI docs, May 2026).
// Some installs use CODEX_HOOKS env var — checked separately by the installer.
const config_path = path.join(home, ".codex", "hooks.toml");
const installed = safeExists(config_path) ||
safeExists(path.join(home, ".codex", "config.toml"));
return { installed, config_path };
}
function probeCopilot(home) {
// GitHub Copilot CLI (preview, May 2026): ~/.config/github-copilot/hooks.json.
const config_path = path.join(home, ".config", "github-copilot", "hooks.json");
const installed = safeExists(config_path) ||
safeExists(path.join(home, ".config", "github-copilot", "config.json"));
return { installed, config_path };
}
function probeGemini(home) {
// Gemini CLI (Google): ~/.gemini/middleware.json or ~/.gemini/settings.json.
const middleware = path.join(home, ".gemini", "middleware.json");
const settings = path.join(home, ".gemini", "settings.json");
const installed = safeExists(middleware) || safeExists(settings);
return { installed, config_path: middleware };
}
function probeCline(cwd) {
// Cline is a VS Code extension — it doesn't have a hook system, only MCP.
// We probe the workspace .vscode/settings.json (where mcpServers lives) and
// user-global ~/.vscode-server/... for VS Code Server installs.
// Project-local detection only — Cline lives per-workspace.
const config_path = path.join(cwd, ".vscode", "settings.json");
let installed = safeExists(config_path);
if (installed) {
// Heuristic: look for "cline" in the settings to confirm extension presence.
const parsed = safeReadJson(config_path);
if (parsed && typeof parsed === "object") {
const s = JSON.stringify(parsed).toLowerCase();
if (!s.includes("cline") && !s.includes("claude-dev")) {
// Settings file exists but no Cline reference — leave installed flag true
// (user may install Cline next). Installer will still write the MCP entry.
}
}
}
return { installed, config_path };
}
function probeAider(home) {
// Aider: ~/.aider.conf.yml (per official docs).
const config_path = path.join(home, ".aider.conf.yml");
const installed = safeExists(config_path);
return { installed, config_path };
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
* Probe the filesystem for evidence of each supported agent. Read-only.
*
* @returns an array with one entry per supported agent, in stable order
* (matches SUPPORTED_AGENTS). `installed=false` means the agent's
* config files are absent — the installer will still produce a
* dry-run shim for it but won't write unless explicitly requested.
*/
export async function detectAgents(opts = {}) {
const home = opts.home ?? os.homedir();
const cwd = opts.cwd ?? process.cwd();
const results = [];
for (const agent of SUPPORTED_AGENTS) {
let probe;
try {
switch (agent) {
case "claude-code":
probe = probeClaudeCode(home, cwd);
break;
case "cursor":
probe = probeCursor(home);
break;
case "codex":
probe = probeCodex(home);
break;
case "copilot":
probe = probeCopilot(home);
break;
case "gemini":
probe = probeGemini(home);
break;
case "cline":
probe = probeCline(cwd);
break;
case "aider":
probe = probeAider(home);
break;
default:
probe = { installed: false, config_path: "" };
}
}
catch {
// Defensive: any unexpected throw → not installed
probe = { installed: false, config_path: "" };
}
const entry = {
agent,
config_path: probe.config_path,
installed: probe.installed,
};
if (probe.version !== undefined)
entry.version = probe.version;
results.push(entry);
}
return results;
}
/**
* Synchronous convenience helper used by tests and the CLI `--install-detect`
* flag. Identical semantics to detectAgents() but without the async wrapper.
*/
export function detectAgentsSync(opts = {}) {
const home = opts.home ?? os.homedir();
const cwd = opts.cwd ?? process.cwd();
const results = [];
for (const agent of SUPPORTED_AGENTS) {
let probe;
try {
switch (agent) {
case "claude-code":
probe = probeClaudeCode(home, cwd);
break;
case "cursor":
probe = probeCursor(home);
break;
case "codex":
probe = probeCodex(home);
break;
case "copilot":
probe = probeCopilot(home);
break;
case "gemini":
probe = probeGemini(home);
break;
case "cline":
probe = probeCline(cwd);
break;
case "aider":
probe = probeAider(home);
break;
default:
probe = { installed: false, config_path: "" };
}
}
catch {
probe = { installed: false, config_path: "" };
}
const entry = {
agent,
config_path: probe.config_path,
installed: probe.installed,
};
if (probe.version !== undefined)
entry.version = probe.version;
results.push(entry);
}
return results;
}
//# sourceMappingURL=detect.js.map
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../src/installer/detect.ts"],"names":[],"mappings":"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"}
/**
* Install orchestrator (T01) — fans `detectAgents()` results out to the
* per-agent shim writers. Honours dry-run (default OFF in CLI, but safe to
* pass true from tests). Supports filtering by agent name.
*
* Design contract:
* - Read-only when dryRun=true (no fs.writeFileSync).
* - Per-agent failures do NOT abort the whole install; they're reported in
* the result array with `bytes: 0` and a `dry_run: false` flag plus an
* `error` field. The CLI can decide whether to exit non-zero.
* - Returned InstallResult array has stable order matching SUPPORTED_AGENTS.
* - NEVER throws on per-agent errors.
*/
import { SUPPORTED_AGENTS, type AgentName } from "./detect.js";
export interface InstallOptions {
/** When true, no files are written. Default false (i.e. real install). */
dryRun?: boolean;
/** Optional whitelist — only these agents are installed. Default: all detected. */
agents?: AgentName[];
/** Override MCP endpoint baked into the shim. Default: stdio. */
mcpEndpoint?: string;
/** Override detection inputs (test-friendly). */
cwd?: string;
home?: string;
/**
* When true, install ONLY for detected agents. When false (default), still
* write shims for un-detected agents (so the user can install the agent
* later and the shim is already in place). The CLI surfaces this via
* `--detected-only`.
*/
detectedOnly?: boolean;
}
export interface InstallResult {
agent: AgentName;
written_to: string;
bytes: number;
dry_run: boolean;
installed: boolean;
/** Population error message if the shim writer failed. */
error?: string;
/** Preview of the shim entry (useful for dry-run + audit). */
preview?: unknown;
}
/**
* Run the cross-agent installer. Returns one InstallResult per agent
* processed in stable order.
*/
export declare function installAll(opts?: InstallOptions): Promise<InstallResult[]>;
/** Pretty-print install results for the CLI. */
export declare function formatResults(results: InstallResult[]): string;
/** Re-export for CLI convenience. */
export { SUPPORTED_AGENTS };
//# sourceMappingURL=install.d.ts.map
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/installer/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAgB,gBAAgB,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AAS7E,MAAM,WAAW,cAAc;IAC7B,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mFAAmF;IACnF,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC;IACrB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,SAAS,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAoBD;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,aAAa,EAAE,CAAC,CAyD1B;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,OAAO,EAAE,aAAa,EAAE,GAAG,MAAM,CAc9D;AAED,qCAAqC;AACrC,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
/**
* Install orchestrator (T01) — fans `detectAgents()` results out to the
* per-agent shim writers. Honours dry-run (default OFF in CLI, but safe to
* pass true from tests). Supports filtering by agent name.
*
* Design contract:
* - Read-only when dryRun=true (no fs.writeFileSync).
* - Per-agent failures do NOT abort the whole install; they're reported in
* the result array with `bytes: 0` and a `dry_run: false` flag plus an
* `error` field. The CLI can decide whether to exit non-zero.
* - Returned InstallResult array has stable order matching SUPPORTED_AGENTS.
* - NEVER throws on per-agent errors.
*/
import { detectAgents, SUPPORTED_AGENTS } from "./detect.js";
import * as claudeCode from "./agents/claude-code.js";
import * as cursor from "./agents/cursor.js";
import * as codex from "./agents/codex.js";
import * as copilot from "./agents/copilot.js";
import * as gemini from "./agents/gemini.js";
import * as cline from "./agents/cline.js";
import * as aider from "./agents/aider.js";
const SHIM_DISPATCH = {
"claude-code": claudeCode,
cursor,
codex,
copilot,
gemini,
cline,
aider,
};
/**
* Run the cross-agent installer. Returns one InstallResult per agent
* processed in stable order.
*/
export async function installAll(opts = {}) {
const dryRun = !!opts.dryRun;
const detections = await detectAgents({
...(opts.cwd !== undefined ? { cwd: opts.cwd } : {}),
...(opts.home !== undefined ? { home: opts.home } : {}),
});
const whitelist = opts.agents ? new Set(opts.agents) : undefined;
const results = [];
for (const det of detections) {
// skip if not in whitelist
if (whitelist && !whitelist.has(det.agent))
continue;
// skip if detected-only and not installed
if (opts.detectedOnly && !det.installed)
continue;
const mod = SHIM_DISPATCH[det.agent];
if (!mod) {
results.push({
agent: det.agent,
written_to: det.config_path,
bytes: 0,
dry_run: dryRun,
installed: det.installed,
error: `no shim writer for ${det.agent}`,
});
continue;
}
try {
const wrote = mod.writeShim(det, {
dryRun,
...(opts.mcpEndpoint !== undefined
? { mcpEndpoint: opts.mcpEndpoint }
: {}),
});
results.push({
agent: det.agent,
written_to: wrote.written_to,
bytes: wrote.bytes,
dry_run: wrote.dry_run,
installed: det.installed,
preview: wrote.preview,
});
}
catch (err) {
results.push({
agent: det.agent,
written_to: det.config_path,
bytes: 0,
dry_run: dryRun,
installed: det.installed,
error: err instanceof Error ? err.message : String(err),
});
}
}
return results;
}
/** Pretty-print install results for the CLI. */
export function formatResults(results) {
const lines = [];
for (const r of results) {
const status = r.error
? `ERROR: ${r.error}`
: r.dry_run
? `DRY-RUN (would write ${r.bytes} bytes)`
: `WROTE ${r.bytes} bytes`;
const installed = r.installed ? "[detected]" : "[not detected]";
lines.push(`${r.agent.padEnd(14)} ${installed.padEnd(16)} ${status} → ${r.written_to}`);
}
return lines.join("\n");
}
/** Re-export for CLI convenience. */
export { SUPPORTED_AGENTS };
//# sourceMappingURL=install.js.map
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/installer/install.ts"],"names":[],"mappings":"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"}
#!/usr/bin/env python3
"""
Sunaiva Gate — Aider `--lint-cmd` hijacked shim.
Aider doesn't have native PreToolUse hooks; the lint-cmd hook fires after
each edit. We hijack it as a post-edit gate: read the changed file path
from sys.argv, send the file content + path through the Sunaiva Gate MCP
tool, exit 0 on allow / non-zero on block.
Cross-platform Python pattern (Rule 11/8 compliance — no os-specific paths,
no hard-coded user dirs):
- Uses sys.executable for python binary lookup.
- Uses subprocess.run with timeout.
- Honors DISABLE_SUNAIVA_GATE env var.
- Fails OPEN at the shim layer (lint-cmd exit-0 = allow).
"""
import json
import os
import re
import subprocess
import sys
def emit_block(reason: str) -> None:
"""Aider treats non-zero exit as a lint failure → surfaces stderr."""
sys.stderr.write(f"[sunaiva-gate] BLOCKED: {reason[:500]}\n")
sys.exit(2)
def emit_allow() -> None:
sys.exit(0)
def main() -> None:
if os.environ.get("DISABLE_SUNAIVA_GATE") == "1":
emit_allow()
return
# Aider passes the edited file path as the last arg.
if len(sys.argv) < 2:
emit_allow() # nothing to gate
return
target_path = sys.argv[-1]
try:
with open(target_path, encoding="utf-8", errors="replace") as f:
content = f.read()[:8_000] # truncate large files
except OSError:
emit_allow()
return
action = json.dumps({
"tool_name": "Edit",
"target_path": target_path,
"content_preview": content,
})
cmd_env = os.environ.get("SUNAIVA_GATE_CMD")
if cmd_env:
cmd = cmd_env.split()
else:
cmd = ["npx", "-y", "-p", "@sunaiva/gate", "sunaiva-gate"]
rpc = json.dumps({
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "validate_action",
"arguments": {
"action": action,
"tool_name": "Edit",
"target_path": target_path,
"hook_phase": "PostToolUse",
},
},
}) + "\n"
try:
proc = subprocess.run(
cmd,
input=rpc,
capture_output=True,
text=True,
timeout=3,
)
except (subprocess.TimeoutExpired, FileNotFoundError):
emit_allow()
return
stdout = proc.stdout or ""
# Match either raw verdict `"allowed":false` or escaped JSON-RPC envelope
# form `\"allowed\":false`.
match = re.search(r'(?:\\"|")allowed(?:\\"|")\s*:\s*(true|false)', stdout)
if not match:
emit_allow()
return
if match.group(1) == "true":
emit_allow()
else:
emit_block("Sunaiva Gate verdict (PostToolUse)")
if __name__ == "__main__":
main()
#!/usr/bin/env bash
# Sunaiva Gate — Claude Code PreToolUse / PostToolUse shim.
#
# Reads a Claude Code hook event JSON from stdin, calls the Sunaiva Gate MCP
# endpoint via npx @sunaiva/gate's stdio bridge, and exits with the correct
# semantics:
# exit 0 → allow (tool proceeds)
# exit 2 → block (Claude Code surfaces stderr to the agent and the user)
#
# This shim deliberately routes the *decision* through the MCP tool result
# rather than relying on raw exit codes from a custom hook — that sidesteps
# anthropic/claude-code issue #24327 (idle-on-exit-2-stderr).
#
# Cross-platform note: this bash script works on macOS/Linux. Windows hosts
# get installed an equivalent .ps1 alternative; the installer chooses by OS.
set -u
GATE_ENDPOINT="${SUNAIVA_GATE_ENDPOINT:-stdio}"
GATE_CMD="${SUNAIVA_GATE_CMD:-npx -y -p @sunaiva/gate sunaiva-gate}"
GATE_TIMEOUT_MS="${SUNAIVA_GATE_TIMEOUT_MS:-3000}"
# Kill-switch — short-circuit to allow when explicitly disabled.
if [ "${DISABLE_SUNAIVA_GATE:-0}" = "1" ]; then
exit 0
fi
# Read the hook event JSON from stdin.
HOOK_PAYLOAD="$(cat || true)"
if [ -z "$HOOK_PAYLOAD" ]; then
# No payload → nothing to gate. Allow rather than spuriously block.
exit 0
fi
# Extract the tool name and a coarse action string. Use python if available,
# else fall back to a grep so the shim still functions without python.
if command -v python3 >/dev/null 2>&1; then
TOOL_NAME=$(printf "%s" "$HOOK_PAYLOAD" | python3 -c 'import sys,json
try:
d=json.loads(sys.stdin.read())
print((d.get("tool_name") or d.get("tool") or "").strip())
except Exception:
print("")' 2>/dev/null)
else
TOOL_NAME=$(printf "%s" "$HOOK_PAYLOAD" | grep -o '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' | head -n1 | sed 's/.*:"\(.*\)"/\1/')
fi
# If extraction fails entirely → allow (fail-OPEN at the shim layer; the gate
# itself fails CLOSED only on its own internal errors).
if [ -z "${TOOL_NAME:-}" ]; then
exit 0
fi
# Call the gate. We send the FULL hook payload as the "action" field so the
# rule engine sees the same surface the agent saw.
VERDICT=$(printf '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"validate_action","arguments":{"action":%s,"tool_name":%s}}}' \
"$(printf '%s' "$HOOK_PAYLOAD" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))' 2>/dev/null || printf '"%s"' "$HOOK_PAYLOAD" )" \
"$(printf '"%s"' "$TOOL_NAME")" \
| timeout "$((GATE_TIMEOUT_MS / 1000))" $GATE_CMD 2>/dev/null \
| tail -n1)
# Parse `allowed` from the verdict text.
ALLOWED=$(printf "%s" "$VERDICT" | python3 -c 'import sys,json,re
try:
raw=sys.stdin.read()
m=re.search(r"\"allowed\"\s*:\s*(true|false)", raw)
print("true" if (m and m.group(1)=="true") else "false")
except Exception:
print("true")' 2>/dev/null || echo "true")
if [ "$ALLOWED" = "true" ]; then
exit 0
fi
# Block — emit the verdict's `message` to stderr so Claude sees it.
printf "%s\n" "$VERDICT" 1>&2
exit 2
{
"_comment": "Sunaiva Gate — Cline MCP-server registration. Cline (VS Code) is MCP-only; it does not use exec-based hooks. This file is appended to Cline's mcpServers config in VS Code settings. The MCP server itself enforces gates via the validate_action tool.",
"mcpServers": {
"sunaiva-gate": {
"command": "npx",
"args": ["-y", "-p", "@sunaiva/gate", "sunaiva-gate"],
"env": {
"DISABLE_SUNAIVA_GATE": "0"
},
"alwaysAllow": [],
"disabled": false
}
}
}
#!/usr/bin/env node
/**
* Sunaiva Gate — OpenAI Codex CLI hook shim.
*
* Codex CLI hooks accept a JSON event on stdin and write a JSON decision on
* stdout: `{ "decision": "allow" | "block", "reason": string }`.
*
* Routes the decision through the Sunaiva Gate MCP tool to keep ALL agents
* consistent. Same fail-OPEN-at-shim, fail-CLOSED-at-gate posture.
*/
const { spawnSync } = require("node:child_process");
function readStdin() {
return new Promise((resolve) => {
let buf = "";
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (chunk) => (buf += chunk));
process.stdin.on("end", () => resolve(buf));
setTimeout(() => resolve(buf), 2500);
});
}
function emit(decision, reason) {
process.stdout.write(
JSON.stringify({
decision,
reason: (reason || "").slice(0, 500),
source: "sunaiva-gate",
}) + "\n"
);
}
async function main() {
if (process.env.DISABLE_SUNAIVA_GATE === "1") return emit("allow", "kill-switch");
let raw = "";
try { raw = await readStdin(); } catch { return emit("allow", "stdin read failed"); }
if (!raw) return emit("allow", "empty payload");
let evt = {};
try { evt = JSON.parse(raw); } catch { return emit("allow", "bad json"); }
const action = JSON.stringify(evt);
const toolName = evt.tool || evt.tool_name || evt.command || "Unknown";
const cmd = process.env.SUNAIVA_GATE_CMD || "npx";
const args =
process.env.SUNAIVA_GATE_CMD ? [] : ["-y", "-p", "@sunaiva/gate", "sunaiva-gate"];
const rpc = JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "validate_action",
arguments: { action, tool_name: toolName },
},
});
let stdout = "";
try {
const r = spawnSync(cmd, args, {
input: rpc + "\n",
encoding: "utf-8",
timeout: 3000,
windowsHide: true,
shell: process.platform === "win32",
});
stdout = r.stdout || "";
} catch (err) {
return emit("allow", "gate invocation failed");
}
const m = stdout.match(/(?:\\"|")allowed(?:\\"|")\s*:\s*(true|false)/);
if (!m) return emit("allow", "no allowed flag");
return emit(m[1] === "true" ? "allow" : "block", "Sunaiva Gate verdict");
}
main().catch(() => emit("allow", "shim exception"));
#!/usr/bin/env node
/**
* Sunaiva Gate — GitHub Copilot CLI hook shim (PREVIEW).
*
* Copilot CLI (May 2026 GA) has a `pre_command` hook that reads a JSON event
* from stdin and decides allow/block via stdout. Until the SDK stabilizes the
* exact event shape, we accept the same generic envelope as the Codex shim.
*
* Marked PREVIEW in the installer README — Copilot's hook API is documented
* but not yet stable, so this shim may need adjustment when Copilot ships
* its first patch.
*/
const { spawnSync } = require("node:child_process");
function readStdin() {
return new Promise((resolve) => {
let buf = "";
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (chunk) => (buf += chunk));
process.stdin.on("end", () => resolve(buf));
setTimeout(() => resolve(buf), 2500);
});
}
function emit(allow, reason) {
process.stdout.write(
JSON.stringify({
allow,
reason: (reason || "").slice(0, 500),
source: "sunaiva-gate",
}) + "\n"
);
// Copilot CLI ALSO uses non-zero exit for block in preview API.
process.exit(allow ? 0 : 2);
}
async function main() {
if (process.env.DISABLE_SUNAIVA_GATE === "1") return emit(true, "kill-switch");
let raw = "";
try { raw = await readStdin(); } catch { return emit(true, "stdin failed"); }
if (!raw) return emit(true, "empty payload");
let evt = {};
try { evt = JSON.parse(raw); } catch { return emit(true, "bad json"); }
const action = JSON.stringify(evt);
const toolName = evt.tool || evt.tool_name || evt.command || "Unknown";
const cmd = process.env.SUNAIVA_GATE_CMD || "npx";
const args =
process.env.SUNAIVA_GATE_CMD ? [] : ["-y", "-p", "@sunaiva/gate", "sunaiva-gate"];
const rpc = JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "validate_action",
arguments: { action, tool_name: toolName },
},
});
let stdout = "";
try {
const r = spawnSync(cmd, args, {
input: rpc + "\n",
encoding: "utf-8",
timeout: 3000,
windowsHide: true,
shell: process.platform === "win32",
});
stdout = r.stdout || "";
} catch (err) {
return emit(true, "gate invocation failed");
}
const m = stdout.match(/(?:\\"|")allowed(?:\\"|")\s*:\s*(true|false)/);
if (!m) return emit(true, "no allowed flag");
return emit(m[1] === "true", "Sunaiva Gate verdict");
}
main().catch(() => emit(true, "shim exception"));
#!/usr/bin/env node
/**
* Sunaiva Gate — Cursor 1.7+ hook shim.
*
* Cursor uses `permissionDecision: "deny" | "allow" | "ask"` returned as JSON
* to stdout. Reads the Cursor event JSON from stdin, calls the gate, returns
* the appropriate decision.
*
* Per R1 §3 + R4 §4.2, Cursor's permission system is more expressive than
* Claude Code's binary block/allow, so we map:
* gate allow → permissionDecision: "allow"
* gate block → permissionDecision: "deny"
* gate warn → permissionDecision: "ask"
*/
const { spawnSync } = require("node:child_process");
function readStdin() {
return new Promise((resolve) => {
let buf = "";
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (chunk) => (buf += chunk));
process.stdin.on("end", () => resolve(buf));
// Safety timer — Cursor sends the event quickly.
setTimeout(() => resolve(buf), 2500);
});
}
function emit(decision, reason) {
process.stdout.write(
JSON.stringify({
permissionDecision: decision,
reason: (reason || "").slice(0, 500),
source: "sunaiva-gate",
}) + "\n"
);
}
async function main() {
if (process.env.DISABLE_SUNAIVA_GATE === "1") {
return emit("allow", "DISABLE_SUNAIVA_GATE=1");
}
let raw = "";
try {
raw = await readStdin();
} catch {
return emit("allow", "shim could not read stdin");
}
if (!raw) return emit("allow", "empty payload");
let evt = {};
try {
evt = JSON.parse(raw);
} catch {
return emit("allow", "shim could not parse cursor event");
}
const action = JSON.stringify(evt);
const toolName = evt.tool_name || evt.tool || "Unknown";
const cmd = process.env.SUNAIVA_GATE_CMD || "npx";
const args =
process.env.SUNAIVA_GATE_CMD ? [] : ["-y", "-p", "@sunaiva/gate", "sunaiva-gate"];
const rpc = JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "validate_action",
arguments: { action, tool_name: toolName },
},
});
let stdout = "";
try {
const r = spawnSync(cmd, args, {
input: rpc + "\n",
encoding: "utf-8",
timeout: 3000,
windowsHide: true,
// Use shell on Windows so paths like C:\path\foo.cmd are honored.
shell: process.platform === "win32",
});
stdout = r.stdout || "";
} catch (err) {
return emit("allow", "gate invocation failed: " + (err && err.message));
}
// The gate's verdict may arrive either as raw verdict JSON OR wrapped in an
// MCP JSON-RPC envelope where the inner JSON is escaped. Match either form:
// "allowed":false (unescaped)
// \"allowed\":false (escaped inside JSON string)
const m = stdout.match(/(?:\\"|")allowed(?:\\"|")\s*:\s*(true|false)/);
if (!m) return emit("allow", "gate response missing allowed flag");
const allowed = m[1] === "true";
// Detect warn-only (next match would block) — pass to user as 'ask'.
const warnHit = /(?:\\"|")warnings(?:\\"|")\s*:\s*\[\s*\{/.test(stdout) && allowed;
if (!allowed) return emit("deny", "Sunaiva Gate blocked this tool call");
if (warnHit) return emit("ask", "Sunaiva Gate warned — confirm before proceeding");
return emit("allow", "ok");
}
main().catch(() => emit("allow", "shim exception"));
#!/usr/bin/env node
/**
* Sunaiva Gate — Gemini CLI middleware shim.
*
* Gemini CLI's tool middleware pattern: hook script receives JSON tool call
* on stdin, returns `{ "decision": "allow" | "deny", "feedback": string }`.
* Same gate-routing pattern as the other shims.
*/
const { spawnSync } = require("node:child_process");
function readStdin() {
return new Promise((resolve) => {
let buf = "";
process.stdin.setEncoding("utf-8");
process.stdin.on("data", (chunk) => (buf += chunk));
process.stdin.on("end", () => resolve(buf));
setTimeout(() => resolve(buf), 2500);
});
}
function emit(decision, feedback) {
process.stdout.write(
JSON.stringify({
decision,
feedback: (feedback || "").slice(0, 500),
source: "sunaiva-gate",
}) + "\n"
);
}
async function main() {
if (process.env.DISABLE_SUNAIVA_GATE === "1") return emit("allow", "kill-switch");
let raw = "";
try { raw = await readStdin(); } catch { return emit("allow", "stdin failed"); }
if (!raw) return emit("allow", "empty payload");
let evt = {};
try { evt = JSON.parse(raw); } catch { return emit("allow", "bad json"); }
const action = JSON.stringify(evt);
const toolName = evt.name || evt.tool_name || evt.tool || "Unknown";
const cmd = process.env.SUNAIVA_GATE_CMD || "npx";
const args =
process.env.SUNAIVA_GATE_CMD ? [] : ["-y", "-p", "@sunaiva/gate", "sunaiva-gate"];
const rpc = JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: {
name: "validate_action",
arguments: { action, tool_name: toolName },
},
});
let stdout = "";
try {
const r = spawnSync(cmd, args, {
input: rpc + "\n",
encoding: "utf-8",
timeout: 3000,
windowsHide: true,
shell: process.platform === "win32",
});
stdout = r.stdout || "";
} catch (err) {
return emit("allow", "gate invocation failed");
}
const m = stdout.match(/(?:\\"|")allowed(?:\\"|")\s*:\s*(true|false)/);
if (!m) return emit("allow", "no allowed flag");
return emit(m[1] === "true" ? "allow" : "deny", "Sunaiva Gate verdict");
}
main().catch(() => emit("allow", "shim exception"));
/**
* T13 — `~/.sunaiva/outbound-allowlist.json` parser.
*
* Inverse-allowlist: the outbound gate is default-DENY when
* `SUNAIVA_PARANOIA=outbound` is set. A user opts INTO specific outbound
* actions by writing an entry here. Default-allow inverted: only what
* the user has expressly approved is permitted.
*
* File shape:
* {
* "version": 1,
* "patterns": [
* "git push origin v[0-9]+",
* "npm publish --dry-run",
* "curl -s https://api.openrouter.ai/*"
* ]
* }
*
* **`git subtree push` patterns** are accepted ONLY when scoped to a
* specific branch (i.e. the allowlist string contains a token AFTER
* `git subtree push`). A blanket `git subtree push` entry is REFUSED —
* this is the failure_051 lesson hard-wired into the loader.
*
* Fail-OPEN: a missing or malformed allowlist file returns an empty
* patterns array. The outbound gate then denies everything in paranoia
* mode — which is the SAFE default.
*/
export interface AllowlistLoadResult {
patterns: string[];
/** Patterns that were rejected at load time (blanket subtree push). */
rejected_patterns: string[];
/** Did the file exist? */
file_existed: boolean;
/** Did the file parse as JSON? */
parsed_ok: boolean;
}
export declare function resolveAllowlistPath(home?: string): string;
/**
* Parse the allowlist payload into a (safe / rejected) split.
*
* Stand-alone, dependency-free for unit testing.
*/
export declare function parseAllowlist(raw: unknown): {
patterns: string[];
rejected_patterns: string[];
};
/**
* Does the action match any pattern in the allowlist?
*
* Each pattern is interpreted as a literal substring OR a glob-light:
* - `*` matches any run of non-newline chars
* - `?` matches a single non-newline char
*
* Returns the FIRST matching pattern string or `null`. Comparison is
* case-INSENSITIVE — same convention as patterns.ts.
*/
export declare function matchAllowlist(action: string, patterns: readonly string[]): string | null;
/**
* Read and validate the user's allowlist file.
*
* Fail-OPEN: returns empty patterns on missing/malformed. NEVER throws.
* The outbound gate then denies everything in paranoia mode (safe).
*/
export declare function loadAllowlist(home?: string): AllowlistLoadResult;
//# sourceMappingURL=allowlist.d.ts.map
{"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../src/paranoia/allowlist.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,uEAAuE;IACvE,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,0BAA0B;IAC1B,YAAY,EAAE,OAAO,CAAC;IACtB,kCAAkC;IAClC,SAAS,EAAE,OAAO,CAAC;CACpB;AAMD,wBAAgB,oBAAoB,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAErE;AAmCD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG;IAC5C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,iBAAiB,EAAE,MAAM,EAAE,CAAC;CAC7B,CAqBA;AAMD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,SAAS,MAAM,EAAE,GAC1B,MAAM,GAAG,IAAI,CAMf;AAgBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAkB,GAAG,mBAAmB,CA4C3E"}
/**
* T13 — `~/.sunaiva/outbound-allowlist.json` parser.
*
* Inverse-allowlist: the outbound gate is default-DENY when
* `SUNAIVA_PARANOIA=outbound` is set. A user opts INTO specific outbound
* actions by writing an entry here. Default-allow inverted: only what
* the user has expressly approved is permitted.
*
* File shape:
* {
* "version": 1,
* "patterns": [
* "git push origin v[0-9]+",
* "npm publish --dry-run",
* "curl -s https://api.openrouter.ai/*"
* ]
* }
*
* **`git subtree push` patterns** are accepted ONLY when scoped to a
* specific branch (i.e. the allowlist string contains a token AFTER
* `git subtree push`). A blanket `git subtree push` entry is REFUSED —
* this is the failure_051 lesson hard-wired into the loader.
*
* Fail-OPEN: a missing or malformed allowlist file returns an empty
* patterns array. The outbound gate then denies everything in paranoia
* mode — which is the SAFE default.
*/
import { readFileSync, existsSync } from "node:fs";
import { join } from "node:path";
import { homedir } from "node:os";
// ---------------------------------------------------------------------------
// Path resolution
// ---------------------------------------------------------------------------
export function resolveAllowlistPath(home = homedir()) {
return join(home, ".sunaiva", "outbound-allowlist.json");
}
// ---------------------------------------------------------------------------
// failure_051 explicit refusal
// ---------------------------------------------------------------------------
/**
* Pattern that catches a blanket `git subtree push` entry (no further
* scoping). A scoped entry like `git subtree push origin protected-branch`
* is allowed; a bare `git subtree push` or `git subtree push origin` is not.
*
* The justification — see failure_051 — is that the bare form opens the
* entire `git subtree push` family of operations and that is what allowed
* a sub-agent to autonomously publish to a public repo in the first place.
*/
function isBlanketSubtreePush(pattern) {
const s = pattern.trim().toLowerCase().replace(/\s+/g, " ");
// Allowed: more than "git subtree push <remote> <ref>" — must have ≥ 4 tokens.
// Refused: "git subtree push" or "git subtree push origin"
if (!s.startsWith("git subtree push"))
return false;
const tokens = s.split(" ").filter(Boolean);
// ["git", "subtree", "push"] = 3 tokens → blanket
// ["git", "subtree", "push", "origin"] = 4 tokens → still blanket
// ["git", "subtree", "push", "origin", "<ref>"] = 5 tokens → scoped, OK
return tokens.length < 5;
}
// ---------------------------------------------------------------------------
// Parser
// ---------------------------------------------------------------------------
function isPlainObject(v) {
return typeof v === "object" && v !== null && !Array.isArray(v);
}
/**
* Parse the allowlist payload into a (safe / rejected) split.
*
* Stand-alone, dependency-free for unit testing.
*/
export function parseAllowlist(raw) {
const patterns = [];
const rejected = [];
if (!isPlainObject(raw))
return { patterns, rejected_patterns: rejected };
const arr = raw.patterns;
if (!Array.isArray(arr))
return { patterns, rejected_patterns: rejected };
for (const p of arr) {
if (typeof p !== "string")
continue;
const trimmed = p.trim();
if (!trimmed)
continue;
if (isBlanketSubtreePush(trimmed)) {
rejected.push(trimmed);
continue;
}
patterns.push(trimmed);
}
return { patterns, rejected_patterns: rejected };
}
// ---------------------------------------------------------------------------
// Matcher
// ---------------------------------------------------------------------------
/**
* Does the action match any pattern in the allowlist?
*
* Each pattern is interpreted as a literal substring OR a glob-light:
* - `*` matches any run of non-newline chars
* - `?` matches a single non-newline char
*
* Returns the FIRST matching pattern string or `null`. Comparison is
* case-INSENSITIVE — same convention as patterns.ts.
*/
export function matchAllowlist(action, patterns) {
const lower = action.toLowerCase();
for (const p of patterns) {
if (compileGlob(p).test(lower))
return p;
}
return null;
}
function compileGlob(pattern) {
// Escape regex metas EXCEPT `*` and `?`, then convert globs.
const escaped = pattern
.toLowerCase()
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
.replace(/\*/g, ".*")
.replace(/\?/g, ".");
return new RegExp(escaped);
}
// ---------------------------------------------------------------------------
// Loader
// ---------------------------------------------------------------------------
/**
* Read and validate the user's allowlist file.
*
* Fail-OPEN: returns empty patterns on missing/malformed. NEVER throws.
* The outbound gate then denies everything in paranoia mode (safe).
*/
export function loadAllowlist(home = homedir()) {
const path = resolveAllowlistPath(home);
const fileExisted = existsSync(path);
if (!fileExisted) {
return {
patterns: [],
rejected_patterns: [],
file_existed: false,
parsed_ok: false,
};
}
let raw = null;
let parsedOk = false;
try {
raw = JSON.parse(readFileSync(path, "utf-8"));
parsedOk = true;
}
catch {
// Fail-OPEN with empty patterns.
return {
patterns: [],
rejected_patterns: [],
file_existed: true,
parsed_ok: false,
};
}
const { patterns, rejected_patterns } = parseAllowlist(raw);
if (rejected_patterns.length > 0) {
process.stderr.write(`[sunaiva-gate] WARN: outbound-allowlist.json contained ${rejected_patterns.length} ` +
`blanket 'git subtree push' pattern(s) — REJECTED (failure_051 cure). ` +
`Scope to a specific remote + branch.\n`);
}
return {
patterns,
rejected_patterns,
file_existed: true,
parsed_ok: parsedOk,
};
}
//# sourceMappingURL=allowlist.js.map
{"version":3,"file":"allowlist.js","sourceRoot":"","sources":["../../src/paranoia/allowlist.ts"],"names":[],"mappings":"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"}
/**
* T13 — Outbound action gate (paranoia mode).
*
* Cures the failure_051 class of incidents (sub-agent autonomously
* creates public repos via `git subtree push`).
*
* Modes:
* - `off` — default, no extra outbound gating. Engine behaves
* exactly as 1.1.0.
* - `outbound` — DEFAULT-DENY for any action matching
* `patterns.ts#OUTBOUND_PATTERNS`. The user opts in
* to specific actions via
* `~/.sunaiva/outbound-allowlist.json`.
* - `all` — DEFAULT-DENY for the entire engine pass; constitutional
* rules still fire. Reserved for future "lock the
* whole agent" use cases. In 1.2.0 this is treated
* identically to `outbound` (the rule-engine wrap
* in 1.2.0 only consults outbound patterns).
*
* Decision protocol:
* 1. mode === "off" → allow (gate does nothing)
* 2. no outbound pattern matches → allow
* 3. outbound pattern matches + allowlist match → allow (with reason)
* 4. outbound pattern matches + no allowlist → DENY
*
* The decision is structurally separate from rule violations: this gate
* fires BEFORE rule evaluation. A constitutional rule that ALSO catches
* the action is still recorded — but the user only sees one block per
* action and the outbound gate is the more specific signal.
*/
import { type AllowlistLoadResult } from "./allowlist.js";
export type ParanoiaMode = "off" | "outbound" | "all";
export interface OutboundCheckResult {
decision: "allow" | "deny";
reason: string;
matched_pattern?: string;
allowlist_match?: string;
/** All patterns that matched (informational; primary is matched_pattern). */
all_matches?: string[];
}
export interface OutboundCheckOptions {
mode: ParanoiaMode;
/** Optional: pre-loaded allowlist. If absent, the gate loads on call. */
allowlist?: AllowlistLoadResult;
/** Optional: override $HOME for tests. */
home?: string;
}
/**
* Read paranoia mode from environment.
*
* SUNAIVA_PARANOIA=off | outbound | all
*
* Unset / unrecognised → "off" (safe default; this matches 1.1.0
* behaviour for non-paranoia users).
*/
export declare function readParanoiaMode(env?: NodeJS.ProcessEnv): ParanoiaMode;
/**
* Core check. Sync because pattern matching + allowlist matching are
* both in-memory operations. The optional allowlist load is also sync.
*
* NEVER throws. On any internal error, returns
* `decision: "deny", reason: "fail_closed_internal_error"` per the
* fail-CLOSED contract in §9.2 of SPRINT_1_2_0_PLAN.md.
*/
export declare function checkOutbound(action: string, opts: OutboundCheckOptions): OutboundCheckResult;
/**
* Convenience wrapper that reads the mode from `process.env`. Useful
* for engine callers that don't want to plumb mode explicitly.
*/
export declare function checkOutboundFromEnv(action: string, env?: NodeJS.ProcessEnv): OutboundCheckResult;
//# sourceMappingURL=outbound-gate.d.ts.map
{"version":3,"file":"outbound-gate.d.ts","sourceRoot":"","sources":["../../src/paranoia/outbound-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAGH,OAAO,EAAE,KAAK,mBAAmB,EAAiC,MAAM,gBAAgB,CAAC;AAEzF,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,UAAU,GAAG,KAAK,CAAC;AAEtD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,YAAY,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,YAAY,CAKd;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,oBAAoB,GACzB,mBAAmB,CA4CrB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,mBAAmB,CAErB"}
/**
* T13 — Outbound action gate (paranoia mode).
*
* Cures the failure_051 class of incidents (sub-agent autonomously
* creates public repos via `git subtree push`).
*
* Modes:
* - `off` — default, no extra outbound gating. Engine behaves
* exactly as 1.1.0.
* - `outbound` — DEFAULT-DENY for any action matching
* `patterns.ts#OUTBOUND_PATTERNS`. The user opts in
* to specific actions via
* `~/.sunaiva/outbound-allowlist.json`.
* - `all` — DEFAULT-DENY for the entire engine pass; constitutional
* rules still fire. Reserved for future "lock the
* whole agent" use cases. In 1.2.0 this is treated
* identically to `outbound` (the rule-engine wrap
* in 1.2.0 only consults outbound patterns).
*
* Decision protocol:
* 1. mode === "off" → allow (gate does nothing)
* 2. no outbound pattern matches → allow
* 3. outbound pattern matches + allowlist match → allow (with reason)
* 4. outbound pattern matches + no allowlist → DENY
*
* The decision is structurally separate from rule violations: this gate
* fires BEFORE rule evaluation. A constitutional rule that ALSO catches
* the action is still recorded — but the user only sees one block per
* action and the outbound gate is the more specific signal.
*/
import { firstMatch, matchOutbound } from "./patterns.js";
import { loadAllowlist, matchAllowlist } from "./allowlist.js";
/**
* Read paranoia mode from environment.
*
* SUNAIVA_PARANOIA=off | outbound | all
*
* Unset / unrecognised → "off" (safe default; this matches 1.1.0
* behaviour for non-paranoia users).
*/
export function readParanoiaMode(env = process.env) {
const v = (env["SUNAIVA_PARANOIA"] ?? "").trim().toLowerCase();
if (v === "outbound")
return "outbound";
if (v === "all")
return "all";
return "off";
}
/**
* Core check. Sync because pattern matching + allowlist matching are
* both in-memory operations. The optional allowlist load is also sync.
*
* NEVER throws. On any internal error, returns
* `decision: "deny", reason: "fail_closed_internal_error"` per the
* fail-CLOSED contract in §9.2 of SPRINT_1_2_0_PLAN.md.
*/
export function checkOutbound(action, opts) {
try {
if (opts.mode === "off") {
return { decision: "allow", reason: "paranoia_mode_off" };
}
// Both "outbound" and "all" use the outbound pattern table in 1.2.0.
const matched = matchOutbound(action);
if (matched.length === 0) {
return { decision: "allow", reason: "no_outbound_pattern_match" };
}
const primary = firstMatch(action) ?? matched[0];
const all_matches = matched.map((m) => m.id);
// Load allowlist lazily.
const allowlist = opts.allowlist ?? loadAllowlist(opts.home);
const allowMatch = matchAllowlist(action, allowlist.patterns);
if (allowMatch !== null) {
return {
decision: "allow",
reason: "allowlist_match",
matched_pattern: primary.id,
allowlist_match: allowMatch,
all_matches,
};
}
return {
decision: "deny",
reason: `outbound_pattern_matched_no_allowlist (${primary.description})`,
matched_pattern: primary.id,
all_matches,
};
}
catch (err) {
// Fail-CLOSED — never let a bug in the gate let an outbound through.
return {
decision: "deny",
reason: `fail_closed_internal_error: ${err instanceof Error ? err.message : String(err)}`,
};
}
}
/**
* Convenience wrapper that reads the mode from `process.env`. Useful
* for engine callers that don't want to plumb mode explicitly.
*/
export function checkOutboundFromEnv(action, env = process.env) {
return checkOutbound(action, { mode: readParanoiaMode(env) });
}
//# sourceMappingURL=outbound-gate.js.map
{"version":3,"file":"outbound-gate.js","sourceRoot":"","sources":["../../src/paranoia/outbound-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC1D,OAAO,EAA4B,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAqBzF;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC/D,IAAI,CAAC,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IACxC,IAAI,CAAC,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,IAA0B;IAE1B,IAAI,CAAC;QACH,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACxB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;QAC5D,CAAC;QAED,qEAAqE;QACrE,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC;QACpE,CAAC;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;QACjD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAE7C,yBAAyB;QACzB,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;QAE9D,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,OAAO;gBACL,QAAQ,EAAE,OAAO;gBACjB,MAAM,EAAE,iBAAiB;gBACzB,eAAe,EAAE,OAAO,CAAC,EAAE;gBAC3B,eAAe,EAAE,UAAU;gBAC3B,WAAW;aACZ,CAAC;QACJ,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,0CAA0C,OAAO,CAAC,WAAW,GAAG;YACxE,eAAe,EAAE,OAAO,CAAC,EAAE;YAC3B,WAAW;SACZ,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,qEAAqE;QACrE,OAAO;YACL,QAAQ,EAAE,MAAM;YAChB,MAAM,EAAE,+BACN,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CACjD,EAAE;SACH,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAAc,EACd,MAAyB,OAAO,CAAC,GAAG;IAEpC,OAAO,aAAa,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC"}
/**
* T13 — Outbound action patterns (paranoia mode).
*
* `SUNAIVA_PARANOIA=outbound` flips the gate from default-allow to
* default-DENY for any action matching the outbound patterns below.
* Each match is reported with a `matched_pattern` label so the audit
* log + allowlist mechanism can reason about exactly what was caught.
*
* **failure_051 cure** — the 2026-05-14 incident in which a sub-agent
* autonomously created public GitHub repos was rooted in the fact that
* `git subtree push` was NOT in PUBLISH_PATTERNS. T13 lists it explicitly
* and gives it its own first-class pattern (`git_subtree_push`) so
* follow-up audits can search for that exact label.
*
* Pattern matching is INTENTIONALLY conservative — we'd rather have a
* false-positive that the user un-blocks via the allowlist than a
* false-negative that lets a publish slip through. See R3 §2 (failure
* taxonomy) for the cost asymmetry.
*
* Implementation note: every pattern is a function `(action: string) =>
* boolean` rather than a regex literal so we can do shell-aware splits
* (e.g. tolerate ` git subtree push ` with weird whitespace) without
* inflating the pattern table.
*/
export type OutboundPatternId = "curl" | "wget" | "gh_api" | "gh_repo_create" | "git_push" | "git_subtree_push" | "git_subtree_split_push" | "npm_publish" | "pnpm_publish" | "yarn_publish" | "cargo_publish" | "pip_upload" | "twine_upload" | "docker_push" | "http_post" | "fetch_post";
export interface OutboundPattern {
id: OutboundPatternId;
/** Human-readable summary for audit logs / explain output. */
description: string;
/** Action-string predicate. Receives a normalised lower-cased copy. */
matches: (lower: string) => boolean;
}
/**
* The full set of outbound patterns. ORDER MATTERS: the more-specific
* `git_subtree_push` is listed BEFORE the generic `git_push` so the
* audit label is the more useful one. The matcher returns ALL matches
* via `matchOutbound`, but `firstMatch` (used by the gate) returns the
* first hit per this ordering.
*/
export declare const OUTBOUND_PATTERNS: readonly OutboundPattern[];
/**
* Return all patterns that match the given action. Empty array = no match.
*
* Action is whitespace-squashed and case-folded before testing so
* multi-line shells / case-variant commands don't slip through.
*/
export declare function matchOutbound(action: string): OutboundPattern[];
/**
* Return the FIRST matching pattern (per the table's declared order)
* or `null`. Used by the outbound gate to produce a single
* `matched_pattern` label for the audit log.
*/
export declare function firstMatch(action: string): OutboundPattern | null;
//# sourceMappingURL=patterns.d.ts.map
{"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/paranoia/patterns.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,MAAM,MAAM,iBAAiB,GACzB,MAAM,GACN,MAAM,GACN,QAAQ,GACR,gBAAgB,GAChB,UAAU,GACV,kBAAkB,GAClB,wBAAwB,GACxB,aAAa,GACb,cAAc,GACd,cAAc,GACd,eAAe,GACf,YAAY,GACZ,cAAc,GACd,aAAa,GACb,WAAW,GACX,YAAY,CAAC;AAEjB,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,iBAAiB,CAAC;IACtB,8DAA8D;IAC9D,WAAW,EAAE,MAAM,CAAC;IACpB,uEAAuE;IACvE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;CACrC;AAeD;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,eAAe,EAuGtD,CAAC;AAMH;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,EAAE,CAO/D;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAMjE"}
/**
* T13 — Outbound action patterns (paranoia mode).
*
* `SUNAIVA_PARANOIA=outbound` flips the gate from default-allow to
* default-DENY for any action matching the outbound patterns below.
* Each match is reported with a `matched_pattern` label so the audit
* log + allowlist mechanism can reason about exactly what was caught.
*
* **failure_051 cure** — the 2026-05-14 incident in which a sub-agent
* autonomously created public GitHub repos was rooted in the fact that
* `git subtree push` was NOT in PUBLISH_PATTERNS. T13 lists it explicitly
* and gives it its own first-class pattern (`git_subtree_push`) so
* follow-up audits can search for that exact label.
*
* Pattern matching is INTENTIONALLY conservative — we'd rather have a
* false-positive that the user un-blocks via the allowlist than a
* false-negative that lets a publish slip through. See R3 §2 (failure
* taxonomy) for the cost asymmetry.
*
* Implementation note: every pattern is a function `(action: string) =>
* boolean` rather than a regex literal so we can do shell-aware splits
* (e.g. tolerate ` git subtree push ` with weird whitespace) without
* inflating the pattern table.
*/
// ---------------------------------------------------------------------------
// Pattern table
// ---------------------------------------------------------------------------
/**
* Collapse runs of whitespace to single spaces so multi-token patterns
* like `git subtree push` match regardless of indentation / line breaks
* inserted by a shell wrapper.
*/
function squashWs(s) {
return s.replace(/\s+/g, " ").trim();
}
/**
* The full set of outbound patterns. ORDER MATTERS: the more-specific
* `git_subtree_push` is listed BEFORE the generic `git_push` so the
* audit label is the more useful one. The matcher returns ALL matches
* via `matchOutbound`, but `firstMatch` (used by the gate) returns the
* first hit per this ordering.
*/
export const OUTBOUND_PATTERNS = Object.freeze([
// ---- HTTP transfer tools ----
{
id: "curl",
description: "curl HTTP request (outbound network)",
matches: (s) => /\bcurl\b/.test(s),
},
{
id: "wget",
description: "wget HTTP request (outbound network)",
matches: (s) => /\bwget\b/.test(s),
},
// ---- GitHub-specific ----
// `gh repo create` is the CREATE half of the failure_051 leak — the
// 2026-05-14 incident "created public GitHub repos ... then ran git
// subtree push". The push half was covered (git_subtree_push); the
// create half was NOT. Under paranoia=outbound, creating ANY remote
// repo from an agent is publish-class and must be gated — `--public`
// makes it worse but even a private-repo create is an outbound action
// (it provisions a remote endpoint a later push can leak into).
// Listed BEFORE gh_api so the audit label is the more specific one.
{
id: "gh_repo_create",
description: "gh repo create (provisions a remote GitHub repo — failure_051 CREATE-half cure)",
matches: (s) => /\bgh\s+repo\s+create\b/.test(s),
},
{
id: "gh_api",
description: "gh CLI api call (GitHub API outbound)",
matches: (s) => /\bgh\s+api\b/.test(s),
},
// ---- Git push variants (failure_051 cure) ----
// Specific BEFORE generic — see header comment.
{
id: "git_subtree_split_push",
description: "git subtree split + push pipeline (failure_051 cure)",
matches: (s) => /\bgit\s+subtree\s+split\b/.test(s) && /\bpush\b/.test(s),
},
{
id: "git_subtree_push",
description: "git subtree push (failure_051 explicit cure)",
matches: (s) => /\bgit\s+subtree\s+push\b/.test(s),
},
{
id: "git_push",
description: "git push (push to remote — outbound)",
matches: (s) => /\bgit\s+push\b/.test(s),
},
// ---- Package managers ----
{
id: "npm_publish",
description: "npm publish (registry upload)",
matches: (s) => /\bnpm\s+publish\b/.test(s),
},
{
id: "pnpm_publish",
description: "pnpm publish (registry upload)",
matches: (s) => /\bpnpm\s+publish\b/.test(s),
},
{
id: "yarn_publish",
description: "yarn publish (registry upload)",
matches: (s) => /\byarn\s+publish\b/.test(s),
},
{
id: "cargo_publish",
description: "cargo publish (crates.io upload)",
matches: (s) => /\bcargo\s+publish\b/.test(s),
},
{
id: "pip_upload",
description: "pip upload (legacy PyPI upload)",
matches: (s) => /\bpip\s+upload\b/.test(s),
},
{
id: "twine_upload",
description: "twine upload (PyPI upload)",
matches: (s) => /\btwine\s+upload\b/.test(s),
},
{
id: "docker_push",
description: "docker push (container registry upload)",
matches: (s) => /\bdocker\s+push\b/.test(s),
},
// ---- Programmatic HTTP ----
{
id: "http_post",
description: "HTTP POST via requests/axios/fetch (programmatic outbound)",
matches: (s) => /\brequests\.post\b/.test(s) ||
/\baxios\.post\b/.test(s) ||
/\baxios\(\s*\{/.test(s),
},
{
id: "fetch_post",
description: "fetch() POST/PUT/DELETE/PATCH (programmatic outbound)",
matches: (s) => /\bfetch\s*\(/.test(s) &&
/(method\s*:\s*['"`](post|put|delete|patch)['"`])/i.test(s),
},
]);
// ---------------------------------------------------------------------------
// Matchers
// ---------------------------------------------------------------------------
/**
* Return all patterns that match the given action. Empty array = no match.
*
* Action is whitespace-squashed and case-folded before testing so
* multi-line shells / case-variant commands don't slip through.
*/
export function matchOutbound(action) {
const lower = squashWs(action).toLowerCase();
const out = [];
for (const p of OUTBOUND_PATTERNS) {
if (p.matches(lower))
out.push(p);
}
return out;
}
/**
* Return the FIRST matching pattern (per the table's declared order)
* or `null`. Used by the outbound gate to produce a single
* `matched_pattern` label for the audit log.
*/
export function firstMatch(action) {
const lower = squashWs(action).toLowerCase();
for (const p of OUTBOUND_PATTERNS) {
if (p.matches(lower))
return p;
}
return null;
}
//# sourceMappingURL=patterns.js.map
{"version":3,"file":"patterns.js","sourceRoot":"","sources":["../../src/paranoia/patterns.ts"],"names":[],"mappings":"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"}
/**
* Rollback Engine — Post-hoc compensation for PostToolUse verdict failures (T11 / G1).
*
* When a PostToolUse verdict fails (i.e. the gate evaluates an action AFTER the
* tool has already mutated state), the rollback engine selects a strategy to
* revert the mutation:
*
* - git-revert → for committed changes (uses `git revert <sha>`)
* - git-restore → for staged-but-uncommitted changes (uses `git restore --staged`)
* - file-restore → for direct file Write/Edit ops (restores from `.sunaiva/backup/`)
* - noop → nothing to revert (read-only ops, info queries, etc.)
*
* Constraints (R3 §2 failure taxonomy + sprint plan §3.2 acceptance criteria):
* - Rollback NEVER touches files outside `<repo>` boundary.
* - Every rollback is itself logged as an audit entry.
* - dryRun=true predicts strategy without mutating filesystem.
* - Fail-OPEN never applies — rollback is compensating, so it must run
* deterministically; errors propagate as detail and `reverted: false`.
*/
export interface RollbackContext {
/** ULID of the verdict that triggered rollback. */
verdict_id: string;
/** Tool name from PostToolUse event (e.g. "Edit", "Write", "Bash"). */
tool_name: string;
/** The action string (for Bash this is the command; for Edit/Write the file path or summary). */
action: string;
/** File the tool wrote to (for Edit/Write strategies). */
target_path?: string;
/** Git SHA captured before the tool ran (enables git-revert pinpointing). */
git_sha_before?: string;
/** Optional repo root override (defaults to cwd). */
repo_root?: string;
}
export type RollbackStrategy = "git-revert" | "git-restore" | "file-restore" | "noop";
export interface RollbackResult {
strategy: RollbackStrategy;
reverted: boolean;
detail: string;
audit_entry_id: string;
}
export interface RollbackOptions {
dryRun?: boolean;
}
/**
* Select the appropriate rollback strategy based on the tool that ran.
* This is a pure decision function (no I/O) so it's safe to call in dry-run.
*/
export declare function selectStrategy(ctx: RollbackContext): RollbackStrategy;
/**
* Main entry point. Pick strategy → execute → emit audit entry.
*/
export declare function rollback(ctx: RollbackContext, opts?: RollbackOptions): Promise<RollbackResult>;
export interface PostToolUseVerdict {
allowed: boolean;
verdict_id?: string;
tool_name?: string;
action?: string;
target_path?: string;
git_sha_before?: string;
}
export declare function maybeRollbackOnPostToolUseFailure(verdict: PostToolUseVerdict): Promise<RollbackResult | null>;
//# sourceMappingURL=engine.d.ts.map
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/rollback/engine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAOH,MAAM,WAAW,eAAe;IAC9B,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,MAAM,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,aAAa,GAAG,cAAc,GAAG,MAAM,CAAC;AAEtF,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,eAAe,GAAG,gBAAgB,CAkCrE;AAUD;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,GAAG,EAAE,eAAe,EACpB,IAAI,GAAE,eAAoB,GACzB,OAAO,CAAC,cAAc,CAAC,CA2EzB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,wBAAsB,iCAAiC,CACrD,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAUhC"}
/**
* Rollback Engine — Post-hoc compensation for PostToolUse verdict failures (T11 / G1).
*
* When a PostToolUse verdict fails (i.e. the gate evaluates an action AFTER the
* tool has already mutated state), the rollback engine selects a strategy to
* revert the mutation:
*
* - git-revert → for committed changes (uses `git revert <sha>`)
* - git-restore → for staged-but-uncommitted changes (uses `git restore --staged`)
* - file-restore → for direct file Write/Edit ops (restores from `.sunaiva/backup/`)
* - noop → nothing to revert (read-only ops, info queries, etc.)
*
* Constraints (R3 §2 failure taxonomy + sprint plan §3.2 acceptance criteria):
* - Rollback NEVER touches files outside `<repo>` boundary.
* - Every rollback is itself logged as an audit entry.
* - dryRun=true predicts strategy without mutating filesystem.
* - Fail-OPEN never applies — rollback is compensating, so it must run
* deterministically; errors propagate as detail and `reverted: false`.
*/
import { appendAudit } from "../tools/audit.js";
import { rollbackGitRevert } from "./strategies/git-revert.js";
import { rollbackGitRestore } from "./strategies/git-restore.js";
import { rollbackFileRestore } from "./strategies/file-restore.js";
/**
* Select the appropriate rollback strategy based on the tool that ran.
* This is a pure decision function (no I/O) so it's safe to call in dry-run.
*/
export function selectStrategy(ctx) {
const tool = (ctx.tool_name || "").toLowerCase();
const action = (ctx.action || "").toLowerCase();
// Direct file mutations → file-restore from backup.
if (tool === "edit" ||
tool === "write" ||
tool === "multiedit" ||
tool === "notebookedit") {
if (ctx.target_path)
return "file-restore";
return "noop";
}
// Bash with git commit / commit-creating ops → git-revert.
if (tool === "bash") {
if (/\bgit\s+commit\b/.test(action) ||
/\bgit\s+merge\b/.test(action) ||
/\bgit\s+rebase\b/.test(action)) {
return "git-revert";
}
if (/\bgit\s+add\b/.test(action) || /\bgit\s+stage\b/.test(action)) {
return "git-restore";
}
// Any other bash command — not safe to auto-revert. Caller may have a
// git_sha_before hint, in which case we can still try git-revert.
if (ctx.git_sha_before)
return "git-revert";
return "noop";
}
return "noop";
}
/**
* Generate a deterministic audit entry id for a rollback event.
* Format: `rb_<verdict_id>_<timestamp>`.
*/
function makeAuditEntryId(verdict_id) {
return `rb_${verdict_id}_${Date.now()}`;
}
/**
* Main entry point. Pick strategy → execute → emit audit entry.
*/
export async function rollback(ctx, opts = {}) {
const dryRun = opts.dryRun === true;
const strategy = selectStrategy(ctx);
const audit_entry_id = makeAuditEntryId(ctx.verdict_id);
// Dry-run: predict only. No I/O against the filesystem.
if (dryRun) {
const result = {
strategy,
reverted: false,
detail: `dry-run: would invoke ${strategy}`,
audit_entry_id,
};
appendAudit({
timestamp: new Date().toISOString(),
type: "rollback_dry_run",
decision: "rollback",
strategy,
verdict_id: ctx.verdict_id,
tool_name: ctx.tool_name,
target_path: ctx.target_path,
audit_entry_id,
});
return result;
}
let reverted = false;
let detail = "";
try {
switch (strategy) {
case "git-revert": {
const r = await rollbackGitRevert(ctx);
reverted = r.reverted;
detail = r.detail;
break;
}
case "git-restore": {
const r = await rollbackGitRestore(ctx);
reverted = r.reverted;
detail = r.detail;
break;
}
case "file-restore": {
const r = await rollbackFileRestore(ctx);
reverted = r.reverted;
detail = r.detail;
break;
}
case "noop":
default:
reverted = false;
detail = "no rollback strategy applicable for this tool/action";
break;
}
}
catch (err) {
reverted = false;
detail = `strategy ${strategy} threw: ${err instanceof Error ? err.message : String(err)}`;
}
appendAudit({
timestamp: new Date().toISOString(),
type: "rollback",
decision: "rollback",
strategy,
reverted,
detail: detail.slice(0, 500),
verdict_id: ctx.verdict_id,
tool_name: ctx.tool_name,
action: (ctx.action || "").slice(0, 200),
target_path: ctx.target_path,
audit_entry_id,
});
return { strategy, reverted, detail, audit_entry_id };
}
export async function maybeRollbackOnPostToolUseFailure(verdict) {
if (verdict.allowed)
return null;
if (!verdict.tool_name || !verdict.action)
return null;
return await rollback({
verdict_id: verdict.verdict_id ?? `auto_${Date.now()}`,
tool_name: verdict.tool_name,
action: verdict.action,
target_path: verdict.target_path,
git_sha_before: verdict.git_sha_before,
});
}
//# sourceMappingURL=engine.js.map
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/rollback/engine.ts"],"names":[],"mappings":"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"}
/**
* file-restore strategy — restore a file from `.sunaiva/backup/` to its original
* location.
*
* Backup convention: PreToolUse handlers for Write/Edit copy the original file
* into `<repo>/.sunaiva/backup/<sha256(target_path)>.bak` before allowing the
* tool to mutate it. On PostToolUse verdict failure, this strategy restores
* that backup.
*
* Safety:
* - Never writes outside repo_root (refuses absolute paths that escape).
* - If no backup exists, returns reverted: false (caller decides what to do).
* - Backup deletion is opt-in (kept by default for audit).
*/
import type { RollbackContext } from "../engine.js";
export interface StrategyResult {
reverted: boolean;
detail: string;
}
/** Deterministic backup filename — sha256 of the absolute target path. */
export declare function backupPathFor(repoRoot: string, targetPath: string): string;
/** Ensure backup directory exists; called by the PreToolUse capture path. */
export declare function ensureBackupDir(repoRoot: string): string;
/**
* Capture the current state of a file into the backup dir. Idempotent —
* safe to call multiple times. Called by PreToolUse before Write/Edit runs.
* Returns the backup path on success, null on failure (fail-OPEN: never throws).
*/
export declare function captureBackup(repoRoot: string, targetPath: string): string | null;
export declare function rollbackFileRestore(ctx: RollbackContext): Promise<StrategyResult>;
/** Test/maintenance helper. */
export declare function purgeBackup(repoRoot: string, targetPath: string): boolean;
//# sourceMappingURL=file-restore.d.ts.map
{"version":3,"file":"file-restore.d.ts","sourceRoot":"","sources":["../../../src/rollback/strategies/file-restore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAIpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAI1E;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAIxD;AASD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAYjF;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAsCvF;AAED,+BAA+B;AAC/B,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAWzE"}
/**
* file-restore strategy — restore a file from `.sunaiva/backup/` to its original
* location.
*
* Backup convention: PreToolUse handlers for Write/Edit copy the original file
* into `<repo>/.sunaiva/backup/<sha256(target_path)>.bak` before allowing the
* tool to mutate it. On PostToolUse verdict failure, this strategy restores
* that backup.
*
* Safety:
* - Never writes outside repo_root (refuses absolute paths that escape).
* - If no backup exists, returns reverted: false (caller decides what to do).
* - Backup deletion is opt-in (kept by default for audit).
*/
import { existsSync, copyFileSync, unlinkSync, mkdirSync } from "node:fs";
import { createHash } from "node:crypto";
import { join, dirname, isAbsolute, relative } from "node:path";
const BACKUP_DIR_REL = ".sunaiva/backup";
/** Deterministic backup filename — sha256 of the absolute target path. */
export function backupPathFor(repoRoot, targetPath) {
const abs = isAbsolute(targetPath) ? targetPath : join(repoRoot, targetPath);
const hash = createHash("sha256").update(abs).digest("hex").slice(0, 32);
return join(repoRoot, BACKUP_DIR_REL, `${hash}.bak`);
}
/** Ensure backup directory exists; called by the PreToolUse capture path. */
export function ensureBackupDir(repoRoot) {
const dir = join(repoRoot, BACKUP_DIR_REL);
mkdirSync(dir, { recursive: true });
return dir;
}
/** True iff `target` resolves to a path within `repoRoot`. */
function pathInRepo(repoRoot, target) {
const abs = isAbsolute(target) ? target : join(repoRoot, target);
const rel = relative(repoRoot, abs);
return !rel.startsWith("..") && !isAbsolute(rel);
}
/**
* Capture the current state of a file into the backup dir. Idempotent —
* safe to call multiple times. Called by PreToolUse before Write/Edit runs.
* Returns the backup path on success, null on failure (fail-OPEN: never throws).
*/
export function captureBackup(repoRoot, targetPath) {
try {
if (!pathInRepo(repoRoot, targetPath))
return null;
const abs = isAbsolute(targetPath) ? targetPath : join(repoRoot, targetPath);
if (!existsSync(abs))
return null; // nothing to backup (new file)
const dest = backupPathFor(repoRoot, targetPath);
mkdirSync(dirname(dest), { recursive: true });
copyFileSync(abs, dest);
return dest;
}
catch {
return null;
}
}
export async function rollbackFileRestore(ctx) {
const cwd = ctx.repo_root || process.cwd();
const target = ctx.target_path;
if (!target) {
return { reverted: false, detail: "file-restore: no target_path provided" };
}
if (!pathInRepo(cwd, target)) {
return {
reverted: false,
detail: `file-restore: refused — target ${target} is outside repo ${cwd}`,
};
}
const backup = backupPathFor(cwd, target);
if (!existsSync(backup)) {
return {
reverted: false,
detail: `file-restore: no backup found for ${target} (expected at ${BACKUP_DIR_REL}/...)`,
};
}
try {
const abs = isAbsolute(target) ? target : join(cwd, target);
mkdirSync(dirname(abs), { recursive: true });
copyFileSync(backup, abs);
// Keep the backup file in place — audit trail. Caller may prune.
return {
reverted: true,
detail: `file-restore: restored ${target} from ${BACKUP_DIR_REL}`,
};
}
catch (err) {
return {
reverted: false,
detail: `file-restore: failed to copy backup → target: ${err instanceof Error ? err.message : String(err)}`,
};
}
}
/** Test/maintenance helper. */
export function purgeBackup(repoRoot, targetPath) {
try {
const backup = backupPathFor(repoRoot, targetPath);
if (existsSync(backup)) {
unlinkSync(backup);
return true;
}
return false;
}
catch {
return false;
}
}
//# sourceMappingURL=file-restore.js.map
{"version":3,"file":"file-restore.js","sourceRoot":"","sources":["../../../src/rollback/strategies/file-restore.ts"],"names":[],"mappings":"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"}
/**
* git-restore strategy — unstage and discard changes for files added but not
* committed (the post-`git add` / pre-`git commit` window).
*
* Steps:
* 1. `git restore --staged <path>` to unstage.
* 2. `git restore <path>` to discard working-tree changes.
*
* Scope: limited to ctx.target_path if provided, else operates on the full
* staging area (`.`). Refuses to traverse outside repo_root.
*/
import type { RollbackContext } from "../engine.js";
export interface StrategyResult {
reverted: boolean;
detail: string;
}
export declare function rollbackGitRestore(ctx: RollbackContext): Promise<StrategyResult>;
//# sourceMappingURL=git-restore.d.ts.map
{"version":3,"file":"git-restore.d.ts","sourceRoot":"","sources":["../../../src/rollback/strategies/git-restore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AA8BD,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAiCtF"}
/**
* git-restore strategy — unstage and discard changes for files added but not
* committed (the post-`git add` / pre-`git commit` window).
*
* Steps:
* 1. `git restore --staged <path>` to unstage.
* 2. `git restore <path>` to discard working-tree changes.
*
* Scope: limited to ctx.target_path if provided, else operates on the full
* staging area (`.`). Refuses to traverse outside repo_root.
*/
import { spawnSync } from "node:child_process";
import { existsSync } from "node:fs";
import { join, isAbsolute, relative } from "node:path";
function runGit(args, cwd) {
const r = spawnSync("git", args, {
cwd,
encoding: "utf-8",
timeout: 30_000,
windowsHide: true,
});
return {
code: r.status ?? 1,
stdout: (r.stdout || "").trim(),
stderr: (r.stderr || "").trim(),
};
}
function isInsideRepo(cwd) {
return existsSync(join(cwd, ".git"));
}
/** True iff `target` resolves to a path within `repoRoot`. */
function pathInRepo(repoRoot, target) {
const abs = isAbsolute(target) ? target : join(repoRoot, target);
const rel = relative(repoRoot, abs);
return !rel.startsWith("..") && !isAbsolute(rel);
}
export async function rollbackGitRestore(ctx) {
const cwd = ctx.repo_root || process.cwd();
if (!isInsideRepo(cwd)) {
return { reverted: false, detail: `git-restore: ${cwd} is not a git repo` };
}
const target = ctx.target_path && ctx.target_path.length > 0 ? ctx.target_path : ".";
if (target !== "." && !pathInRepo(cwd, target)) {
return {
reverted: false,
detail: `git-restore: refused — target ${target} is outside repo ${cwd}`,
};
}
// Step 1: unstage.
const unstage = runGit(["restore", "--staged", target], cwd);
// Step 2: discard working-tree changes.
const discard = runGit(["restore", target], cwd);
if (unstage.code !== 0 && discard.code !== 0) {
return {
reverted: false,
detail: `git-restore: both steps failed (${unstage.stderr.slice(0, 100)} / ${discard.stderr.slice(0, 100)})`,
};
}
return {
reverted: true,
detail: `git-restore: unstaged and discarded changes for ${target}`,
};
}
//# sourceMappingURL=git-restore.js.map
{"version":3,"file":"git-restore.js","sourceRoot":"","sources":["../../../src/rollback/strategies/git-restore.ts"],"names":[],"mappings":"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"}
/**
* git-revert strategy — revert a commit by SHA (or HEAD if no SHA captured).
*
* Safety:
* - Always uses `--no-edit` to avoid hanging on editor invocation.
* - Always runs in the repo_root (or cwd) — never escapes.
* - If the commit is unmergeable, abort cleanly and return reverted: false.
*/
import type { RollbackContext } from "../engine.js";
export interface StrategyResult {
reverted: boolean;
detail: string;
}
export declare function rollbackGitRevert(ctx: RollbackContext): Promise<StrategyResult>;
//# sourceMappingURL=git-revert.d.ts.map
{"version":3,"file":"git-revert.d.ts","sourceRoot":"","sources":["../../../src/rollback/strategies/git-revert.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAuBD,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8DrF"}
/**
* git-revert strategy — revert a commit by SHA (or HEAD if no SHA captured).
*
* Safety:
* - Always uses `--no-edit` to avoid hanging on editor invocation.
* - Always runs in the repo_root (or cwd) — never escapes.
* - If the commit is unmergeable, abort cleanly and return reverted: false.
*/
import { spawnSync } from "node:child_process";
import { existsSync } from "node:fs";
import { join } from "node:path";
function runGit(args, cwd) {
const r = spawnSync("git", args, {
cwd,
encoding: "utf-8",
timeout: 30_000,
windowsHide: true,
});
return {
code: r.status ?? 1,
stdout: (r.stdout || "").trim(),
stderr: (r.stderr || "").trim(),
};
}
function isInsideRepo(cwd) {
return existsSync(join(cwd, ".git"));
}
export async function rollbackGitRevert(ctx) {
const cwd = ctx.repo_root || process.cwd();
if (!isInsideRepo(cwd)) {
return { reverted: false, detail: `git-revert: ${cwd} is not a git repo` };
}
// Determine the commit to revert.
// Priority: ctx.git_sha_before (captured before the tool ran — but we want
// the commit CREATED by the tool, which is HEAD now if SHA matches).
// If git_sha_before is provided, the commit to revert is HEAD (the one after).
let targetSha = "HEAD";
if (ctx.git_sha_before) {
// Verify HEAD is descendant of git_sha_before — i.e. there is exactly
// one new commit. If multiple, revert all newer than git_sha_before.
const before = ctx.git_sha_before;
const rev = runGit(["rev-list", `${before}..HEAD`], cwd);
if (rev.code === 0 && rev.stdout) {
// List of new SHAs, newest first. Revert all of them in reverse order.
const shas = rev.stdout.split("\n").filter(Boolean);
if (shas.length === 0) {
return {
reverted: false,
detail: "git-revert: HEAD == git_sha_before, nothing to revert",
};
}
// Revert from newest to oldest so each revert applies cleanly.
const revertResults = [];
for (const sha of shas) {
const out = runGit(["revert", "--no-edit", sha], cwd);
if (out.code !== 0) {
// Best-effort abort to leave the working tree clean.
runGit(["revert", "--abort"], cwd);
return {
reverted: false,
detail: `git-revert: failed reverting ${sha.slice(0, 7)}: ${out.stderr.slice(0, 200)}`,
};
}
revertResults.push(sha.slice(0, 7));
}
return {
reverted: true,
detail: `git-revert: reverted ${revertResults.length} commit(s) [${revertResults.join(", ")}]`,
};
}
targetSha = before; // fall through to single-shot revert if rev-list failed
}
// Single-shot revert: HEAD (default) or the resolved SHA.
const out = runGit(["revert", "--no-edit", targetSha], cwd);
if (out.code !== 0) {
runGit(["revert", "--abort"], cwd);
return {
reverted: false,
detail: `git-revert: failed (${out.stderr.slice(0, 200) || `exit ${out.code}`})`,
};
}
return { reverted: true, detail: `git-revert: reverted ${targetSha}` };
}
//# sourceMappingURL=git-revert.js.map
{"version":3,"file":"git-revert.js","sourceRoot":"","sources":["../../../src/rollback/strategies/git-revert.ts"],"names":[],"mappings":"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"}
/**
* Timelock CLI — `sunaiva-gate cancel <token>` (1.2.0 T10).
*
* Thin command-handler that's wired into src/index.ts argv parsing. Exit
* code semantics:
* 0 = cancellation succeeded
* 2 = invalid arguments (no token, unknown token, already resolved)
* 3 = internal error
*/
import { TimelockManager } from "./manager.js";
export interface TimelockCliResult {
ok: boolean;
exit_code: number;
message: string;
record?: unknown;
}
/** Cancel a pending action. */
export declare function runCancelCli(token: string | undefined, opts?: {
reason?: string;
manager?: TimelockManager;
}): Promise<TimelockCliResult>;
/** List pending actions (informational helper). */
export declare function runListPendingCli(opts?: {
manager?: TimelockManager;
}): Promise<TimelockCliResult>;
//# sourceMappingURL=cli.d.ts.map
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/timelock/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,+BAA+B;AAC/B,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,eAAe,CAAA;CAAO,GACxD,OAAO,CAAC,iBAAiB,CAAC,CAwB5B;AAED,mDAAmD;AACnD,wBAAsB,iBAAiB,CACrC,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,eAAe,CAAA;CAAO,GACvC,OAAO,CAAC,iBAAiB,CAAC,CAiB5B"}
/**
* Timelock CLI — `sunaiva-gate cancel <token>` (1.2.0 T10).
*
* Thin command-handler that's wired into src/index.ts argv parsing. Exit
* code semantics:
* 0 = cancellation succeeded
* 2 = invalid arguments (no token, unknown token, already resolved)
* 3 = internal error
*/
import { TimelockManager } from "./manager.js";
/** Cancel a pending action. */
export async function runCancelCli(token, opts = {}) {
if (!token || typeof token !== "string") {
return {
ok: false,
exit_code: 2,
message: "Usage: sunaiva-gate cancel <token>",
};
}
const mgr = opts.manager ?? new TimelockManager();
try {
const record = await mgr.cancel(token, opts.reason);
return {
ok: true,
exit_code: 0,
message: `Cancelled token ${token} (artifact_id=${record.artifact_id})`,
record,
};
}
catch (err) {
return {
ok: false,
exit_code: 2,
message: err instanceof Error ? err.message : String(err),
};
}
}
/** List pending actions (informational helper). */
export async function runListPendingCli(opts = {}) {
const mgr = opts.manager ?? new TimelockManager();
try {
const records = mgr.list({ status: "pending" });
return {
ok: true,
exit_code: 0,
message: `${records.length} pending action(s)`,
record: records,
};
}
catch (err) {
return {
ok: false,
exit_code: 3,
message: err instanceof Error ? err.message : String(err),
};
}
}
//# sourceMappingURL=cli.js.map
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/timelock/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAS/C,+BAA+B;AAC/B,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAyB,EACzB,OAAuD,EAAE;IAEzD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,oCAAoC;SAC9C,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,eAAe,EAAE,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,mBAAmB,KAAK,iBAAiB,MAAM,CAAC,WAAW,GAAG;YACvE,MAAM;SACP,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC1D,CAAC;IACJ,CAAC;AACH,CAAC;AAED,mDAAmD;AACnD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAsC,EAAE;IAExC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,eAAe,EAAE,CAAC;IAClD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;QAChD,OAAO;YACL,EAAE,EAAE,IAAI;YACR,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,oBAAoB;YAC9C,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC1D,CAAC;IACJ,CAAC;AACH,CAAC"}
/**
* Time-Locked Publish-Class Actions — Sprint 1.2.0 (T10, builder W2-B4).
*
* Cures the failure_051 class of incidents (sub-agent autonomously creates a
* public repository or publishes a package). For publish-class actions, the
* gate writes a "pending" record with a cancellation window (default 5 min,
* configurable via SUNAIVA_TIMELOCK_WINDOW_MINUTES). Humans can cancel via
* `sunaiva-gate cancel <token>` within the window.
*
* Per §9.2 fail-safe #5: window_minutes cannot be reduced below 1 (hard floor).
*
* Storage: ~/.sunaiva/timelock/<token>.json — one file per pending action.
* Atomic operations via write-rename. No SQLite (Rule 7). All state is on-disk.
*
* SECURITY NOTE: cancel() does NOT require authentication on top of filesystem
* ACLs. Operators relying on this for multi-user environments must protect
* ~/.sunaiva/timelock/ via OS file permissions.
*/
export type PendingStatus = "pending" | "cancelled" | "promoted";
export interface PendingAction {
token: string;
artifact_id: string;
scheduled_promote_at: string;
created_at: string;
status: PendingStatus;
window_minutes: number;
/** When the status changed to cancelled or promoted. */
resolved_at?: string;
/** Free-form reason for cancellation (e.g. "user cancelled via CLI"). */
resolution_reason?: string;
}
export interface TimelockManagerOptions {
/** Override the on-disk store directory. Defaults to ~/.sunaiva/timelock. */
storeDir?: string;
/** Override env (for tests). Defaults to process.env. */
env?: NodeJS.ProcessEnv;
/** Override current time for deterministic tests. */
now?: () => Date;
}
export declare class TimelockManager {
private readonly storeDir;
private readonly env;
private readonly now;
constructor(opts?: TimelockManagerOptions);
private resolveWindowMinutes;
private filenameFor;
/** Create a fresh pending-action record. */
createPending(artifact_id: string, window_minutes?: number): Promise<PendingAction>;
/** Read a pending record by token. Returns null if not found. */
read(token: string): PendingAction | null;
/** Cancel within the window. Throws if already past the promote time or already resolved. */
cancel(token: string, reason?: string): Promise<PendingAction>;
/** Auto-promote all pending records whose window has elapsed. Returns promoted records. */
promoteIfDue(): Promise<PendingAction[]>;
/** List all pending records (for diagnostic / CLI listing). */
list(filter?: {
status?: PendingStatus;
}): PendingAction[];
/** Delete a record (only safe after resolved). */
delete(token: string): boolean;
}
export declare function _resetDefaultManagerForTests(): void;
export declare function createPending(artifact_id: string, window_minutes: number): Promise<PendingAction>;
export declare function cancel(token: string): Promise<PendingAction>;
export declare function promoteIfDue(): Promise<PendingAction[]>;
//# sourceMappingURL=manager.d.ts.map
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/timelock/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAmBH,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;AAEjE,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,aAAa,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,yEAAyE;IACzE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,sBAAsB;IACrC,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yDAAyD;IACzD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAa;gBAErB,IAAI,GAAE,sBAA2B;IAM7C,OAAO,CAAC,oBAAoB;IAiB5B,OAAO,CAAC,WAAW;IAKnB,4CAA4C;IACtC,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA2BzF,iEAAiE;IACjE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAUzC,6FAA6F;IACvF,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IA2BpE,2FAA2F;IACrF,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;IAmC9C,+DAA+D;IAC/D,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,aAAa,CAAA;KAAE,GAAG,aAAa,EAAE;IAuB1D,kDAAkD;IAClD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;CAe/B;AAYD,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD;AAED,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,aAAa,CAAC,CAExB;AAED,wBAAsB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAElE;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAE7D"}
/**
* Time-Locked Publish-Class Actions — Sprint 1.2.0 (T10, builder W2-B4).
*
* Cures the failure_051 class of incidents (sub-agent autonomously creates a
* public repository or publishes a package). For publish-class actions, the
* gate writes a "pending" record with a cancellation window (default 5 min,
* configurable via SUNAIVA_TIMELOCK_WINDOW_MINUTES). Humans can cancel via
* `sunaiva-gate cancel <token>` within the window.
*
* Per §9.2 fail-safe #5: window_minutes cannot be reduced below 1 (hard floor).
*
* Storage: ~/.sunaiva/timelock/<token>.json — one file per pending action.
* Atomic operations via write-rename. No SQLite (Rule 7). All state is on-disk.
*
* SECURITY NOTE: cancel() does NOT require authentication on top of filesystem
* ACLs. Operators relying on this for multi-user environments must protect
* ~/.sunaiva/timelock/ via OS file permissions.
*/
import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, writeFileSync, unlinkSync, } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
import { randomBytes } from "node:crypto";
const DEFAULT_WINDOW_MINUTES = 5;
const MIN_WINDOW_MINUTES = 1;
const DEFAULT_STORE_DIR = join(homedir(), ".sunaiva", "timelock");
export class TimelockManager {
storeDir;
env;
now;
constructor(opts = {}) {
this.env = opts.env ?? process.env;
this.storeDir = opts.storeDir ?? DEFAULT_STORE_DIR;
this.now = opts.now ?? (() => new Date());
}
resolveWindowMinutes(input) {
if (input !== undefined && input !== null) {
if (!Number.isFinite(input) || input < MIN_WINDOW_MINUTES) {
throw new Error(`Timelock window must be >= ${MIN_WINDOW_MINUTES} minute(s) (got ${input}). Hard floor per §9.2 fail-safe #5.`);
}
return Math.floor(input);
}
const envVal = this.env.SUNAIVA_TIMELOCK_WINDOW_MINUTES;
if (envVal) {
const parsed = parseInt(envVal, 10);
if (Number.isFinite(parsed) && parsed >= MIN_WINDOW_MINUTES)
return parsed;
}
return DEFAULT_WINDOW_MINUTES;
}
filenameFor(token) {
// Token format ensures filename safety
return join(this.storeDir, `${token}.json`);
}
/** Create a fresh pending-action record. */
async createPending(artifact_id, window_minutes) {
if (!artifact_id || typeof artifact_id !== "string") {
throw new Error("createPending: 'artifact_id' is required");
}
const wm = this.resolveWindowMinutes(window_minutes);
const now = this.now();
const promoteAt = new Date(now.getTime() + wm * 60_000);
// Token: opaque hex, no PII. 16 bytes = 32 hex chars.
const token = randomBytes(16).toString("hex");
const record = {
token,
artifact_id,
scheduled_promote_at: promoteAt.toISOString(),
created_at: now.toISOString(),
status: "pending",
window_minutes: wm,
};
mkdirSync(this.storeDir, { recursive: true });
// Atomic write: write to temp then rename.
const tmpPath = this.filenameFor(token) + ".tmp";
writeFileSync(tmpPath, JSON.stringify(record, null, 2), "utf-8");
renameSync(tmpPath, this.filenameFor(token));
return record;
}
/** Read a pending record by token. Returns null if not found. */
read(token) {
const path = this.filenameFor(token);
if (!existsSync(path))
return null;
try {
return JSON.parse(readFileSync(path, "utf-8"));
}
catch {
return null;
}
}
/** Cancel within the window. Throws if already past the promote time or already resolved. */
async cancel(token, reason) {
const existing = this.read(token);
if (!existing) {
throw new Error(`cancel: unknown token '${token}'`);
}
if (existing.status !== "pending") {
throw new Error(`cancel: token '${token}' is already ${existing.status}. Cannot cancel.`);
}
const promoteAt = new Date(existing.scheduled_promote_at);
const now = this.now();
if (now.getTime() >= promoteAt.getTime()) {
throw new Error(`cancel: token '${token}' window has elapsed (scheduled ${existing.scheduled_promote_at}, now ${now.toISOString()}). Use 'promoteIfDue' to clean up.`);
}
const updated = {
...existing,
status: "cancelled",
resolved_at: now.toISOString(),
resolution_reason: reason ?? "cancelled via CLI",
};
const tmpPath = this.filenameFor(token) + ".tmp";
writeFileSync(tmpPath, JSON.stringify(updated, null, 2), "utf-8");
renameSync(tmpPath, this.filenameFor(token));
return updated;
}
/** Auto-promote all pending records whose window has elapsed. Returns promoted records. */
async promoteIfDue() {
if (!existsSync(this.storeDir))
return [];
const now = this.now();
const promoted = [];
let entries = [];
try {
entries = readdirSync(this.storeDir).filter((f) => f.endsWith(".json"));
}
catch {
return [];
}
for (const entry of entries) {
const fullPath = join(this.storeDir, entry);
let record;
try {
record = JSON.parse(readFileSync(fullPath, "utf-8"));
}
catch {
continue;
}
if (record.status !== "pending")
continue;
const promoteAt = new Date(record.scheduled_promote_at);
if (now.getTime() < promoteAt.getTime())
continue;
const updated = {
...record,
status: "promoted",
resolved_at: now.toISOString(),
resolution_reason: "window elapsed",
};
const tmpPath = fullPath + ".tmp";
writeFileSync(tmpPath, JSON.stringify(updated, null, 2), "utf-8");
renameSync(tmpPath, fullPath);
promoted.push(updated);
}
return promoted;
}
/** List all pending records (for diagnostic / CLI listing). */
list(filter) {
if (!existsSync(this.storeDir))
return [];
let entries = [];
try {
entries = readdirSync(this.storeDir).filter((f) => f.endsWith(".json"));
}
catch {
return [];
}
const records = [];
for (const entry of entries) {
try {
const r = JSON.parse(readFileSync(join(this.storeDir, entry), "utf-8"));
if (filter?.status && r.status !== filter.status)
continue;
records.push(r);
}
catch {
continue;
}
}
return records;
}
/** Delete a record (only safe after resolved). */
delete(token) {
const existing = this.read(token);
if (!existing)
return false;
if (existing.status === "pending") {
throw new Error(`delete: refusing to delete still-pending token '${token}' — cancel first`);
}
try {
unlinkSync(this.filenameFor(token));
return true;
}
catch {
return false;
}
}
}
// ---------------------------------------------------------------------------
// Convenience module-level functions (per §3.4 signature)
// ---------------------------------------------------------------------------
let _defaultManager = null;
function defaultManager() {
if (!_defaultManager)
_defaultManager = new TimelockManager();
return _defaultManager;
}
export function _resetDefaultManagerForTests() {
_defaultManager = null;
}
export async function createPending(artifact_id, window_minutes) {
return defaultManager().createPending(artifact_id, window_minutes);
}
export async function cancel(token) {
return defaultManager().cancel(token);
}
export async function promoteIfDue() {
return defaultManager().promoteIfDue();
}
//# sourceMappingURL=manager.js.map
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/timelock/manager.ts"],"names":[],"mappings":"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"}
/**
* Ruleset version registry client (W2-B3 / T07).
*
* Consults `GET /api/v1/ruleset/:version` on the Sunaiva Gate premium
* backend to fetch a pinned ruleset by tag or SHA.
*
* Per §5.2 of SPRINT_1_2_0_PLAN.md these endpoints are SCAFFOLDED
* (not deployed) in 1.2.0. This client therefore:
* - Honours the same `SUNAIVA_GATE_BACKEND_URL` env var the rest of
* the 1.1.0 backend-client uses.
* - Accepts an injected fetch impl for testability (mock backend in
* unit tests; real fetch when deployed in 1.3.0).
* - Fails OPEN on any backend error — the rule-engine treats a
* skipped pin the same as "no pin requested" so a Sunaiva outage
* never blocks the customer (matches the 1.1.0 backend-client
* pattern). Audit caller is responsible for recording the skip.
*
* Caller order:
* 1. parseRulesetRef(input) — input validation (validator.ts)
* 2. registry.fetchByRef(parsed) — backend lookup (this file)
* 3. rule-engine evaluates against the returned ruleset.
*/
import { type RulesetRef } from "./validator.js";
export interface RulesetFetchOptions {
/** Backend base URL. Defaults to env SUNAIVA_GATE_BACKEND_URL → DEFAULT_BACKEND_URL. */
backendUrl?: string;
/** API token. Defaults to env SUNAIVA_GATE_API_TOKEN. */
apiToken?: string;
/** Timeout in ms. Defaults to 3000. */
timeoutMs?: number;
/** Injected fetch impl (test fixture). Defaults to globalThis.fetch. */
fetchImpl?: typeof fetch;
/** Env override (tests). Defaults to process.env. */
env?: NodeJS.ProcessEnv;
}
export interface PinnedRulesetResponse {
/** The canonical tag (e.g. `v1.4.7`) or 40-char SHA. */
ruleset_version: string;
/** Backend-provided sha256 hex of the rule set body. */
ruleset_hash: string;
/** The actual rules array (shape matches dist/rules/rules.json). */
rules: unknown[];
/** ISO timestamp of when the backend issued the response. */
issued_at: string;
/** Backend signature over the canonical-json of the response (excluding signature itself). */
signature?: string;
}
export interface RulesetFetchResult {
/** True iff a ruleset was successfully returned. */
ok: boolean;
/** Resolved ruleset, present when ok=true. */
ruleset?: PinnedRulesetResponse;
/** Status code from the backend (or 0 for network failures). */
status: number;
/** Human-readable reason for skip / error. */
reason: string;
}
/**
* Fetch a pinned ruleset by reference. Fails OPEN — on any error this
* returns `{ ok: false, status, reason }`. Callers (rule-engine) treat
* `ok=false` as "no pin honoured, evaluate with the default ruleset"
* and record an audit entry tagged `bypass_reason: 'ruleset-pin-skipped'`.
*
* NEVER throws.
*/
export declare function fetchByRef(ref: RulesetRef, opts?: RulesetFetchOptions): Promise<RulesetFetchResult>;
//# sourceMappingURL=registry.d.ts.map
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/version-pin/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAKrE,MAAM,WAAW,mBAAmB;IAClC,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,qDAAqD;IACrD,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB;IACpC,wDAAwD;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,YAAY,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,8FAA8F;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,oDAAoD;IACpD,EAAE,EAAE,OAAO,CAAC;IACZ,8CAA8C;IAC9C,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,UAAU,EACf,IAAI,GAAE,mBAAwB,GAC7B,OAAO,CAAC,kBAAkB,CAAC,CA8E7B"}
/**
* Ruleset version registry client (W2-B3 / T07).
*
* Consults `GET /api/v1/ruleset/:version` on the Sunaiva Gate premium
* backend to fetch a pinned ruleset by tag or SHA.
*
* Per §5.2 of SPRINT_1_2_0_PLAN.md these endpoints are SCAFFOLDED
* (not deployed) in 1.2.0. This client therefore:
* - Honours the same `SUNAIVA_GATE_BACKEND_URL` env var the rest of
* the 1.1.0 backend-client uses.
* - Accepts an injected fetch impl for testability (mock backend in
* unit tests; real fetch when deployed in 1.3.0).
* - Fails OPEN on any backend error — the rule-engine treats a
* skipped pin the same as "no pin requested" so a Sunaiva outage
* never blocks the customer (matches the 1.1.0 backend-client
* pattern). Audit caller is responsible for recording the skip.
*
* Caller order:
* 1. parseRulesetRef(input) — input validation (validator.ts)
* 2. registry.fetchByRef(parsed) — backend lookup (this file)
* 3. rule-engine evaluates against the returned ruleset.
*/
import { rulesetRefToString } from "./validator.js";
const DEFAULT_BACKEND_URL = "https://mcp.sunaivacore.io/v1/gatehooks";
const DEFAULT_TIMEOUT_MS = 3000;
/**
* Fetch a pinned ruleset by reference. Fails OPEN — on any error this
* returns `{ ok: false, status, reason }`. Callers (rule-engine) treat
* `ok=false` as "no pin honoured, evaluate with the default ruleset"
* and record an audit entry tagged `bypass_reason: 'ruleset-pin-skipped'`.
*
* NEVER throws.
*/
export async function fetchByRef(ref, opts = {}) {
const env = opts.env ?? process.env;
const backendUrl = opts.backendUrl ?? env.SUNAIVA_GATE_BACKEND_URL ?? DEFAULT_BACKEND_URL;
const apiToken = opts.apiToken ?? env.SUNAIVA_GATE_API_TOKEN;
const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
const fetchImpl = opts.fetchImpl ?? globalThis.fetch;
if (typeof fetchImpl !== "function") {
return {
ok: false,
status: 0,
reason: "no fetch implementation available — ruleset-pin skipped",
};
}
if (!apiToken) {
return {
ok: false,
status: 0,
reason: "SUNAIVA_GATE_API_TOKEN unset — ruleset-pin skipped (fail-OPEN)",
};
}
const refStr = encodeURIComponent(rulesetRefToString(ref));
const url = `${backendUrl.replace(/\/+$/, "")}/api/v1/ruleset/${refStr}`;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const res = await fetchImpl(url, {
method: "GET",
signal: controller.signal,
headers: {
Accept: "application/json",
Authorization: `Bearer ${apiToken}`,
"User-Agent": "@sunaiva/gate@1.2.0",
},
});
if (!res.ok) {
return {
ok: false,
status: res.status,
reason: `backend returned ${res.status} — ruleset-pin skipped`,
};
}
let body;
try {
body = await res.json();
}
catch (err) {
return {
ok: false,
status: res.status,
reason: `backend response unparseable (${err instanceof Error ? err.message : String(err)})`,
};
}
if (!isPinnedRulesetResponse(body)) {
return {
ok: false,
status: res.status,
reason: "backend response did not match PinnedRulesetResponse shape",
};
}
return { ok: true, status: res.status, ruleset: body, reason: "ok" };
}
catch (err) {
const msg = err instanceof Error ? err.message : String(err);
return {
ok: false,
status: 0,
reason: `backend fetch failed: ${msg}`,
};
}
finally {
clearTimeout(timer);
}
}
/** Defensive shape check on a backend response. */
function isPinnedRulesetResponse(value) {
if (!value || typeof value !== "object")
return false;
const v = value;
return (typeof v.ruleset_version === "string" &&
typeof v.ruleset_hash === "string" &&
Array.isArray(v.rules) &&
typeof v.issued_at === "string");
}
//# sourceMappingURL=registry.js.map
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/version-pin/registry.ts"],"names":[],"mappings":"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"}
/**
* Ruleset version-pin reference validator (W2-B3 / T07).
*
* Premium rulesets are versioned in the backend. To prevent the
* "ruleset shifted under you" anti-pattern called out in R3 §5 of the
* sprint plan, we enforce the pre-commit-style discipline:
*
* - REJECT branch refs (e.g. `main`, `feature/foo`) — branches move,
* so pinning to one is functionally an unpinned config.
* - ACCEPT git tags (e.g. `v1.4.7`) — immutable by convention.
* - ACCEPT 40-char hex SHAs — fully immutable.
* - REJECT empty / non-string / oversize input.
*
* This module is INPUT VALIDATION ONLY. It does not consult the
* backend; see {@link ./registry.ts} for the registry lookup. Caller
* order should be: parseRulesetRef(input) → registry.fetchByRef(parsed).
*/
export type RulesetRefKind = "tag" | "sha";
export interface RulesetRef {
kind: RulesetRefKind;
/** The exact value after normalization (tag string OR lowercase hex SHA). */
value: string;
}
/**
* Parse a user-supplied ruleset reference. Throws on invalid input.
*
* Accepts:
* - SemVer-style tags (`1.4.7`, `v1.4.7`, `1.4.7-beta.1`).
* - 40-char hex SHAs.
*
* Rejects:
* - Empty string / non-string.
* - Strings > 256 chars (defensive: prevents pathological inputs).
* - Branch refs (`main`, `master`, `dev`, etc. — see BRANCH_NAMES).
* - Anything that looks like a path (contains `/` other than refs/tags/).
*/
export declare function parseRulesetRef(input: string): RulesetRef;
/**
* Type guard: returns true iff `input` would parse without throwing.
* Useful for callers that need a non-throwing pre-check (e.g. CLI args).
*/
export declare function isValidRulesetRef(input: unknown): boolean;
/**
* Render a {@link RulesetRef} back to a stable canonical string for use
* in URLs, file names, and audit logs.
*
* Tags retain their original form (with or without leading `v`); SHAs
* are emitted lower-case.
*/
export declare function rulesetRefToString(ref: RulesetRef): string;
//# sourceMappingURL=validator.d.ts.map
{"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/version-pin/validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAoBH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,KAAK,CAAC;AAE3C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAqDzD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAQzD;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAK1D"}
/**
* Ruleset version-pin reference validator (W2-B3 / T07).
*
* Premium rulesets are versioned in the backend. To prevent the
* "ruleset shifted under you" anti-pattern called out in R3 §5 of the
* sprint plan, we enforce the pre-commit-style discipline:
*
* - REJECT branch refs (e.g. `main`, `feature/foo`) — branches move,
* so pinning to one is functionally an unpinned config.
* - ACCEPT git tags (e.g. `v1.4.7`) — immutable by convention.
* - ACCEPT 40-char hex SHAs — fully immutable.
* - REJECT empty / non-string / oversize input.
*
* This module is INPUT VALIDATION ONLY. It does not consult the
* backend; see {@link ./registry.ts} for the registry lookup. Caller
* order should be: parseRulesetRef(input) → registry.fetchByRef(parsed).
*/
/** Branch-ref allowlist exception: hard-reject all of these. */
const BRANCH_NAMES = new Set([
"main",
"master",
"develop",
"dev",
"trunk",
"next",
"staging",
"production",
"prod",
"release",
]);
const TAG_REGEX = /^v?\d+\.\d+\.\d+(?:[-+][0-9A-Za-z._-]+)*$/;
const SHA_REGEX = /^[0-9a-f]{40}$/i;
const MAX_REF_LENGTH = 256;
/**
* Parse a user-supplied ruleset reference. Throws on invalid input.
*
* Accepts:
* - SemVer-style tags (`1.4.7`, `v1.4.7`, `1.4.7-beta.1`).
* - 40-char hex SHAs.
*
* Rejects:
* - Empty string / non-string.
* - Strings > 256 chars (defensive: prevents pathological inputs).
* - Branch refs (`main`, `master`, `dev`, etc. — see BRANCH_NAMES).
* - Anything that looks like a path (contains `/` other than refs/tags/).
*/
export function parseRulesetRef(input) {
if (typeof input !== "string") {
throw new TypeError("parseRulesetRef: input must be a string");
}
const trimmed = input.trim();
if (trimmed.length === 0) {
throw new TypeError("parseRulesetRef: input must be non-empty");
}
if (trimmed.length > MAX_REF_LENGTH) {
throw new TypeError(`parseRulesetRef: input exceeds ${MAX_REF_LENGTH} chars`);
}
// Normalize `refs/tags/v1.4.7` shorthand by stripping the prefix once.
let value = trimmed;
if (value.startsWith("refs/tags/")) {
value = value.slice("refs/tags/".length);
}
else if (value.startsWith("refs/heads/")) {
throw new TypeError(`parseRulesetRef: branch refs are forbidden (got 'refs/heads/...'). ` +
`Pin to a tag or SHA — see R3 §5 of SPRINT_1_2_0_PLAN.md.`);
}
// SHA check is cheap and unambiguous; do it before tag check.
if (SHA_REGEX.test(value)) {
return { kind: "sha", value: value.toLowerCase() };
}
// Reject obvious branch names.
if (BRANCH_NAMES.has(value.toLowerCase())) {
throw new TypeError(`parseRulesetRef: branch refs are forbidden ('${value}' is a known branch name). ` +
`Pin to a tag or SHA — see R3 §5 of SPRINT_1_2_0_PLAN.md.`);
}
// Reject path-like inputs (commonly branch refs in disguise).
if (value.includes("/")) {
throw new TypeError(`parseRulesetRef: input contains '/'; expected a tag or 40-char SHA. ` +
`Pin to a tag or SHA — see R3 §5 of SPRINT_1_2_0_PLAN.md.`);
}
// Tag check.
if (TAG_REGEX.test(value)) {
return { kind: "tag", value };
}
throw new TypeError(`parseRulesetRef: '${value}' is neither a SemVer tag (e.g. v1.4.7) nor a 40-char hex SHA. ` +
`Pin to a tag or SHA — see R3 §5 of SPRINT_1_2_0_PLAN.md.`);
}
/**
* Type guard: returns true iff `input` would parse without throwing.
* Useful for callers that need a non-throwing pre-check (e.g. CLI args).
*/
export function isValidRulesetRef(input) {
if (typeof input !== "string")
return false;
try {
parseRulesetRef(input);
return true;
}
catch {
return false;
}
}
/**
* Render a {@link RulesetRef} back to a stable canonical string for use
* in URLs, file names, and audit logs.
*
* Tags retain their original form (with or without leading `v`); SHAs
* are emitted lower-case.
*/
export function rulesetRefToString(ref) {
if (!ref || (ref.kind !== "tag" && ref.kind !== "sha")) {
throw new TypeError("rulesetRefToString: invalid RulesetRef");
}
return ref.value;
}
//# sourceMappingURL=validator.js.map
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/version-pin/validator.ts"],"names":[],"mappings":"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"}
+51
-16

@@ -7,8 +7,41 @@ # Changelog

## [Unreleased] — 2026-05-27 — "Build-pipeline P00 fix"
## [1.1.7] — 2026-06-03 — "Bundle Fix"
### Fixed
- **Critical: `ERR_MODULE_NOT_FOUND` on MCP boot** — `files[]` in `package.json` omitted 11 dist
subdirectories that are required at runtime. Any customer running `npx @sunaiva/gate` from
`v1.1.4` through `v1.1.6` would crash immediately with
`Cannot find module '.../dist/events/bridge.js'` (and equivalent errors for `bypass`, `compliance`,
`cost`, `diff`, `explain`, `installer`, `paranoia`, `rollback`, `timelock`, `version-pin`).
The fix adds all missing dirs to `files[]`. `dist/index.js.map` and `dist/index.d.ts.map` also
added for completeness.
- **`PKG_VERSION` constant synced** — `src/index.ts` `PKG_VERSION` updated from `"1.1.6"` to
`"1.1.7"` so the MCP server's reported version matches `package.json` (verify-bundle Check 4).
---
## [1.1.6] — 2026-06-01 — "Honest Launch"
### Changed
- **API endpoint URLs corrected**: identity endpoints (`premium-unlock`, `first-run`, `register-client`) and in-toto attestation builder/buildType URLs updated from `sunaivacore.io` to canonical `sunaiva.ai` / `api.sunaiva.ai` domain.
- **Rule count language unified**: upsell trigger copy corrected from "68 server-side rules" to "69 server-side rules" (canonical: 100 rules total — 31 local + 69 premium server-side).
- **Gate telemetry wired**: `ship_confidence_gate.py` now calls `emit_gate_decision()` from `infra/observability/gate_telemetry_emitter.py` on every gate decision (fire-and-forget, fail-OPEN).
- **Memory observability flush loop added**: `memory_observability.py` gains `start_flush_loop()` / `stop_flush_loop()` — daemon thread POSTs OTLP traces to `http://152.53.201.221:4318/v1/traces` every 30 seconds. Fail-OPEN on any error.
---
## [1.1.5] — 2026-05-31 — "Freemium Monetization"
### Added
- **Stderr upsell trigger** — after 30+ rule evaluations in a single session (tracked via
`action_count` in session-state), the gate emits a one-time stderr line directing free-tier
users to `https://sunaiva.ai/products/gate`. Fires at most once per session (gated by
`upsell_shown` flag persisted to the session state file). Skippable via
`SUNAIVA_NUDGE_OFF=1` (reuses the existing nudge kill-switch). Written to stderr so it never
pollutes JSON stdout or MCP protocol output.
### Fixed
- **`scripts/strip-patterns.js` — critical build-pipeline bug (P00)**: the strip script was
replacing `detection_pattern` with `"[server-side]"` for ALL 100 rules including the 32
constitutional rules. Constitutional rules require their `detection_pattern` to be visible
replacing `detection_pattern` with `"[server-side]"` for ALL 100 rules including the 31
local rules (23 constitutional + 8 recommended). Constitutional rules require their `detection_pattern` to be visible
in the published dist so the local rule-engine can evaluate them without a backend connection.

@@ -18,6 +51,8 @@ The fix: constitutional rules (`enforcement === "constitutional"`) now pass through unchanged;

Any `npm run build` prior to this fix would have produced a `dist/rules/rules.json` where
all 32 constitutional rules had `detection_pattern: "[server-side]"`, causing them to be
all 31 local rules had `detection_pattern: "[server-side]"`, causing them to be
silently skipped by the local engine (same failure class as `failure_054`).
- **`User-Agent` version string** — `backend-client.ts` HTTP header updated from
`sunaiva-gate-client/1.1.0` to `sunaiva-gate-client/1.1.5` (cosmetic version sync).
### Added
### Added (also in this release)
- **`tests/strip-patterns.test.ts`** — 12 tests covering source + dist rules.json integrity:

@@ -28,3 +63,3 @@ correct constitutional/premium counts, no constitutional rule stripped, no overlap between

### Changed
- **`rules/rules.json` (source)** — all 68 non-constitutional rules now carry
- **`rules/rules.json` (source)** — all 69 non-constitutional rules now carry
`"backend_required": true` matching the dist/ baseline. This is the canonical source for

@@ -38,3 +73,3 @@ which rules are premium; `strip-patterns.js` uses it to decide what to strip.

Metadata-only patch release. No functional behaviour changes — same gate, same
100 rules (32 constitutional + 68 premium), same Ship-Confidence integration,
100 rules (31 local + 69 premium), same Ship-Confidence integration,
same smoke-test verdict (HEALTHY). Closes Rule 43.1 (Sunaiva canonical ship

@@ -99,3 +134,3 @@ pathway, hardwired 2026-05-16) by removing all references to the forbidden

### Unchanged (verified)
- 100-rule library, 32 constitutional + 68 premium, byte-identical to v1.1.0
- 100-rule library, 31 local + 69 premium, byte-identical to v1.1.0
- All 6 MCP tools (`validate_action`, `log_bypass`, `get_rules`,

@@ -137,3 +172,3 @@ `update_rules`, `get_audit_log`, `ship_confidence_check`)

- **Premium backend client** (`src/engine/backend-client.ts`) — optional HTTP +
JWT path to `https://mcp.sunaivacore.io/v1/gatehooks` for evaluating the 68
JWT path to `https://mcp.sunaivacore.io/v1/gatehooks` for evaluating the 69
premium rules server-side. Opt-in via `SUNAIVA_GATE_BACKEND_URL` +

@@ -143,10 +178,10 @@ `SUNAIVA_GATE_API_TOKEN`. Backend errors fail-OPEN per-rule (never blocks the

- **Constitutional immutability guards** — load-time re-merge plus write-time
rejection. The 32 constitutional rules cannot be disabled via `update_rules`
rejection. The 31 local rules cannot be disabled via `update_rules`
and cannot be bypassed via `log_bypass`, even if `~/.sunaiva/gate-config.json`
is hand-edited.
- **`--smoke-test` CLI flag** — pre-deployment self-check with three canned
evaluations (allow / block / block) and an explicit `Constitutional rules —
32` count line. Exit 0 = HEALTHY, 1 = DEGRADED, 5 = missing required files.
evaluations (allow / block / block) and an explicit `Local rules —
31` count line. Exit 0 = HEALTHY, 1 = DEGRADED, 5 = missing required files.
- **Bundle invariant tests** — `tests/bundle.test.ts` asserts the package ships
with exactly 32 constitutional rules (patterns intact) and 68 premium stubs
with exactly 31 local rules (patterns intact) and 69 premium stubs
(patterns replaced with `"[server-side]"`).

@@ -171,3 +206,3 @@ - **Audit ledger fields** — every entry now records `tier`, `audit_status`,

- **`DEFAULT_CONFIG.active_rules`** expanded from 5 constitutional IDs to all
32 — the package now boots with the full constitutional set active by default.
31 — the package now boots with the full local rule set active by default.
- **License model documented**: BUSL-1.1 wrapper, Change Date **2030-05-10**,

@@ -183,3 +218,3 @@ Change License **Apache-2.0**. The premium backend remains proprietary and is

- **C1** — `rules.json` now ships inside the npm tarball at `dist/rules/rules.json`
with all 32 constitutional patterns intact. Previous releases loaded from
with all 31 local rule patterns intact. Previous releases loaded from
`~/.sunaiva/rules.json` only, which the strip-patterns build step had emptied

@@ -210,3 +245,3 @@ to `"[server-side]"` placeholders on the install path.

- 19/19 ship-confidence-gate TypeScript port tests pass.
- Bundle invariant assertions confirm 32 constitutional rules + 68 premium
- Bundle invariant assertions confirm 31 local rules + 69 premium
stubs in the published tarball.

@@ -213,0 +248,0 @@

@@ -53,5 +53,5 @@ /**

// "[sunaiva-gate] premium rules skipped — set SUNAIVA_GATE_API_TOKEN to enable.
// See https://sunaivacore.io/pricing"
// See https://sunaiva.ai/products/gate"
console.error("[sunaiva-gate] premium rules skipped — set SUNAIVA_GATE_API_TOKEN to enable. " +
"See https://sunaivacore.io/pricing");
"See https://sunaiva.ai/products/gate");
}

@@ -202,3 +202,3 @@ /**

Authorization: `Bearer ${this.apiToken}`,
"User-Agent": "sunaiva-gate-client/1.1.0",
"User-Agent": "sunaiva-gate-client/1.1.5",
},

@@ -205,0 +205,0 @@ body: JSON.stringify({

@@ -1,1 +0,1 @@

{"version":3,"file":"backend-client.js","sourceRoot":"","sources":["../../src/engine/backend-client.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"backend-client.js","sourceRoot":"","sources":["../../src/engine/backend-client.ts"],"names":[],"mappings":"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"}

@@ -5,2 +5,3 @@ interface SessionState {

warnings_issued: Record<string, number>;
upsell_shown: boolean;
}

@@ -13,4 +14,15 @@ export declare function getState(): SessionState;

export declare function incrementAction(): void;
/**
* maybeEmitUpsellTrigger — emit a one-time stderr upsell notice when the
* session has evaluated 30+ actions and the notice has not yet been shown.
*
* Design constraints (v1.1.5):
* - FAIL-OPEN: any error in this function is swallowed — never crash the gate.
* - Skip silently when SUNAIVA_NUDGE_OFF=1 (reuses the nudge kill-switch).
* - Fires at most ONCE per session (gated by upsell_shown persisted to state file).
* - Written to stderr so it never pollutes JSON stdout / MCP protocol output.
*/
export declare function maybeEmitUpsellTrigger(): void;
export declare function resetState(): void;
export {};
//# sourceMappingURL=session-state.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/engine/session-state.ts"],"names":[],"mappings":"AAOA,UAAU,YAAY;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACzC;AAMD,wBAAgB,QAAQ,IAAI,YAAY,CAGvC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAI/C;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAGtD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}
{"version":3,"file":"session-state.d.ts","sourceRoot":"","sources":["../../src/engine/session-state.ts"],"names":[],"mappings":"AAOA,UAAU,YAAY;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,YAAY,EAAE,OAAO,CAAC;CACvB;AAMD,wBAAgB,QAAQ,IAAI,YAAY,CAGvC;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,YAAY,GAAG,IAAI,CAI/C;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAKpD;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAGtD;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAkB7C;AAED,wBAAgB,UAAU,IAAI,IAAI,CAEjC"}

@@ -7,3 +7,3 @@ import { readFileSync, writeFileSync } from "node:fs";

function defaultState() {
return { session_start: new Date().toISOString(), action_count: 0, warnings_issued: {} };
return { session_start: new Date().toISOString(), action_count: 0, warnings_issued: {}, upsell_shown: false };
}

@@ -42,2 +42,32 @@ export function getState() {

}
/**
* maybeEmitUpsellTrigger — emit a one-time stderr upsell notice when the
* session has evaluated 30+ actions and the notice has not yet been shown.
*
* Design constraints (v1.1.5):
* - FAIL-OPEN: any error in this function is swallowed — never crash the gate.
* - Skip silently when SUNAIVA_NUDGE_OFF=1 (reuses the nudge kill-switch).
* - Fires at most ONCE per session (gated by upsell_shown persisted to state file).
* - Written to stderr so it never pollutes JSON stdout / MCP protocol output.
*/
export function maybeEmitUpsellTrigger() {
try {
if (process.env.SUNAIVA_NUDGE_OFF === "1")
return;
const s = getState();
if (s.action_count < 30 || s.upsell_shown)
return;
process.stderr.write("\n[Sunaiva Gate] You've used 30+ constitutional rule checks this session. " +
"The premium tier adds 69 server-side rules (cross-provider decorrelation + " +
"Article 12 audit trail) + dashboard.\n" +
"Subscribe to Starter ($19/mo launch — through Aug 31, 2026): " +
"https://sunaiva.ai/products/gate\n" +
"This message will not appear again this session.\n\n");
s.upsell_shown = true;
saveState(s);
}
catch {
// fail-OPEN: upsell errors must never surface to the caller
}
}
export function resetState() {

@@ -44,0 +74,0 @@ saveState(defaultState());

@@ -1,1 +0,1 @@

{"version":3,"file":"session-state.js","sourceRoot":"","sources":["../../src/engine/session-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,oEAAoE;AACpE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,2BAA2B,CAAC,CAAC;AAQ/D,SAAS,YAAY;IACnB,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,CAAC;IAC7D,MAAM,CAAC;QAAC,OAAO,YAAY,EAAE,CAAC;IAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAe;IACvC,IAAI,CAAC;QACH,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC,CAAC,gEAAgE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,SAAS,CAAC,CAAC,CAAC,CAAC;IACb,OAAO,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,QAAQ,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,YAAY,EAAE,CAAC;IACjB,SAAS,CAAC,CAAC,CAAC,CAAC;AACf,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;AAC5B,CAAC"}
{"version":3,"file":"session-state.js","sourceRoot":"","sources":["../../src/engine/session-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,oEAAoE;AACpE,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,2BAA2B,CAAC,CAAC;AAS/D,SAAS,YAAY;IACnB,OAAO,EAAE,aAAa,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,eAAe,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;AAChH,CAAC;AAED,MAAM,UAAU,QAAQ;IACtB,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,CAAC;IAC7D,MAAM,CAAC;QAAC,OAAO,YAAY,EAAE,CAAC;IAAC,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,CAAe;IACvC,IAAI,CAAC;QACH,aAAa,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC,CAAC,gEAAgE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACjE,SAAS,CAAC,CAAC,CAAC,CAAC;IACb,OAAO,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAc;IAC5C,OAAO,QAAQ,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,YAAY,EAAE,CAAC;IACjB,SAAS,CAAC,CAAC,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG;YAAE,OAAO;QAClD,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;QACrB,IAAI,CAAC,CAAC,YAAY,GAAG,EAAE,IAAI,CAAC,CAAC,YAAY;YAAE,OAAO;QAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4EAA4E;YAC1E,6EAA6E;YAC7E,wCAAwC;YACxC,+DAA+D;YAC/D,oCAAoC;YACpC,sDAAsD,CACzD,CAAC;QACF,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC;QACtB,SAAS,CAAC,CAAC,CAAC,CAAC;IACf,CAAC;IAAC,MAAM,CAAC;QACP,4DAA4D;IAC9D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,SAAS,CAAC,YAAY,EAAE,CAAC,CAAC;AAC5B,CAAC"}

@@ -704,3 +704,3 @@ /**

reason: "free-tier approval token accepted",
upgrade_hint: "Free tier — no cryptographic proof. Upgrade to sunaiva-ship-confidence for signed verdicts: https://sunaivacore.io/products/ship-confidence",
upgrade_hint: "Free tier — no cryptographic proof. Upgrade to sunaiva-ship-confidence for signed verdicts: https://sunaiva.ai/products/gate",
});

@@ -707,0 +707,0 @@ await this.consumeToken(tokenPath);

@@ -1,1 +0,1 @@

{"version":3,"file":"ship-confidence-gate.js","sourceRoot":"","sources":["../../src/engine/ship-confidence-gate.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"ship-confidence-gate.js","sourceRoot":"","sources":["../../src/engine/ship-confidence-gate.ts"],"names":[],"mappings":"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"}

@@ -18,3 +18,3 @@ /**

const MARKER_DIR = join(homedir(), ".sunaiva-gate");
const DEFAULT_ENDPOINT = "https://sunaivacore.io/api/telemetry/first-run";
const DEFAULT_ENDPOINT = "https://api.sunaiva.ai/api/telemetry/first-run";
const TIMEOUT_MS = 2_000;

@@ -21,0 +21,0 @@ /**

@@ -59,3 +59,3 @@ /**

// In non-TTY mode write to stderr so the nudge does not break JSON output
process.stderr.write(`[sunaiva-gate] Register free at https://sunaivacore.io/gate/register ` +
process.stderr.write(`[sunaiva-gate] Register free at https://sunaiva.ai/products/gate ` +
`for the live rule feed + Shield-of-Health dashboard. ` +

@@ -65,3 +65,3 @@ `Skip with SUNAIVA_NUDGE_OFF=1.\n`);

else {
process.stdout.write(`\n[sunaiva-gate] Register free at https://sunaivacore.io/gate/register\n` +
process.stdout.write(`\n[sunaiva-gate] Register free at https://sunaiva.ai/products/gate\n` +
` for the live rule feed + Shield-of-Health dashboard.\n` +

@@ -68,0 +68,0 @@ ` Skip this message with: SUNAIVA_NUDGE_OFF=1\n\n`);

@@ -1,1 +0,1 @@

{"version":3,"file":"nudge.js","sourceRoot":"","sources":["../../src/identity/nudge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AACpD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,8CAA8C;IAC7D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,aAAa,CAAC,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG;YAAE,OAAO;QAClD,IAAI,eAAe,EAAE;YAAE,OAAO;QAC9B,wDAAwD;QACxD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1B,0EAA0E;YAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,uEAAuE;gBACrE,uDAAuD;gBACvD,kCAAkC,CACrC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,0EAA0E;gBACxE,0DAA0D;gBAC1D,mDAAmD,CACtD,CAAC;QACJ,CAAC;QACD,iBAAiB,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,6CAA6C;IAC/C,CAAC;AACH,CAAC"}
{"version":3,"file":"nudge.js","sourceRoot":"","sources":["../../src/identity/nudge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,eAAe,CAAC,CAAC;AACpD,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,OAAO,UAAU,CAAC,WAAW,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,8CAA8C;IAC7D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB;IAC/B,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,aAAa,CAAC,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,OAAO,CAAC,CAAC;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;IACjD,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc;IAC5B,IAAI,CAAC;QACH,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,GAAG;YAAE,OAAO;QAClD,IAAI,eAAe,EAAE;YAAE,OAAO;QAC9B,wDAAwD;QACxD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1B,0EAA0E;YAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,mEAAmE;gBACjE,uDAAuD;gBACvD,kCAAkC,CACrC,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sEAAsE;gBACpE,0DAA0D;gBAC1D,mDAAmD,CACtD,CAAC;QACJ,CAAC;QACD,iBAAiB,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,6CAA6C;IAC/C,CAAC;AACH,CAAC"}

@@ -13,3 +13,3 @@ /**

*/
const DEFAULT_RULES_ENDPOINT = "https://sunaivacore.io/api/rules/premium";
const DEFAULT_RULES_ENDPOINT = "https://api.sunaiva.ai/api/rules/premium";
const FETCH_TIMEOUT_MS = 10_000;

@@ -39,3 +39,3 @@ /**

"Accept": "application/json",
"X-Gate-Version": "1.1.4",
"X-Gate-Version": "1.1.6",
},

@@ -42,0 +42,0 @@ signal: controller.signal,

@@ -12,3 +12,3 @@ /**

*/
const DEFAULT_REGISTER_ENDPOINT = "https://sunaivacore.io/api/register";
const DEFAULT_REGISTER_ENDPOINT = "https://api.sunaiva.ai/api/register";
const REGISTER_TIMEOUT_MS = 5_000;

@@ -30,3 +30,3 @@ /**

headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email, source: "sunaiva-gate", version: "1.1.4" }),
body: JSON.stringify({ email, source: "sunaiva-gate", version: "1.1.6" }),
signal: controller.signal,

@@ -33,0 +33,0 @@ });

@@ -52,2 +52,44 @@ /**

/**
* emitObsEvent — send ONE authenticated, content-free validation event to the
* per-user events backend so it appears in the customer's Gate dashboard
* (activity chart / metrics / audit log).
*
* Privacy + safety posture (identical contract to emitEvaluation):
* - Content-free: tool + decision + rule_id + agent + session_id ONLY.
* NO command body, NO file content, NO file paths, NO prompt text.
* - Requires a per-user token: only fires when SUNAIVA_GATE_API_TOKEN is set
* (the token the customer receives on subscribe). No token → no-op.
* - Kill-switches: SUNAIVA_TELEMETRY_OFF=1 OR SUNAIVA_GATE_TELEMETRY=0 → no-op.
* - 2s timeout. FAIL-OPEN: all errors swallowed. NEVER throws, NEVER awaited
* in a blocking way (fire-and-forget). A telemetry hiccup must never delay
* or block a gate decision.
* - Endpoint overridable via SUNAIVA_OBS_ENDPOINT (staging/preview).
*/
export declare function emitObsEvent(ev: {
tool?: string;
decision: string;
rule_id?: string | null;
agent?: string | null;
session_id?: string | null;
event?: string | null;
reason?: string | null;
}): void;
/**
* emitObsEventAwaitable — same as emitObsEvent but RETURNS the in-flight promise
* so a short-lived caller (the `--mcp-bridge` path, which `process.exit`s per
* invocation) can `await` delivery before exiting. The internal 2s timeout
* still bounds it, and it NEVER rejects (fail-open). The verdict MUST already
* be printed before awaiting this so gate-decision latency is unaffected.
* No-op (resolves immediately) when disabled or no token.
*/
export declare function emitObsEventAwaitable(ev: {
tool?: string;
decision: string;
rule_id?: string | null;
agent?: string | null;
session_id?: string | null;
event?: string | null;
reason?: string | null;
}): Promise<void>;
/**
* emitFirstRunIfNeeded — fire a single anonymous "first_run" install event.

@@ -54,0 +96,0 @@ *

@@ -1,1 +0,1 @@

{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/identity/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkBH,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,IAAI,CAUP;AAuFD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CzE"}
{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../src/identity/telemetry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAkBH,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,eAAe,EAAE,MAAM,CAAC;IACxB,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB;IACpB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE;IAC3C,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,IAAI,CAUP;AA6CD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAAC,EAAE,EAAE;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,GAAG,IAAI,CAcP;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,EAAE,EAAE;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CAWhB;AA6FD;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CzE"}

@@ -24,3 +24,3 @@ /**

import { join } from "node:path";
const GATE_VERSION = "1.1.4";
const GATE_VERSION = "1.1.6";
const DEFAULT_TELEMETRY_ENDPOINT = "https://gate-telemetry.kinan-ae7.workers.dev/v1/events";

@@ -74,2 +74,91 @@ const TELEMETRY_TIMEOUT_MS = 2_000;

// ---------------------------------------------------------------------------
// Per-user observability emit (Phase-2 events backend → /v1/obs/events)
// ---------------------------------------------------------------------------
const DEFAULT_OBS_ENDPOINT = "https://mcp.sunaivacore.io/v1/obs/events";
const OBS_TIMEOUT_MS = 2_000;
/**
* emitObsEvent — send ONE authenticated, content-free validation event to the
* per-user events backend so it appears in the customer's Gate dashboard
* (activity chart / metrics / audit log).
*
* Privacy + safety posture (identical contract to emitEvaluation):
* - Content-free: tool + decision + rule_id + agent + session_id ONLY.
* NO command body, NO file content, NO file paths, NO prompt text.
* - Requires a per-user token: only fires when SUNAIVA_GATE_API_TOKEN is set
* (the token the customer receives on subscribe). No token → no-op.
* - Kill-switches: SUNAIVA_TELEMETRY_OFF=1 OR SUNAIVA_GATE_TELEMETRY=0 → no-op.
* - 2s timeout. FAIL-OPEN: all errors swallowed. NEVER throws, NEVER awaited
* in a blocking way (fire-and-forget). A telemetry hiccup must never delay
* or block a gate decision.
* - Endpoint overridable via SUNAIVA_OBS_ENDPOINT (staging/preview).
*/
export function emitObsEvent(ev) {
// Kill-switches always win.
if (process.env.SUNAIVA_TELEMETRY_OFF === "1")
return;
if (process.env.SUNAIVA_GATE_TELEMETRY === "0")
return;
const token = process.env.SUNAIVA_GATE_API_TOKEN;
if (!token)
return; // not connected → nothing to send
const tool = ev.tool && ev.tool.length > 0 ? ev.tool : "unknown";
// Fire-and-forget — do not await, do not block the gate.
void _sendObs(token, { ...ev, tool }).catch(() => {
// fail-open: swallow all errors
});
}
/**
* emitObsEventAwaitable — same as emitObsEvent but RETURNS the in-flight promise
* so a short-lived caller (the `--mcp-bridge` path, which `process.exit`s per
* invocation) can `await` delivery before exiting. The internal 2s timeout
* still bounds it, and it NEVER rejects (fail-open). The verdict MUST already
* be printed before awaiting this so gate-decision latency is unaffected.
* No-op (resolves immediately) when disabled or no token.
*/
export async function emitObsEventAwaitable(ev) {
if (process.env.SUNAIVA_TELEMETRY_OFF === "1")
return;
if (process.env.SUNAIVA_GATE_TELEMETRY === "0")
return;
const token = process.env.SUNAIVA_GATE_API_TOKEN;
if (!token)
return;
const tool = ev.tool && ev.tool.length > 0 ? ev.tool : "unknown";
try {
await _sendObs(token, { ...ev, tool });
}
catch {
// fail-open: swallow all errors
}
}
async function _sendObs(token, ev) {
const endpoint = process.env.SUNAIVA_OBS_ENDPOINT ?? DEFAULT_OBS_ENDPOINT;
const payload = {
tool: ev.tool,
decision: ev.decision,
rule_id: ev.rule_id ?? null,
agent: ev.agent ?? null,
session_id: ev.session_id ?? null,
event: ev.event ?? null,
reason: ev.reason ?? null,
ts: new Date().toISOString(),
};
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), OBS_TIMEOUT_MS);
try {
await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(payload),
signal: controller.signal,
});
}
finally {
clearTimeout(timer);
}
}
// ---------------------------------------------------------------------------
// Install-tracking layer (v1.1.4)

@@ -76,0 +165,0 @@ // ---------------------------------------------------------------------------

@@ -1,1 +0,1 @@

{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/identity/telemetry.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../src/identity/telemetry.ts"],"names":[],"mappings":"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"}

@@ -19,6 +19,7 @@ #!/usr/bin/env node

import { emitFirstRunIfNeeded } from "./identity/first-run.js";
import { emitObsEventAwaitable } from "./identity/telemetry.js";
import * as fs from "node:fs";
import * as path from "node:path";
import { fileURLToPath } from "node:url";
const PKG_VERSION = "1.1.4";
const PKG_VERSION = "1.1.8";
const __dirname = path.dirname(fileURLToPath(import.meta.url));

@@ -260,3 +261,3 @@ const server = new Server({ name: "sunaiva-gate", version: PKG_VERSION }, { capabilities: { tools: {} } });

MCP integration: add the command to your client's mcpServers config.
Docs: https://sunaivacore.io/products/gate
Docs: https://sunaiva.ai/products/gate
Support: support@sunaiva.ai`);

@@ -315,3 +316,16 @@ process.exit(0);

const verdict = await runBridge(raw, agentArg, PKG_VERSION);
// Verdict goes to stdout FIRST — gate-decision latency is never affected
// by telemetry. THEN await the per-user dashboard event (content-free,
// fail-open, bounded by a 2s internal timeout, no-op unless
// SUNAIVA_GATE_API_TOKEN is set). We await because this --mcp-bridge path
// process.exit()s per call, which would otherwise kill the in-flight POST.
console.log(JSON.stringify(verdict));
await emitObsEventAwaitable({
tool: verdict.tool,
decision: verdict.decision,
agent: verdict.source_agent,
session_id: verdict.session_id,
event: verdict.event,
reason: verdict.reason,
});
}

@@ -318,0 +332,0 @@ catch (err) {

@@ -1,1 +0,1 @@

{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAQA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GA6EpF"}
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAQA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;GAiFpF"}
import { evaluateActionAsync } from "../engine/rule-engine.js";
import { getConfig } from "../config/loader.js";
import { getWarningCounts, recordWarning } from "../engine/session-state.js";
import { getWarningCounts, recordWarning, incrementAction, maybeEmitUpsellTrigger } from "../engine/session-state.js";
import { appendAudit } from "./audit.js";

@@ -23,2 +23,5 @@ const PKG_VERSION = "1.1.1";

}
// Track evaluation count and fire the one-time freemium upsell trigger at 30+.
incrementAction();
maybeEmitUpsellTrigger();
const dryRun = process.env.SUNAIVA_GATE_DRY_RUN === "1";

@@ -25,0 +28,0 @@ const cfg = getConfig();

@@ -1,1 +0,1 @@

{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"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"}
{
"name": "@sunaiva/gate",
"version": "1.1.4",
"version": "1.1.8",
"description": "Sunaiva Gate MCP — enforcement layer for AI agent rules. Stop documenting rules your agents ignore. Start enforcing them.",

@@ -13,8 +13,21 @@ "main": "dist/index.js",

"dist/index.d.ts",
"dist/index.js.map",
"dist/index.d.ts.map",
"dist/bypass/**",
"dist/compliance/**",
"dist/config/**",
"dist/cost/**",
"dist/diff/**",
"dist/engine/**",
"dist/events/**",
"dist/explain/**",
"dist/identity/**",
"dist/installer/**",
"dist/paranoia/**",
"dist/rollback/**",
"dist/rules/**",
"dist/timelock/**",
"dist/tools/**",
"dist/types/**",
"dist/rules/**",
"dist/version-pin/**",
"README.md",

@@ -33,2 +46,3 @@ "CHANGELOG.md",

"verify-bundle": "node scripts/verify-bundle.js",
"verify-tarball-completeness": "node scripts/verify-tarball-completeness.js",
"prepack": "node scripts/verify-bundle.js",

@@ -35,0 +49,0 @@ "prepublishOnly": "npm run build && node scripts/verify-bundle.js",

@@ -15,3 +15,3 @@ # @sunaiva/gate — Free Safety Hook for AI Coding Agents

No signup. No API key. No DNS record. Just add it to your MCP config and the
32 free constitutional rules are active on the next tool call.
31 free local rules (23 constitutional + 8 recommended) are active on the next tool call.

@@ -35,3 +35,3 @@ ---

The free tier works entirely on your machine — no backend, no telemetry,
no external calls of any kind. It evaluates 32 constitutional rules locally
no external calls of any kind. It evaluates 31 local rules (23 constitutional + 8 recommended) locally
against pattern matching. It is not perfect. Some edge cases are unmapped.

@@ -74,4 +74,4 @@ The patterns improve with each release. We publish the miss reports and the

✓ Gate loaded — 100 rules
✓ Constitutional rules — 32 (cannot be disabled, enforced locally)
✓ Premium rules — 68 (require backend service)
✓ Constitutional rules — 31 local (23 constitutional + 8 recommended) (cannot be disabled, enforced locally)
✓ Premium rules — 69 server-side (require backend service)
✓ Live eval (git push origin main) — HARD block via gov-001

@@ -90,3 +90,3 @@ ✓ Live eval (rm -rf /) — HARD block via dat-001

The 32 constitutional rules are evaluated entirely on your machine using
The 31 local rules (23 constitutional + 8 recommended) are evaluated entirely on your machine using
keyword and pattern matching against the action text. They are split across

@@ -174,3 +174,3 @@ five categories.

The **one exception to fail-open**: the 32 constitutional rules evaluated
The **one exception to fail-open**: the 31 local rules evaluated
by the local engine exit with code `3` (internal error) or `4` (malformed

@@ -201,3 +201,3 @@ input) if the gate binary itself crashes on those paths. This is intentional

unblock one-shot legitimate actions.
- **Incomplete** — some attack patterns are not yet mapped. The 68 premium
- **Incomplete** — some attack patterns are not yet mapped. The 69 premium
rules cover more edge cases server-side; the free set is the foundation,

@@ -347,3 +347,3 @@ not the ceiling.

**Tier 1 — Free gate (now)**: 32 local constitutional rules. Fail-open
**Tier 1 — Free gate (now)**: 31 local rules (23 constitutional + 8 recommended). Fail-open
guarantee. Pattern coverage grows with every release. This is the floor.

@@ -350,0 +350,0 @@

+34
-18

@@ -14,6 +14,4 @@ # @sunaiva/gate

> **Status**: `1.1.0` "Foundation Release" — first publicly-supported release.
> Closes all 7 CRITICAL findings from the signed Ship-Confidence verdict on
> `1.0.1`. Full changelog: [`CHANGELOG.md`](./CHANGELOG.md). Roadmap that led
> here: [`ROADMAP_1_1_0.md`](./ROADMAP_1_1_0.md).
> **Status**: `1.1.5` "Freemium Monetization" — strip-patterns constitutional fix +
> per-session upsell trigger. Full changelog: [`CHANGELOG.md`](./CHANGELOG.md).

@@ -31,4 +29,4 @@ ---

# → ✓ Gate loaded — 100 rules
# → ✓ Constitutional rules — 32 (cannot be disabled, enforced locally)
# → ✓ Premium rules — 68 (require backend service)
# → ✓ Constitutional rules — 31 local (23 constitutional + 8 recommended) (cannot be disabled, enforced locally)
# → ✓ Premium rules — 69 server-side (require backend service)
# → Status: HEALTHY

@@ -41,3 +39,3 @@ # → Version: 1.1.0

That is the entire onboarding. The 32 constitutional rules are active on first
That is the entire onboarding. The 31 local rules are active on first
boot; no other configuration is required.

@@ -52,3 +50,3 @@

- **32 constitutional rules enforced locally** across five categories —
- **31 local rules (23 constitutional + 8 recommended) enforced locally** across five categories —
financial-safety, data-protection, action-governance, security, and

@@ -69,3 +67,3 @@ communication-safety. Detection patterns ship intact inside the package at

records `would_have_blocked: [...]` without ever blocking.
- **Constitutional immutability** — the 32 rules cannot be disabled via
- **Constitutional immutability** — the 31 local rules cannot be disabled via
`update_rules` and cannot be bypassed via `log_bypass`, even if

@@ -90,6 +88,6 @@ `~/.sunaiva/gate-config.json` is hand-edited (the loader re-merges on every

tier matrix in [`TIER_DEFINITIONS.md`](./TIER_DEFINITIONS.md). Current pricing
at **https://sunaivacore.io/pricing** (canonical source of truth across all
at **https://sunaiva.ai/products/gate** (canonical source of truth across all
Sunaiva Core products).
- **68 additional premium rules** (100 total) evaluated server-side via the
- **69 premium rules** (100 total) evaluated server-side via the
premium backend at `https://mcp.sunaivacore.io/v1/gatehooks`. Detection

@@ -137,7 +135,7 @@ patterns are proprietary and stay in our infrastructure.

│ │ │ │ │
│ │ ├─► Constitutional rules (32) — pattern matched │ │
│ │ ├─► Local rules (31) — pattern matched │ │
│ │ │ LOCALLY against dist/rules/rules.json │ │
│ │ │ ─────────────────────────────► block/warn │ │
│ │ │ │ │
│ │ └─► Premium rules (68) — only if backend set │ │
│ │ └─► Premium rules (69) — only if backend set │ │
│ │ POST https://mcp.sunaivacore.io/v1/gatehooks │ │

@@ -161,2 +159,20 @@ │ │ (JWT auth via SUNAIVA_GATE_API_TOKEN) │ │

## Sunaiva Gate vs. the Sunaiva Validation Engine
`@sunaiva/gate` is an **action-governance** product: it intercepts AI agent
tool calls at runtime and enforces constitutional hook rules with a
deterministic OR-logic engine (any matching rule blocks). It validates
**agent ACTIONS** — things the agent is about to do.
The **Sunaiva Validation Engine** at [sunaiva.ai](https://sunaiva.ai) is a
separate product that validates AI **OUTPUTS** — documents, reports, claims, and
decisions — via a multi-gate architecture with composite cryptographic binding.
These are complementary layers, not substitutes for each other.
The Sunaiva product family includes patent-pending validation technologies
(USPTO 64/006,491 family) — see [sunaiva.ai](https://sunaiva.ai) for the full
Validation Engine.
---
## MCP configuration

@@ -279,4 +295,4 @@

✓ Gate loaded — 100 rules
✓ Constitutional rules — 32 (cannot be disabled, enforced locally)
✓ Premium rules — 68 (require backend service)
✓ Constitutional rules — 31 local (23 constitutional + 8 recommended) (cannot be disabled, enforced locally)
✓ Premium rules — 69 server-side (require backend service)
✓ Presets file — 5 presets available

@@ -287,3 +303,3 @@ ✓ Live eval (git push origin main) — HARD block via gov-001

✓ Live eval (stripe.charges.create) — HARD block via fin-001
✓ Immutability guard — ACTIVE (32 constitutional rules pinned)
✓ Immutability guard — ACTIVE (31 local rules pinned)
✓ MCP server — ready (not started in smoke test)

@@ -355,3 +371,3 @@ Status: HEALTHY

This is the package's hard guarantee. The 32 constitutional rules are
This is the package's hard guarantee. The 31 local rules (23 constitutional + 8 recommended) are
re-merged into `active_rules` on every config load — even if

@@ -465,3 +481,3 @@ `~/.sunaiva/gate-config.json` is hand-edited to remove them — and:

| Commercial / paid tier | `support@sunaiva.ai` |
| Product page | `https://sunaivacore.io/products/gate` |
| Product page | `https://sunaiva.ai/products/gate` |

@@ -468,0 +484,0 @@ When reporting bugs, include the output of `npx @sunaiva/gate --smoke-test`

@@ -28,4 +28,4 @@ # Tier Definitions — `@sunaiva/gate`

- **Scope**:
- All 32 constitutional rules evaluated locally (cannot be disabled per the immutability guard)
- All 68 premium rule slots present but marked `[server-side]` placeholders (no evaluation — requires Pro+)
- All 31 local rules (23 constitutional + 8 recommended) evaluated locally (cannot be disabled per the immutability guard)
- All 69 premium rule slots present but marked `[server-side]` placeholders (no evaluation — requires Pro+)
- Local audit log at `~/.sunaiva/audit/audit.jsonl`

@@ -62,3 +62,3 @@ - 5 presets (Minimal / Essential / Developer-Safety / Financial-Protection / Full-Suite)

- **Higher metered validation budget**
- **All 68 premium rules** active
- **All 69 premium rules** active
- **5 connected agents** (any mix of Claude Code, Cursor, Windsurf, Copilot, Aider, Codex, Zed)

@@ -116,4 +116,4 @@ - **BYOK support** — bring your own Gemini / Anthropic / OpenRouter API key for the LLM portion of Gate 2 (semantic analysis); or stay on the included Managed Gemini Flash

|---|---|---|---|---|---|
| 32 constitutional rules (local) | ✓ | ✓ | ✓ | ✓ | ✓ |
| 68 premium rules (server-eval) | — | curated subset | All 68 | All 68 + custom | All 68 + custom |
| 31 local rules (23 constitutional + 8 recommended) | ✓ | ✓ | ✓ | ✓ | ✓ |
| 69 premium rules (server-eval) | — | curated subset | All 69 | All 69 + custom | All 69 + custom |
| Hosted dashboard | — | ✓ | ✓ | ✓ | ✓ (self-host option) |

@@ -120,0 +120,0 @@ | Validations / month | unmetered (local only) | metered | metered (higher) | metered (highest) | unlimited |