@adtl/gateway 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +61 -4
  2. package/dist/audit.d.ts +21 -0
  3. package/dist/audit.d.ts.map +1 -1
  4. package/dist/audit.js +137 -2
  5. package/dist/audit.js.map +1 -1
  6. package/dist/auditCli.d.ts +7 -0
  7. package/dist/auditCli.d.ts.map +1 -0
  8. package/dist/auditCli.js +54 -0
  9. package/dist/auditCli.js.map +1 -0
  10. package/dist/authorizer.d.ts +50 -0
  11. package/dist/authorizer.d.ts.map +1 -0
  12. package/dist/authorizer.js +15 -0
  13. package/dist/authorizer.js.map +1 -0
  14. package/dist/cli.js +12 -3
  15. package/dist/cli.js.map +1 -1
  16. package/dist/gateway.d.ts +12 -3
  17. package/dist/gateway.d.ts.map +1 -1
  18. package/dist/gateway.js +88 -15
  19. package/dist/gateway.js.map +1 -1
  20. package/dist/hooks/claudeCode.d.ts +1 -0
  21. package/dist/hooks/claudeCode.d.ts.map +1 -1
  22. package/dist/hooks/claudeCode.js +8 -1
  23. package/dist/hooks/claudeCode.js.map +1 -1
  24. package/dist/hooks/run.d.ts.map +1 -1
  25. package/dist/hooks/run.js +3 -2
  26. package/dist/hooks/run.js.map +1 -1
  27. package/dist/index.d.ts +2 -0
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -0
  30. package/dist/index.js.map +1 -1
  31. package/dist/invoker.d.ts +9 -6
  32. package/dist/invoker.d.ts.map +1 -1
  33. package/dist/invoker.js +11 -9
  34. package/dist/invoker.js.map +1 -1
  35. package/dist/ledgerCli.d.ts +1 -1
  36. package/dist/ledgerCli.d.ts.map +1 -1
  37. package/dist/ledgerCli.js +26 -6
  38. package/dist/ledgerCli.js.map +1 -1
  39. package/package.json +4 -4
  40. package/src/audit.ts +142 -2
  41. package/src/auditCli.ts +53 -0
  42. package/src/authorizer.ts +60 -0
  43. package/src/cli.ts +12 -3
  44. package/src/gateway.ts +95 -17
  45. package/src/hooks/claudeCode.ts +9 -2
  46. package/src/hooks/run.ts +3 -2
  47. package/src/index.ts +2 -0
  48. package/src/invoker.ts +24 -17
  49. package/src/ledgerCli.ts +22 -6
@@ -1 +1 @@
1
- {"version":3,"file":"invoker.js","sourceRoot":"","sources":["../src/invoker.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"invoker.js","sourceRoot":"","sources":["../src/invoker.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export declare const LEDGER_USAGE = "Usage: adtl-gateway ledger stats [-c <adtl.yaml>]\n adtl-gateway ledger verify [-c <adtl.yaml>]\n adtl-gateway ledger declassify <file>... [-c <adtl.yaml>] [--reason <text>]\n\nThe ledger remembers content written by sessions that had read untrusted or\nprivate data, and re-labels it when it is read back. It lives in\nledger.path from the config, else ADTL_LEDGER, else ~/.adtl/ledger.db.\n\n stats Count entries.\n verify Check that no entry was changed or removed (exit 1 if one was).\n declassify Clear the label of each file's current content. Check the\n files first: after this, ADTL treats that content as clean.";
1
+ export declare const LEDGER_USAGE = "Usage: adtl-gateway ledger stats [-c <adtl.yaml>]\n adtl-gateway ledger verify [-c <adtl.yaml>]\n adtl-gateway ledger declassify <file>... [-c <adtl.yaml>] --reason <text>\n adtl-gateway ledger declassified [-c <adtl.yaml>] [--limit <n>]\n\nThe ledger remembers content written by sessions that had read untrusted or\nprivate data, and re-labels it when it is read back. It lives in\nledger.path from the config, else ADTL_LEDGER, else ~/.adtl/ledger.db.\n\n stats Count entries.\n verify Check that no entry was changed or removed (exit 1 if one was).\n declassify Clear the label of each file's current content. Check the\n files first: after this, ADTL treats that content as clean.\n --reason is required and kept in the ledger.\n declassified List recent declassifications: when, who, what and why.";
2
2
  export interface LedgerCommandResult {
3
3
  stdout: string;
4
4
  exitCode: number;
@@ -1 +1 @@
1
- {"version":3,"file":"ledgerCli.d.ts","sourceRoot":"","sources":["../src/ledgerCli.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,YAAY,0pBAWiD,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+CzH"}
1
+ {"version":3,"file":"ledgerCli.d.ts","sourceRoot":"","sources":["../src/ledgerCli.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,YAAY,q2BAc+C,CAAC;AAEzE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAyDzH"}
package/dist/ledgerCli.js CHANGED
@@ -3,11 +3,14 @@
3
3
  *
4
4
  * adtl-gateway ledger stats [-c adtl.yaml]
5
5
  * adtl-gateway ledger verify [-c adtl.yaml]
6
- * adtl-gateway ledger declassify <file>... [-c adtl.yaml] [--reason <text>]
6
+ * adtl-gateway ledger declassify <file>... [-c adtl.yaml] --reason <text>
7
+ * adtl-gateway ledger declassified [-c adtl.yaml] [--limit <n>]
7
8
  *
8
9
  * `declassify` clears the label of each file's current content, after you've
9
10
  * checked it. It is meant to be run by a person; the Claude Code hook asks
10
- * before letting the agent run it.
11
+ * before letting the agent run it. The reason is required: declassifying is
12
+ * where taint tracking erodes, and the reason is what a later review reads.
13
+ * `declassified` lists recent declassifications for that review.
11
14
  */
12
15
  import { readFile } from "node:fs/promises";
13
16
  import { userInfo } from "node:os";
@@ -16,7 +19,8 @@ import { parseConfigText } from "@adtl/interceptors";
16
19
  import { Ledger, chunkHashes, defaultLedgerPath } from "@adtl/ledger";
17
20
  export const LEDGER_USAGE = `Usage: adtl-gateway ledger stats [-c <adtl.yaml>]
18
21
  adtl-gateway ledger verify [-c <adtl.yaml>]
19
- adtl-gateway ledger declassify <file>... [-c <adtl.yaml>] [--reason <text>]
22
+ adtl-gateway ledger declassify <file>... [-c <adtl.yaml>] --reason <text>
23
+ adtl-gateway ledger declassified [-c <adtl.yaml>] [--limit <n>]
20
24
 
21
25
  The ledger remembers content written by sessions that had read untrusted or
22
26
  private data, and re-labels it when it is read back. It lives in
@@ -25,11 +29,14 @@ ledger.path from the config, else ADTL_LEDGER, else ~/.adtl/ledger.db.
25
29
  stats Count entries.
26
30
  verify Check that no entry was changed or removed (exit 1 if one was).
27
31
  declassify Clear the label of each file's current content. Check the
28
- files first: after this, ADTL treats that content as clean.`;
32
+ files first: after this, ADTL treats that content as clean.
33
+ --reason is required and kept in the ledger.
34
+ declassified List recent declassifications: when, who, what and why.`;
29
35
  export async function runLedgerCommand(argv, env = process.env) {
30
36
  const [cmd, ...rest] = argv;
31
37
  let config;
32
38
  let reason;
39
+ let limit;
33
40
  const files = [];
34
41
  for (let i = 0; i < rest.length; i++) {
35
42
  const a = rest[i];
@@ -37,6 +44,8 @@ export async function runLedgerCommand(argv, env = process.env) {
37
44
  config = rest[++i];
38
45
  else if (a === "--reason")
39
46
  reason = rest[++i];
47
+ else if (a === "--limit")
48
+ limit = Number(rest[++i]);
40
49
  else if (a.startsWith("-"))
41
50
  throw new Error(`Unknown argument: ${a}\n\n${LEDGER_USAGE}`);
42
51
  else
@@ -44,10 +53,14 @@ export async function runLedgerCommand(argv, env = process.env) {
44
53
  }
45
54
  if (cmd === undefined || cmd === "-h" || cmd === "--help")
46
55
  return { stdout: LEDGER_USAGE, exitCode: 0 };
47
- if (!["stats", "verify", "declassify"].includes(cmd))
56
+ if (!["stats", "verify", "declassify", "declassified"].includes(cmd))
48
57
  throw new Error(`Unknown ledger command: ${cmd}\n\n${LEDGER_USAGE}`);
49
58
  if (cmd === "declassify" && files.length === 0)
50
59
  throw new Error(`declassify needs at least one file\n\n${LEDGER_USAGE}`);
60
+ if (cmd === "declassify" && !reason?.trim())
61
+ throw new Error(`declassify needs --reason: say why this content is safe\n\n${LEDGER_USAGE}`);
62
+ if (limit !== undefined && !(Number.isInteger(limit) && limit > 0))
63
+ throw new Error(`--limit must be a positive whole number\n\n${LEDGER_USAGE}`);
51
64
  if (cmd !== "declassify" && files.length > 0)
52
65
  throw new Error(`Unexpected argument: ${files[0]}\n\n${LEDGER_USAGE}`);
53
66
  let path = defaultLedgerPath(env);
@@ -71,10 +84,17 @@ export async function runLedgerCommand(argv, env = process.env) {
71
84
  ? { stdout: `${path}: ${v.entries} entries, chain intact`, exitCode: 0 }
72
85
  : { stdout: `${path}: TAMPERED: ${v.problem}`, exitCode: 1 };
73
86
  }
87
+ if (cmd === "declassified") {
88
+ const list = ledger.declassifications(limit);
89
+ if (list.length === 0)
90
+ return { stdout: `${path}: nothing declassified`, exitCode: 0 };
91
+ const rows = list.map((d) => `${d.ts} ${d.by} ${d.subject ?? "-"} ${d.chunks} chunk${d.chunks === 1 ? "" : "s"} ${d.reason ?? "(no reason given)"}`);
92
+ return { stdout: rows.join("\n"), exitCode: 0 };
93
+ }
74
94
  const by = `user:${userInfo().username}`;
75
95
  const lines = [];
76
96
  for (const f of files) {
77
- const n = ledger.declassify(chunkHashes(await readFile(resolve(f), "utf8")), by, reason);
97
+ const n = ledger.declassify(chunkHashes(await readFile(resolve(f), "utf8")), by, reason.trim(), f);
78
98
  lines.push(n ? `${f}: cleared ${n} labeled chunk${n === 1 ? "" : "s"}` : `${f}: nothing labeled`);
79
99
  }
80
100
  return { stdout: lines.join("\n"), exitCode: 0 };
@@ -1 +1 @@
1
- {"version":3,"file":"ledgerCli.js","sourceRoot":"","sources":["../src/ledgerCli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ledgerCli.js","sourceRoot":"","sources":["../src/ledgerCli.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adtl/gateway",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Experimental: MCP gateway that labels every tool result and blocks risky tool calls using ADTL trust labels",
5
5
  "keywords": [
6
6
  "mcp",
@@ -46,9 +46,9 @@
46
46
  "url": "https://github.com/probita-ai/adtl/issues"
47
47
  },
48
48
  "dependencies": {
49
- "@adtl/interceptors": "0.4.0",
50
- "@adtl/labels": "0.4.0",
51
- "@adtl/ledger": "0.4.0",
49
+ "@adtl/interceptors": "0.5.0",
50
+ "@adtl/labels": "0.5.0",
51
+ "@adtl/ledger": "0.5.0",
52
52
  "@modelcontextprotocol/sdk": "1.31.0",
53
53
  "nodemailer": "10.0.12",
54
54
  "yaml": "2.9.1",
package/src/audit.ts CHANGED
@@ -3,9 +3,21 @@
3
3
  *
4
4
  * Arguments and results are never written; the call is identified by its
5
5
  * hash, so the log can be shared without leaking the data it describes.
6
+ *
7
+ * Lines are hash-chained: each carries `prev` (the hash of the line before)
8
+ * and `hash` (over the canonical form of the line without `hash`), so
9
+ * `adtl-gateway audit verify` detects lines that were edited, removed,
10
+ * reordered or inserted. The gateway and the Claude Code hook (a new process
11
+ * per tool call) write the same file, so appends take a lock file
12
+ * (`<log>.lock`) to keep the chain from forking.
13
+ *
14
+ * The chain has no secret: an agent with shell access could rewrite the whole
15
+ * file consistently, and cutting lines off the end is not detected. Signed
16
+ * session receipts are planned for that.
6
17
  */
7
- import { appendFileSync, mkdirSync } from "node:fs";
18
+ import { closeSync, fstatSync, mkdirSync, openSync, readFileSync, readSync, statSync, unlinkSync, writeSync } from "node:fs";
8
19
  import { dirname } from "node:path";
20
+ import { digest, sha256Hex } from "@adtl/labels";
9
21
 
10
22
  export interface AuditEntry {
11
23
  ts: string;
@@ -24,6 +36,8 @@ export interface AuditEntry {
24
36
  decision?: string;
25
37
  /** Present when the gateway ran in audit mode: nothing was stopped or changed. */
26
38
  mode?: "audit";
39
+ /** Present when the authorizer denied the caller: which one, and why. In audit mode the call still ran. */
40
+ denied?: { by: string; reason: string };
27
41
  /** Present when a human was asked: outcome, channel, approver (if known) and wait time. */
28
42
  approval?: { outcome: string; channel?: string; approver?: string; waitedMs: number };
29
43
  reason?: string;
@@ -32,6 +46,8 @@ export interface AuditEntry {
32
46
  label?: unknown;
33
47
  /** Present when the label ledger recognized content in the result: how many chunks matched, and which sessions wrote them. */
34
48
  ledger?: unknown;
49
+ /** Present when the result carried record label stamps: how many, and which sessions wrote them. */
50
+ records?: unknown;
35
51
  sessionLabel?: unknown;
36
52
  warnings?: string[];
37
53
  durationMs: number;
@@ -41,14 +57,138 @@ export interface AuditSink {
41
57
  write(entry: AuditEntry): void;
42
58
  }
43
59
 
60
+ /** `prev` of the first line of a log. */
61
+ export const AUDIT_GENESIS = `sha256:${"0".repeat(64)}`;
62
+
63
+ const LOCK_TIMEOUT_MS = 5000;
64
+ /** A lock older than this was left by a process that died while holding it. */
65
+ const LOCK_STALE_MS = 10_000;
66
+
67
+ function sleepSync(ms: number): void {
68
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
69
+ }
70
+
71
+ function withLock<T>(lockPath: string, fn: () => T): T {
72
+ const deadline = Date.now() + LOCK_TIMEOUT_MS;
73
+ for (;;) {
74
+ try {
75
+ closeSync(openSync(lockPath, "wx"));
76
+ break;
77
+ } catch (err) {
78
+ if ((err as NodeJS.ErrnoException).code !== "EEXIST") throw err;
79
+ try {
80
+ if (Date.now() - statSync(lockPath).mtimeMs > LOCK_STALE_MS) unlinkSync(lockPath);
81
+ } catch {
82
+ // Released meanwhile; try again.
83
+ }
84
+ if (Date.now() > deadline) throw new Error(`Timed out waiting for the audit log lock ${lockPath}`);
85
+ sleepSync(5);
86
+ }
87
+ }
88
+ try {
89
+ return fn();
90
+ } finally {
91
+ try {
92
+ unlinkSync(lockPath);
93
+ } catch {
94
+ // Already gone.
95
+ }
96
+ }
97
+ }
98
+
99
+ /** Last line of the file (without its newline), and whether the file ends with one. */
100
+ function tail(fd: number): { line?: string; endsWithNewline: boolean } {
101
+ const size = fstatSync(fd).size;
102
+ if (size === 0) return { endsWithNewline: true };
103
+ const chunks: Buffer[] = [];
104
+ let pos = size;
105
+ let text = "";
106
+ while (pos > 0) {
107
+ const n = Math.min(65536, pos);
108
+ pos -= n;
109
+ const buf = Buffer.alloc(n);
110
+ readSync(fd, buf, 0, n, pos);
111
+ chunks.unshift(buf);
112
+ text = Buffer.concat(chunks).toString("utf8");
113
+ if (text.slice(0, -1).includes("\n")) break;
114
+ }
115
+ const endsWithNewline = text.endsWith("\n");
116
+ const body = endsWithNewline ? text.slice(0, -1) : text;
117
+ return { line: body.slice(body.lastIndexOf("\n") + 1), endsWithNewline };
118
+ }
119
+
120
+ /** Hash a line links to: its `hash`, or for lines written before the chain, the hash of the raw line. */
121
+ function linkHash(raw: string): string {
122
+ try {
123
+ const v = JSON.parse(raw) as { hash?: unknown };
124
+ if (typeof v.hash === "string") return v.hash;
125
+ } catch {
126
+ // Not JSON: link to the raw text.
127
+ }
128
+ return `sha256:${sha256Hex(raw)}`;
129
+ }
130
+
44
131
  export class JsonlAuditLog implements AuditSink {
45
132
  constructor(readonly path: string) {
46
133
  mkdirSync(dirname(path), { recursive: true });
47
134
  }
48
135
 
49
136
  write(entry: AuditEntry): void {
50
- appendFileSync(this.path, `${JSON.stringify(entry)}\n`, "utf8");
137
+ withLock(`${this.path}.lock`, () => {
138
+ const fd = openSync(this.path, "a+");
139
+ try {
140
+ const t = tail(fd);
141
+ const prev = t.line === undefined ? AUDIT_GENESIS : linkHash(t.line);
142
+ const chained = { ...entry, prev };
143
+ const line = JSON.stringify({ ...chained, hash: digest(chained) });
144
+ writeSync(fd, `${t.endsWithNewline ? "" : "\n"}${line}\n`);
145
+ } finally {
146
+ closeSync(fd);
147
+ }
148
+ });
149
+ }
150
+ }
151
+
152
+ export interface AuditVerifyResult {
153
+ ok: boolean;
154
+ /** Lines checked. */
155
+ lines: number;
156
+ /** Lines at the start written before the chain (ADTL 0.4 and earlier). */
157
+ unchained: number;
158
+ /** Hash of the last line: note it to detect lines cut off the end later. */
159
+ last?: string;
160
+ problem?: string;
161
+ }
162
+
163
+ /** Check every line's hash and its link to the line before. */
164
+ export function verifyAuditLog(path: string): AuditVerifyResult {
165
+ const lines = readFileSync(path, "utf8").split("\n");
166
+ if (lines.at(-1) === "") lines.pop();
167
+ let prev = AUDIT_GENESIS;
168
+ let unchained = 0;
169
+ let chained = false;
170
+ for (const [i, raw] of lines.entries()) {
171
+ const n = i + 1;
172
+ const fail = (problem: string): AuditVerifyResult => ({ ok: false, lines: n, unchained, problem: `line ${n} ${problem}` });
173
+ let v: Record<string, unknown>;
174
+ try {
175
+ v = JSON.parse(raw) as Record<string, unknown>;
176
+ } catch {
177
+ return fail("is not valid JSON");
178
+ }
179
+ const { hash, ...rest } = v;
180
+ if (typeof hash !== "string") {
181
+ if (chained) return fail("has no hash: it was inserted or edited");
182
+ unchained++;
183
+ prev = linkHash(raw);
184
+ continue;
185
+ }
186
+ chained = true;
187
+ if (rest.prev !== prev) return fail(`doesn't follow line ${n - 1 || "(start)"}: a line was removed, reordered or inserted`);
188
+ if (digest(rest) !== hash) return fail("was changed after it was written");
189
+ prev = hash;
51
190
  }
191
+ return { ok: true, lines: lines.length, unchained, ...(lines.length ? { last: prev } : {}) };
52
192
  }
53
193
 
54
194
  export class MemoryAuditLog implements AuditSink {
@@ -0,0 +1,53 @@
1
+ /**
2
+ * `adtl-gateway audit`: check the audit log by hand.
3
+ *
4
+ * adtl-gateway audit verify [<file>] [-c adtl.yaml]
5
+ *
6
+ * Without a file, the log is `gateway.audit` from the config.
7
+ */
8
+ import { readFile } from "node:fs/promises";
9
+ import { dirname, resolve } from "node:path";
10
+ import { parse as parseYaml } from "yaml";
11
+ import { verifyAuditLog } from "./audit.js";
12
+
13
+ export const AUDIT_USAGE = `Usage: adtl-gateway audit verify [<file>] [-c <adtl.yaml>]
14
+
15
+ The audit log is hash-chained. verify checks that no line was edited,
16
+ removed, reordered or inserted (exit 1 if one was), and prints the hash of
17
+ the last line. Lines cut off the end are not detected; note that hash
18
+ somewhere else if you need to check later. Without <file>, the log is
19
+ gateway.audit from the config.`;
20
+
21
+ export interface AuditCommandResult {
22
+ stdout: string;
23
+ exitCode: number;
24
+ }
25
+
26
+ export async function runAuditCommand(argv: string[]): Promise<AuditCommandResult> {
27
+ const [cmd, ...rest] = argv;
28
+ let config: string | undefined;
29
+ const files: string[] = [];
30
+ for (let i = 0; i < rest.length; i++) {
31
+ const a = rest[i]!;
32
+ if (a === "-c" || a === "--config") config = rest[++i];
33
+ else if (a.startsWith("-")) throw new Error(`Unknown argument: ${a}\n\n${AUDIT_USAGE}`);
34
+ else files.push(a);
35
+ }
36
+ if (cmd === undefined || cmd === "-h" || cmd === "--help") return { stdout: AUDIT_USAGE, exitCode: 0 };
37
+ if (cmd !== "verify") throw new Error(`Unknown audit command: ${cmd}\n\n${AUDIT_USAGE}`);
38
+ if (files.length > 1) throw new Error(`Unexpected argument: ${files[1]}\n\n${AUDIT_USAGE}`);
39
+
40
+ let path = files[0] && resolve(files[0]);
41
+ if (!path) {
42
+ if (!config) throw new Error(`Give the audit log file, or -c <adtl.yaml> with gateway.audit set\n\n${AUDIT_USAGE}`);
43
+ const abs = resolve(config);
44
+ const gw = ((parseYaml(await readFile(abs, "utf8")) ?? {}) as { gateway?: { audit?: unknown } }).gateway ?? {};
45
+ if (typeof gw.audit !== "string") throw new Error(`${config} has no gateway.audit`);
46
+ path = resolve(dirname(abs), gw.audit);
47
+ }
48
+
49
+ const v = verifyAuditLog(path);
50
+ if (!v.ok) return { stdout: `${path}: TAMPERED: ${v.problem}`, exitCode: 1 };
51
+ const before = v.unchained ? ` (${v.unchained} written before the chain)` : "";
52
+ return { stdout: `${path}: ${v.lines} lines${before}, chain intact${v.last ? `\nlast: ${v.last}` : ""}`, exitCode: 0 };
53
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Authorization: may this caller use this tool, resource or prompt at all?
3
+ *
4
+ * Labels and the policy answer "may this call run, given what the session has
5
+ * seen?". An Authorizer answers the question before it, from who is calling.
6
+ * The gateway asks it on every tools/call, resources/read and prompts/get,
7
+ * before the request interceptors run, and the stricter answer wins: a denial
8
+ * stops the call whatever the policy would say, and an allow still leaves the
9
+ * call to the policy.
10
+ *
11
+ * The caller is the SEP-2624 `context.principal` the gateway passes to the
12
+ * interceptors. Over stdio that is whoever started the gateway (anonymous
13
+ * unless configured); authenticated transports can fill it in per request.
14
+ *
15
+ * An authorizer that throws denies the call (fails closed). In audit mode
16
+ * denials are logged and not enforced, like policy decisions.
17
+ */
18
+ import type { InvocationContext } from "@adtl/interceptors";
19
+
20
+ export type Principal = NonNullable<InvocationContext["principal"]>;
21
+
22
+ export interface AuthorizationRequest {
23
+ principal: Principal;
24
+ event: "tools/call" | "resources/read" | "prompts/get";
25
+ /** Upstream server id, as named in the config. */
26
+ server: string;
27
+ /** Exactly one of tool, resource or prompt is set, matching `event`. */
28
+ tool?: string;
29
+ resource?: string;
30
+ prompt?: string;
31
+ /** Tool or prompt arguments, for authorizers that decide on them. */
32
+ arguments?: Record<string, unknown>;
33
+ }
34
+
35
+ export type AuthorizationDecision = { allow: true } | { allow: false; reason: string };
36
+
37
+ export interface Authorizer {
38
+ /** Shown in audit entries and error messages, e.g. "rbac". */
39
+ readonly name: string;
40
+ check(request: AuthorizationRequest): AuthorizationDecision | Promise<AuthorizationDecision>;
41
+ }
42
+
43
+ /** A denial: which authorizer said no, and why. */
44
+ export interface Denial {
45
+ by: string;
46
+ reason: string;
47
+ }
48
+
49
+ /** Ask `authorizer`, failing closed. Returns the denial, or undefined if allowed. */
50
+ export async function authorize(authorizer: Authorizer, request: AuthorizationRequest): Promise<Denial | undefined> {
51
+ let d: AuthorizationDecision;
52
+ try {
53
+ d = await authorizer.check(request);
54
+ } catch (err) {
55
+ return { by: authorizer.name, reason: `${authorizer.name} failed: ${err instanceof Error ? err.message : String(err)}` };
56
+ }
57
+ if (d?.allow === true) return undefined;
58
+ const reason = d && "reason" in d && typeof d.reason === "string" && d.reason ? d.reason : `${authorizer.name} denied the call`;
59
+ return { by: authorizer.name, reason };
60
+ }
package/src/cli.ts CHANGED
@@ -6,7 +6,8 @@
6
6
  * adtl-gateway --config adtl.yaml [--audit]
7
7
  * adtl-gateway init --config adtl.yaml [--from .mcp.json] [--write]
8
8
  * adtl-gateway hook --config adtl.yaml [--gateway-server adtl]
9
- * adtl-gateway ledger stats|verify|declassify <file>
9
+ * adtl-gateway ledger stats|verify|declassify|declassified
10
+ * adtl-gateway audit verify [<file>]
10
11
  *
11
12
  * Point your MCP client (e.g. Claude Code's .mcp.json) at this command.
12
13
  * Logs go to stderr; stdout carries MCP JSON-RPC only.
@@ -14,6 +15,7 @@
14
15
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
16
  import { EnvExpansionError } from "./config.js";
16
17
  import { GATEWAY_VERSION } from "./gateway.js";
18
+ import { runAuditCommand } from "./auditCli.js";
17
19
  import { runHook } from "./hooks/run.js";
18
20
  import { runLedgerCommand } from "./ledgerCli.js";
19
21
  import { runInit, type InitResult } from "./init/run.js";
@@ -22,7 +24,8 @@ import { GatewayConfigError, loadGatewayConfig, startGateway } from "./startup.j
22
24
  const USAGE = `Usage: adtl-gateway --config <adtl.yaml> [--audit]
23
25
  adtl-gateway init --config <adtl.yaml> [--from <.mcp.json>] [--write]
24
26
  adtl-gateway hook --config <adtl.yaml> [--gateway-server <name>]
25
- adtl-gateway ledger stats|verify|declassify <file> (see: adtl-gateway ledger --help)
27
+ adtl-gateway ledger stats|verify|declassify|declassified (see: adtl-gateway ledger --help)
28
+ adtl-gateway audit verify [<file>] (see: adtl-gateway audit --help)
26
29
 
27
30
  Runs an MCP server over stdio that forwards tool calls to the upstream
28
31
  servers in the config, checking and labeling each call with ADTL.
@@ -95,6 +98,12 @@ async function main(): Promise<void> {
95
98
  process.exitCode = r.exitCode;
96
99
  return;
97
100
  }
101
+ if (process.argv[2] === "audit") {
102
+ const r = await runAuditCommand(process.argv.slice(3));
103
+ console.log(r.stdout);
104
+ process.exitCode = r.exitCode;
105
+ return;
106
+ }
98
107
  const args = parseArgs(process.argv.slice(2));
99
108
  // --help and --version print to stdout and exit; MCP is never served in these modes.
100
109
  if (args.help) return void console.log(USAGE);
@@ -181,7 +190,7 @@ async function init(path: string, write: boolean, from?: string): Promise<void>
181
190
  }
182
191
 
183
192
  main().catch((err: unknown) => {
184
- const known = err instanceof GatewayConfigError || err instanceof EnvExpansionError || process.argv[2] === "ledger";
193
+ const known = err instanceof GatewayConfigError || err instanceof EnvExpansionError || ["ledger", "audit"].includes(process.argv[2] ?? "");
185
194
  console.error(known ? `[adtl-gateway] ${(err as Error).message}` : err);
186
195
  // For Claude Code hooks only exit code 2 stops the call; any other code lets it run.
187
196
  process.exit(process.argv[2] === "hook" ? 2 : 1);