@adtl/gateway 0.5.1 → 0.7.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.
- package/README.md +152 -9
- package/dist/approvals.d.ts +22 -6
- package/dist/approvals.d.ts.map +1 -1
- package/dist/approvals.js +56 -26
- package/dist/approvals.js.map +1 -1
- package/dist/audit.d.ts +8 -0
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/auditCli.d.ts +2 -0
- package/dist/auditCli.d.ts.map +1 -1
- package/dist/auditCli.js +13 -10
- package/dist/auditCli.js.map +1 -1
- package/dist/cedar.d.ts +27 -0
- package/dist/cedar.d.ts.map +1 -0
- package/dist/cedar.js +134 -0
- package/dist/cedar.js.map +1 -0
- package/dist/cli.js +17 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +330 -21
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +74 -1
- package/dist/config.js.map +1 -1
- package/dist/elicitation.d.ts +25 -0
- package/dist/elicitation.d.ts.map +1 -0
- package/dist/elicitation.js +46 -0
- package/dist/elicitation.js.map +1 -0
- package/dist/gateway.d.ts +30 -5
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +96 -14
- package/dist/gateway.js.map +1 -1
- package/dist/hooks/claudeCode.d.ts +4 -0
- package/dist/hooks/claudeCode.d.ts.map +1 -1
- package/dist/hooks/claudeCode.js +8 -1
- package/dist/hooks/claudeCode.js.map +1 -1
- package/dist/hooks/run.d.ts.map +1 -1
- package/dist/hooks/run.js +6 -3
- package/dist/hooks/run.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/init/presets.d.ts.map +1 -1
- package/dist/init/presets.js +54 -0
- package/dist/init/presets.js.map +1 -1
- package/dist/invoker.d.ts +21 -1
- package/dist/invoker.d.ts.map +1 -1
- package/dist/invoker.js +19 -2
- package/dist/invoker.js.map +1 -1
- package/dist/ledgerCli.d.ts +1 -1
- package/dist/ledgerCli.d.ts.map +1 -1
- package/dist/ledgerCli.js +9 -3
- package/dist/ledgerCli.js.map +1 -1
- package/dist/ntfy.d.ts +3 -1
- package/dist/ntfy.d.ts.map +1 -1
- package/dist/ntfy.js +2 -1
- package/dist/ntfy.js.map +1 -1
- package/dist/playgroundCli.d.ts +8 -0
- package/dist/playgroundCli.d.ts.map +1 -0
- package/dist/playgroundCli.js +57 -0
- package/dist/playgroundCli.js.map +1 -0
- package/dist/receipt.d.ts +62 -0
- package/dist/receipt.d.ts.map +1 -0
- package/dist/receipt.js +117 -0
- package/dist/receipt.js.map +1 -0
- package/dist/receiptCli.d.ts +8 -0
- package/dist/receiptCli.d.ts.map +1 -0
- package/dist/receiptCli.js +87 -0
- package/dist/receiptCli.js.map +1 -0
- package/dist/roles.d.ts +9 -0
- package/dist/roles.d.ts.map +1 -0
- package/dist/roles.js +41 -0
- package/dist/roles.js.map +1 -0
- package/dist/startup.d.ts +14 -0
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +92 -7
- package/dist/startup.js.map +1 -1
- package/package.json +16 -4
- package/playground/fake-github.mjs +98 -0
- package/playground/fake-memory.mjs +130 -0
- package/playground/index.html +411 -0
- package/playground/playground.yaml +40 -0
- package/playground/server.mjs +290 -0
- package/src/approvals.ts +63 -26
- package/src/audit.ts +5 -0
- package/src/auditCli.ts +11 -8
- package/src/cedar.ts +140 -0
- package/src/cli.ts +16 -1
- package/src/config.ts +80 -1
- package/src/elicitation.ts +69 -0
- package/src/gateway.ts +108 -17
- package/src/hooks/claudeCode.ts +13 -2
- package/src/hooks/run.ts +6 -3
- package/src/index.ts +6 -0
- package/src/init/presets.ts +54 -0
- package/src/invoker.ts +39 -2
- package/src/ledgerCli.ts +9 -3
- package/src/ntfy.ts +4 -1
- package/src/playgroundCli.ts +60 -0
- package/src/receipt.ts +148 -0
- package/src/receiptCli.ts +85 -0
- package/src/roles.ts +55 -0
- package/src/startup.ts +88 -6
package/dist/ledgerCli.js
CHANGED
|
@@ -17,6 +17,7 @@ import { userInfo } from "node:os";
|
|
|
17
17
|
import { dirname, resolve } from "node:path";
|
|
18
18
|
import { parseConfigText } from "@adtl/interceptors";
|
|
19
19
|
import { Ledger, chunkHashes, defaultLedgerPath } from "@adtl/ledger";
|
|
20
|
+
import { defaultSigningKeyPath, loadSigner, trySigner } from "@adtl/labels";
|
|
20
21
|
export const LEDGER_USAGE = `Usage: adtl-gateway ledger stats [-c <adtl.yaml>]
|
|
21
22
|
adtl-gateway ledger verify [-c <adtl.yaml>]
|
|
22
23
|
adtl-gateway ledger declassify <file>... [-c <adtl.yaml>] --reason <text>
|
|
@@ -27,7 +28,8 @@ private data, and re-labels it when it is read back. It lives in
|
|
|
27
28
|
ledger.path from the config, else ADTL_LEDGER, else ~/.adtl/ledger.db.
|
|
28
29
|
|
|
29
30
|
stats Count entries.
|
|
30
|
-
verify Check that no entry was changed or removed
|
|
31
|
+
verify Check that no entry was changed or removed, and that signed
|
|
32
|
+
entries are signed by this machine's key (exit 1 if not).
|
|
31
33
|
declassify Clear the label of each file's current content. Check the
|
|
32
34
|
files first: after this, ADTL treats that content as clean.
|
|
33
35
|
--reason is required and kept in the ledger.
|
|
@@ -72,7 +74,10 @@ export async function runLedgerCommand(argv, env = process.env) {
|
|
|
72
74
|
path = resolve(dirname(abs), parsed.ledger.path);
|
|
73
75
|
retentionDays = parsed.ledger.retentionDays;
|
|
74
76
|
}
|
|
75
|
-
|
|
77
|
+
// Declassifying signs its entries; verifying only reads the key, to know whose signatures to trust.
|
|
78
|
+
const keyPath = defaultSigningKeyPath(env);
|
|
79
|
+
const signer = cmd === "declassify" ? trySigner(keyPath) : loadSigner(keyPath);
|
|
80
|
+
const ledger = new Ledger(path, { ...(retentionDays ? { retentionDays } : {}), ...(signer ? { signer } : {}) });
|
|
76
81
|
try {
|
|
77
82
|
if (cmd === "stats") {
|
|
78
83
|
const s = ledger.stats();
|
|
@@ -80,8 +85,9 @@ export async function runLedgerCommand(argv, env = process.env) {
|
|
|
80
85
|
}
|
|
81
86
|
if (cmd === "verify") {
|
|
82
87
|
const v = ledger.verify();
|
|
88
|
+
const sigs = v.signed ? `, ${v.signed} signed${v.unsigned ? `, ${v.unsigned} from before signing` : ""}` : "";
|
|
83
89
|
return v.ok
|
|
84
|
-
? { stdout: `${path}: ${v.entries} entries, chain intact`, exitCode: 0 }
|
|
90
|
+
? { stdout: `${path}: ${v.entries} entries${sigs}, chain intact`, exitCode: 0 }
|
|
85
91
|
: { stdout: `${path}: TAMPERED: ${v.problem}`, exitCode: 1 };
|
|
86
92
|
}
|
|
87
93
|
if (cmd === "declassified") {
|
package/dist/ledgerCli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ledgerCli.js","sourceRoot":"","sources":["../src/ledgerCli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"ledgerCli.js","sourceRoot":"","sources":["../src/ledgerCli.ts"],"names":[],"mappings":"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"}
|
package/dist/ntfy.d.ts
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import type { AnswerFn, ApprovalEvent, ApprovalRequest, Notifier } from "./approvals.js";
|
|
13
13
|
export interface NtfyOptions {
|
|
14
|
+
/** Channel name in approval results and logs. Default: "ntfy". */
|
|
15
|
+
name?: string;
|
|
14
16
|
/** Server base URL, e.g. https://ntfy.sh */
|
|
15
17
|
server: string;
|
|
16
18
|
topic: string;
|
|
@@ -25,7 +27,7 @@ export interface NtfyOptions {
|
|
|
25
27
|
publishAttempts?: number;
|
|
26
28
|
}
|
|
27
29
|
export declare class NtfyNotifier implements Notifier {
|
|
28
|
-
readonly name
|
|
30
|
+
readonly name: string;
|
|
29
31
|
private readonly server;
|
|
30
32
|
private readonly topic;
|
|
31
33
|
private readonly replyTopic;
|
package/dist/ntfy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy.d.ts","sourceRoot":"","sources":["../src/ntfy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEzF,MAAM,WAAW,WAAW;IAC1B,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,sGAAsG;IACtG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"ntfy.d.ts","sourceRoot":"","sources":["../src/ntfy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAEzF,MAAM,WAAW,WAAW;IAC1B,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,sGAAsG;IACtG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAOD,qBAAa,YAAa,YAAW,QAAQ;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqB;IAC3C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;gBAE7B,IAAI,EAAE,WAAW;IAW7B,OAAO,KAAK,IAAI,GAEf;IAEK,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCjD,2FAA2F;YAC7E,OAAO;IAgBf,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;YAkB9E,IAAI;CAoBnB"}
|
package/dist/ntfy.js
CHANGED
|
@@ -3,7 +3,7 @@ function describe(request) {
|
|
|
3
3
|
return `${request.reason}\n\nRule: ${request.matched.join(", ") || "default"}\nExpires in ${secs}s; no answer means deny.`;
|
|
4
4
|
}
|
|
5
5
|
export class NtfyNotifier {
|
|
6
|
-
name
|
|
6
|
+
name;
|
|
7
7
|
server;
|
|
8
8
|
topic;
|
|
9
9
|
replyTopic;
|
|
@@ -12,6 +12,7 @@ export class NtfyNotifier {
|
|
|
12
12
|
reconnectMs;
|
|
13
13
|
publishAttempts;
|
|
14
14
|
constructor(opts) {
|
|
15
|
+
this.name = opts.name ?? "ntfy";
|
|
15
16
|
this.server = opts.server.replace(/\/+$/, "");
|
|
16
17
|
this.topic = opts.topic;
|
|
17
18
|
this.replyTopic = opts.replyTopic ?? `${opts.topic}-reply`;
|
package/dist/ntfy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ntfy.js","sourceRoot":"","sources":["../src/ntfy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ntfy.js","sourceRoot":"","sources":["../src/ntfy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const PLAYGROUND_USAGE = "Usage: adtl-gateway playground [--port <n>] [--no-open]\n\nRuns the ADTL gateway in front of fake GitHub and memory servers, with a\nbrowser UI: three test cases, every call's label and decision, the session\nlabel, approvals, the config and the audit log. Nothing leaves your machine.\n\n --port <n> Port on 127.0.0.1 (default 4317; 0 picks a free one).\n --no-open Don't open the browser.";
|
|
2
|
+
export declare function parsePlaygroundArgs(argv: string[]): {
|
|
3
|
+
port: number;
|
|
4
|
+
open: boolean;
|
|
5
|
+
help: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare function runPlayground(argv: string[]): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=playgroundCli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playgroundCli.d.ts","sourceRoot":"","sources":["../src/playgroundCli.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB,kZAOU,CAAC;AAOxC,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAalG;AAYD,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAajE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adtl-gateway playground [--port 4317] [--no-open]`: the web playground, with
|
|
3
|
+
* the real gateway in front of fake GitHub and memory servers. Listens on
|
|
4
|
+
* 127.0.0.1 only and opens the browser unless --no-open is given.
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from "node:child_process";
|
|
7
|
+
export const PLAYGROUND_USAGE = `Usage: adtl-gateway playground [--port <n>] [--no-open]
|
|
8
|
+
|
|
9
|
+
Runs the ADTL gateway in front of fake GitHub and memory servers, with a
|
|
10
|
+
browser UI: three test cases, every call's label and decision, the session
|
|
11
|
+
label, approvals, the config and the audit log. Nothing leaves your machine.
|
|
12
|
+
|
|
13
|
+
--port <n> Port on 127.0.0.1 (default 4317; 0 picks a free one).
|
|
14
|
+
--no-open Don't open the browser.`;
|
|
15
|
+
export function parsePlaygroundArgs(argv) {
|
|
16
|
+
let port = 4317;
|
|
17
|
+
let open = true;
|
|
18
|
+
let help = false;
|
|
19
|
+
for (let i = 0; i < argv.length; i++) {
|
|
20
|
+
const a = argv[i];
|
|
21
|
+
if (a === "--port")
|
|
22
|
+
port = Number(argv[++i]);
|
|
23
|
+
else if (a === "--no-open")
|
|
24
|
+
open = false;
|
|
25
|
+
else if (a === "-h" || a === "--help")
|
|
26
|
+
help = true;
|
|
27
|
+
else
|
|
28
|
+
throw new Error(`Unknown argument: ${a}\n\n${PLAYGROUND_USAGE}`);
|
|
29
|
+
}
|
|
30
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535)
|
|
31
|
+
throw new Error(`--port must be a number from 0 to 65535\n\n${PLAYGROUND_USAGE}`);
|
|
32
|
+
return { port, open, help };
|
|
33
|
+
}
|
|
34
|
+
function openBrowser(url) {
|
|
35
|
+
const [cmd, args] = process.platform === "darwin" ? ["open", [url]] : process.platform === "win32" ? ["cmd", ["/c", "start", "", url]] : ["xdg-open", [url]];
|
|
36
|
+
try {
|
|
37
|
+
spawn(cmd, args, { stdio: "ignore", detached: true }).on("error", () => { }).unref();
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// No browser to open: the URL is printed anyway.
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export async function runPlayground(argv) {
|
|
44
|
+
const opts = parsePlaygroundArgs(argv);
|
|
45
|
+
if (opts.help)
|
|
46
|
+
return void console.log(PLAYGROUND_USAGE);
|
|
47
|
+
// Plain JavaScript shipped next to dist/, not compiled.
|
|
48
|
+
const mod = (await import(new URL("../playground/server.mjs", import.meta.url).href));
|
|
49
|
+
const pg = await mod.startPlayground({ port: opts.port });
|
|
50
|
+
console.log(`ADTL playground: ${pg.url} (Ctrl-C to stop)`);
|
|
51
|
+
if (opts.open)
|
|
52
|
+
openBrowser(pg.url);
|
|
53
|
+
for (const sig of ["SIGINT", "SIGTERM"]) {
|
|
54
|
+
process.once(sig, () => void pg.close().finally(() => process.exit(0)));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=playgroundCli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playgroundCli.js","sourceRoot":"","sources":["../src/playgroundCli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type Signer } from "@adtl/labels";
|
|
2
|
+
import { type AuditEntry } from "./audit.js";
|
|
3
|
+
export declare const RECEIPT_TYPE = "adtl.receipt.v1";
|
|
4
|
+
export interface ReceiptCall {
|
|
5
|
+
ts: string;
|
|
6
|
+
event: AuditEntry["event"];
|
|
7
|
+
server: string;
|
|
8
|
+
tool?: string;
|
|
9
|
+
resource?: string;
|
|
10
|
+
prompt?: string;
|
|
11
|
+
outcome: AuditEntry["outcome"];
|
|
12
|
+
decision?: string;
|
|
13
|
+
approver?: string;
|
|
14
|
+
callHash?: string;
|
|
15
|
+
/** Integrity and confidentiality of the result. */
|
|
16
|
+
label?: {
|
|
17
|
+
integrity: string;
|
|
18
|
+
confidentiality: string;
|
|
19
|
+
};
|
|
20
|
+
/** Hash of this call's audit log line. */
|
|
21
|
+
line: string;
|
|
22
|
+
}
|
|
23
|
+
export interface Receipt {
|
|
24
|
+
type: typeof RECEIPT_TYPE;
|
|
25
|
+
sessionId: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
counts: {
|
|
28
|
+
calls: number;
|
|
29
|
+
forwarded: number;
|
|
30
|
+
blocked: number;
|
|
31
|
+
asked: number;
|
|
32
|
+
upstreamErrors: number;
|
|
33
|
+
approved: number;
|
|
34
|
+
denied: number;
|
|
35
|
+
};
|
|
36
|
+
calls: ReceiptCall[];
|
|
37
|
+
/** Public key that signed it, `ed25519:…`. */
|
|
38
|
+
signer: string;
|
|
39
|
+
signature: string;
|
|
40
|
+
}
|
|
41
|
+
/** Sessions in the audit log, with their number of calls and last activity. */
|
|
42
|
+
export declare function listSessions(logPath: string): {
|
|
43
|
+
sessionId: string;
|
|
44
|
+
calls: number;
|
|
45
|
+
last: string;
|
|
46
|
+
}[];
|
|
47
|
+
/** Build and sign the receipt for `sessionId` from a verified audit log. */
|
|
48
|
+
export declare function buildReceipt(logPath: string, sessionId: string, signer: Signer, now?: Date): Receipt;
|
|
49
|
+
export interface ReceiptCheck {
|
|
50
|
+
ok: boolean;
|
|
51
|
+
problem?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check a receipt's signature, that it is signed by `trustedKey` if given,
|
|
55
|
+
* and, with `logPath`, that the log is intact and the receipt lists exactly
|
|
56
|
+
* the session's lines from its first call to its last.
|
|
57
|
+
*/
|
|
58
|
+
export declare function verifyReceipt(receipt: Receipt, opts?: {
|
|
59
|
+
logPath?: string;
|
|
60
|
+
trustedKey?: string;
|
|
61
|
+
}): ReceiptCheck;
|
|
62
|
+
//# sourceMappingURL=receipt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAeA,OAAO,EAAkC,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3E,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7D,eAAO,MAAM,YAAY,oBAAoB,CAAC;AAE9C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,KAAK,CAAC,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC;IACvD,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,OAAO,YAAY,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACvI,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,8CAA8C;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAcD,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CASlG;AAsBD,4EAA4E;AAC5E,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,GAAE,IAAiB,GAAG,OAAO,CAqBhH;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,YAAY,CAqBlH"}
|
package/dist/receipt.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session receipts: a signed summary of every call a session made through
|
|
3
|
+
* the gateway and the Claude Code hooks, built from the hash-chained audit log.
|
|
4
|
+
*
|
|
5
|
+
* Agents can misreport what they did; the audit log is written outside the
|
|
6
|
+
* model. A receipt names the session, lists each call (tool, outcome,
|
|
7
|
+
* decision, approver, call hash, result label, and the hash of its audit log
|
|
8
|
+
* line) with counts, and is signed with the machine's Ed25519 key. Anyone with
|
|
9
|
+
* the public key can check it, and with the log at hand, that it lists every
|
|
10
|
+
* line the session wrote between its first and last call.
|
|
11
|
+
*
|
|
12
|
+
* Receipts cover what crossed the gateway and the hooks, not everything the
|
|
13
|
+
* agent did. Arguments and results are never included.
|
|
14
|
+
*/
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
16
|
+
import { verifyCanonical, signCanonical } from "@adtl/labels";
|
|
17
|
+
import { verifyAuditLog } from "./audit.js";
|
|
18
|
+
export const RECEIPT_TYPE = "adtl.receipt.v1";
|
|
19
|
+
function chainedEntries(logPath) {
|
|
20
|
+
const v = verifyAuditLog(logPath);
|
|
21
|
+
if (!v.ok)
|
|
22
|
+
throw new Error(`${logPath}: the audit log was tampered with (${v.problem}); refusing to issue a receipt`);
|
|
23
|
+
return readFileSync(logPath, "utf8")
|
|
24
|
+
.split("\n")
|
|
25
|
+
.filter((l) => l.trim())
|
|
26
|
+
.map((l) => JSON.parse(l))
|
|
27
|
+
.filter((e) => typeof e.hash === "string" && typeof e.sessionId === "string");
|
|
28
|
+
}
|
|
29
|
+
/** Sessions in the audit log, with their number of calls and last activity. */
|
|
30
|
+
export function listSessions(logPath) {
|
|
31
|
+
const out = new Map();
|
|
32
|
+
for (const e of chainedEntries(logPath)) {
|
|
33
|
+
const s = out.get(e.sessionId) ?? { sessionId: e.sessionId, calls: 0, last: e.ts };
|
|
34
|
+
s.calls++;
|
|
35
|
+
if (e.ts > s.last)
|
|
36
|
+
s.last = e.ts;
|
|
37
|
+
out.set(e.sessionId, s);
|
|
38
|
+
}
|
|
39
|
+
return [...out.values()].sort((a, b) => b.last.localeCompare(a.last));
|
|
40
|
+
}
|
|
41
|
+
function receiptCall(e) {
|
|
42
|
+
const label = e.label;
|
|
43
|
+
return {
|
|
44
|
+
ts: e.ts,
|
|
45
|
+
event: e.event,
|
|
46
|
+
server: e.server,
|
|
47
|
+
...(e.tool !== undefined ? { tool: e.tool } : {}),
|
|
48
|
+
...(e.resource !== undefined ? { resource: e.resource } : {}),
|
|
49
|
+
...(e.prompt !== undefined ? { prompt: e.prompt } : {}),
|
|
50
|
+
outcome: e.outcome,
|
|
51
|
+
...(e.decision !== undefined ? { decision: e.decision } : {}),
|
|
52
|
+
...(e.approval?.approver !== undefined ? { approver: e.approval.approver } : {}),
|
|
53
|
+
...(typeof e.callHash === "string" ? { callHash: e.callHash } : {}),
|
|
54
|
+
...(typeof label?.integrity === "string" && typeof label.confidentiality === "string"
|
|
55
|
+
? { label: { integrity: label.integrity, confidentiality: label.confidentiality } }
|
|
56
|
+
: {}),
|
|
57
|
+
line: e.hash,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Build and sign the receipt for `sessionId` from a verified audit log. */
|
|
61
|
+
export function buildReceipt(logPath, sessionId, signer, now = new Date()) {
|
|
62
|
+
const entries = chainedEntries(logPath).filter((e) => e.sessionId === sessionId);
|
|
63
|
+
if (entries.length === 0)
|
|
64
|
+
throw new Error(`${logPath} has no entries for session ${sessionId}`);
|
|
65
|
+
const count = (f) => entries.filter(f).length;
|
|
66
|
+
const unsigned = {
|
|
67
|
+
type: RECEIPT_TYPE,
|
|
68
|
+
sessionId,
|
|
69
|
+
createdAt: now.toISOString(),
|
|
70
|
+
counts: {
|
|
71
|
+
calls: entries.length,
|
|
72
|
+
forwarded: count((e) => e.outcome === "forwarded"),
|
|
73
|
+
blocked: count((e) => e.outcome === "blocked"),
|
|
74
|
+
asked: count((e) => e.outcome === "asked"),
|
|
75
|
+
upstreamErrors: count((e) => e.outcome === "upstream_error"),
|
|
76
|
+
approved: count((e) => e.approval?.outcome === "approved"),
|
|
77
|
+
denied: count((e) => e.approval?.outcome === "denied"),
|
|
78
|
+
},
|
|
79
|
+
calls: entries.map(receiptCall),
|
|
80
|
+
signer: signer.publicKey,
|
|
81
|
+
};
|
|
82
|
+
return { ...unsigned, signature: signCanonical(signer, unsigned) };
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Check a receipt's signature, that it is signed by `trustedKey` if given,
|
|
86
|
+
* and, with `logPath`, that the log is intact and the receipt lists exactly
|
|
87
|
+
* the session's lines from its first call to its last.
|
|
88
|
+
*/
|
|
89
|
+
export function verifyReceipt(receipt, opts = {}) {
|
|
90
|
+
const { signature, ...unsigned } = receipt;
|
|
91
|
+
if (receipt.type !== RECEIPT_TYPE)
|
|
92
|
+
return { ok: false, problem: `not an ADTL receipt (type ${String(receipt.type)})` };
|
|
93
|
+
if (!verifyCanonical(receipt.signer, unsigned, signature))
|
|
94
|
+
return { ok: false, problem: "the signature doesn't match: the receipt was changed or forged" };
|
|
95
|
+
if (opts.trustedKey && receipt.signer !== opts.trustedKey)
|
|
96
|
+
return { ok: false, problem: `signed by ${receipt.signer}, not the expected key` };
|
|
97
|
+
if (!opts.logPath)
|
|
98
|
+
return { ok: true };
|
|
99
|
+
let entries;
|
|
100
|
+
try {
|
|
101
|
+
entries = chainedEntries(opts.logPath);
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return { ok: false, problem: err.message };
|
|
105
|
+
}
|
|
106
|
+
const lines = receipt.calls.map((c) => c.line);
|
|
107
|
+
const first = entries.findIndex((e) => e.hash === lines[0]);
|
|
108
|
+
const last = entries.findIndex((e) => e.hash === lines.at(-1));
|
|
109
|
+
if (first < 0 || last < 0)
|
|
110
|
+
return { ok: false, problem: "the log doesn't contain the receipt's calls" };
|
|
111
|
+
const logged = entries.slice(first, last + 1).filter((e) => e.sessionId === receipt.sessionId);
|
|
112
|
+
if (logged.length !== lines.length || logged.some((e, i) => e.hash !== lines[i])) {
|
|
113
|
+
return { ok: false, problem: "the receipt doesn't list exactly the session's calls in the log" };
|
|
114
|
+
}
|
|
115
|
+
return { ok: true };
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=receipt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receipt.js","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const RECEIPT_USAGE = "Usage: adtl-gateway receipt list [<log>] [-c <adtl.yaml>]\n adtl-gateway receipt <session> [<log>] [-c <adtl.yaml>] [-o <receipt.json>]\n adtl-gateway receipt verify <receipt.json> [--log <log>] [--key <ed25519:...>]\n adtl-gateway key\n\nA receipt is a signed summary of every call one session made through the\ngateway and the Claude Code hooks: tool, outcome, decision, approver, call\nhash, result label and the hash of each audit log line. It is built from the\nhash-chained audit log (gateway.audit) and signed with this machine's key\n(ADTL_SIGNING_KEY, or ~/.adtl/signing-key.pem).\n\n list Sessions in the log, newest first.\n verify Check the signature; with --log, also that the receipt lists every\n line the session wrote; with --key, who signed it (exit 1 if not).\n key Print this machine's public key, to give to whoever checks receipts.";
|
|
2
|
+
export interface ReceiptCommandResult {
|
|
3
|
+
stdout: string;
|
|
4
|
+
exitCode: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function runKeyCommand(env?: NodeJS.ProcessEnv): Promise<ReceiptCommandResult>;
|
|
7
|
+
export declare function runReceiptCommand(argv: string[], env?: NodeJS.ProcessEnv): Promise<ReceiptCommandResult>;
|
|
8
|
+
//# sourceMappingURL=receiptCli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receiptCli.d.ts","sourceRoot":"","sources":["../src/receiptCli.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,aAAa,o4BAcsD,CAAC;AAEjF,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,wBAAsB,aAAa,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAIvG;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA4C3H"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adtl-gateway receipt` and `adtl-gateway key`.
|
|
3
|
+
*
|
|
4
|
+
* adtl-gateway receipt list [<log>] [-c adtl.yaml]
|
|
5
|
+
* adtl-gateway receipt <session> [<log>] [-c adtl.yaml] [-o receipt.json]
|
|
6
|
+
* adtl-gateway receipt verify <receipt.json> [--log <log>] [--key ed25519:…]
|
|
7
|
+
* adtl-gateway key
|
|
8
|
+
*/
|
|
9
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
10
|
+
import { defaultSigningKeyPath, loadOrCreateSigner } from "@adtl/labels";
|
|
11
|
+
import { resolveAuditPath } from "./auditCli.js";
|
|
12
|
+
import { buildReceipt, listSessions, verifyReceipt } from "./receipt.js";
|
|
13
|
+
export const RECEIPT_USAGE = `Usage: adtl-gateway receipt list [<log>] [-c <adtl.yaml>]
|
|
14
|
+
adtl-gateway receipt <session> [<log>] [-c <adtl.yaml>] [-o <receipt.json>]
|
|
15
|
+
adtl-gateway receipt verify <receipt.json> [--log <log>] [--key <ed25519:...>]
|
|
16
|
+
adtl-gateway key
|
|
17
|
+
|
|
18
|
+
A receipt is a signed summary of every call one session made through the
|
|
19
|
+
gateway and the Claude Code hooks: tool, outcome, decision, approver, call
|
|
20
|
+
hash, result label and the hash of each audit log line. It is built from the
|
|
21
|
+
hash-chained audit log (gateway.audit) and signed with this machine's key
|
|
22
|
+
(ADTL_SIGNING_KEY, or ~/.adtl/signing-key.pem).
|
|
23
|
+
|
|
24
|
+
list Sessions in the log, newest first.
|
|
25
|
+
verify Check the signature; with --log, also that the receipt lists every
|
|
26
|
+
line the session wrote; with --key, who signed it (exit 1 if not).
|
|
27
|
+
key Print this machine's public key, to give to whoever checks receipts.`;
|
|
28
|
+
export async function runKeyCommand(env = process.env) {
|
|
29
|
+
const path = defaultSigningKeyPath(env);
|
|
30
|
+
const signer = loadOrCreateSigner(path);
|
|
31
|
+
return { stdout: `${signer.publicKey}\nkey id: ${signer.keyId}\nfile: ${path}`, exitCode: 0 };
|
|
32
|
+
}
|
|
33
|
+
export async function runReceiptCommand(argv, env = process.env) {
|
|
34
|
+
const [cmd, ...rest] = argv;
|
|
35
|
+
if (cmd === undefined || cmd === "-h" || cmd === "--help")
|
|
36
|
+
return { stdout: RECEIPT_USAGE, exitCode: 0 };
|
|
37
|
+
let config;
|
|
38
|
+
let out;
|
|
39
|
+
let log;
|
|
40
|
+
let key;
|
|
41
|
+
const args = [];
|
|
42
|
+
for (let i = 0; i < rest.length; i++) {
|
|
43
|
+
const a = rest[i];
|
|
44
|
+
if (a === "-c" || a === "--config")
|
|
45
|
+
config = rest[++i];
|
|
46
|
+
else if (a === "-o" || a === "--out")
|
|
47
|
+
out = rest[++i];
|
|
48
|
+
else if (a === "--log")
|
|
49
|
+
log = rest[++i];
|
|
50
|
+
else if (a === "--key")
|
|
51
|
+
key = rest[++i];
|
|
52
|
+
else if (a.startsWith("-"))
|
|
53
|
+
throw new Error(`Unknown argument: ${a}\n\n${RECEIPT_USAGE}`);
|
|
54
|
+
else
|
|
55
|
+
args.push(a);
|
|
56
|
+
}
|
|
57
|
+
if (cmd === "verify") {
|
|
58
|
+
if (args.length !== 1)
|
|
59
|
+
throw new Error(`receipt verify needs one receipt file\n\n${RECEIPT_USAGE}`);
|
|
60
|
+
const receipt = JSON.parse(await readFile(args[0], "utf8"));
|
|
61
|
+
const r = verifyReceipt(receipt, { ...(log ? { logPath: log } : {}), ...(key ? { trustedKey: key } : {}) });
|
|
62
|
+
if (!r.ok)
|
|
63
|
+
return { stdout: `${args[0]}: INVALID: ${r.problem}`, exitCode: 1 };
|
|
64
|
+
const checked = [`signed by ${receipt.signer}`, ...(key ? ["the expected key"] : []), ...(log ? ["matches the log"] : [])];
|
|
65
|
+
return { stdout: `${args[0]}: valid (${checked.join(", ")}): ${receipt.counts.calls} calls in session ${receipt.sessionId}`, exitCode: 0 };
|
|
66
|
+
}
|
|
67
|
+
if (cmd === "list") {
|
|
68
|
+
if (args.length > 1)
|
|
69
|
+
throw new Error(`Unexpected argument: ${args[1]}\n\n${RECEIPT_USAGE}`);
|
|
70
|
+
const path = await resolveAuditPath(args[0], config, RECEIPT_USAGE);
|
|
71
|
+
const sessions = listSessions(path);
|
|
72
|
+
if (sessions.length === 0)
|
|
73
|
+
return { stdout: `${path}: no sessions`, exitCode: 0 };
|
|
74
|
+
return { stdout: sessions.map((s) => `${s.last} ${s.sessionId} ${s.calls} call${s.calls === 1 ? "" : "s"}`).join("\n"), exitCode: 0 };
|
|
75
|
+
}
|
|
76
|
+
if (args.length > 1)
|
|
77
|
+
throw new Error(`Unexpected argument: ${args[1]}\n\n${RECEIPT_USAGE}`);
|
|
78
|
+
const path = await resolveAuditPath(args[0], config, RECEIPT_USAGE);
|
|
79
|
+
const receipt = buildReceipt(path, cmd, loadOrCreateSigner(defaultSigningKeyPath(env)));
|
|
80
|
+
const json = `${JSON.stringify(receipt, null, 2)}\n`;
|
|
81
|
+
if (out) {
|
|
82
|
+
await writeFile(out, json);
|
|
83
|
+
return { stdout: `${out}: receipt for ${receipt.counts.calls} calls in session ${cmd}`, exitCode: 0 };
|
|
84
|
+
}
|
|
85
|
+
return { stdout: json.trimEnd(), exitCode: 0 };
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=receiptCli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receiptCli.js","sourceRoot":"","sources":["../src/receiptCli.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAgB,MAAM,cAAc,CAAC;AAEvF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;gFAcmD,CAAC;AAOjF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,MAAyB,OAAO,CAAC,GAAG;IACtE,MAAM,IAAI,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,aAAa,MAAM,CAAC,KAAK,WAAW,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAChG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAc,EAAE,MAAyB,OAAO,CAAC,GAAG;IAC1F,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC5B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,QAAQ;QAAE,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACzG,IAAI,MAA0B,CAAC;IAC/B,IAAI,GAAuB,CAAC;IAC5B,IAAI,GAAuB,CAAC;IAC5B,IAAI,GAAuB,CAAC;IAC5B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACnB,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,UAAU;YAAE,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aAClD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,OAAO;YAAE,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACjD,IAAI,CAAC,KAAK,OAAO;YAAE,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACnC,IAAI,CAAC,KAAK,OAAO;YAAE,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;aACnC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,OAAO,aAAa,EAAE,CAAC,CAAC;;YACrF,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpB,CAAC;IAED,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,aAAa,EAAE,CAAC,CAAC;QACpG,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAE,EAAE,MAAM,CAAC,CAAY,CAAC;QACxE,MAAM,CAAC,GAAG,aAAa,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAC5G,IAAI,CAAC,CAAC,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QAC/E,MAAM,OAAO,GAAG,CAAC,aAAa,OAAO,CAAC,MAAM,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3H,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,YAAY,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,qBAAqB,OAAO,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC7I,CAAC;IAED,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,CAAC,CAAC,OAAO,aAAa,EAAE,CAAC,CAAC;QAC5F,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;QACpE,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;QAClF,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IAC1I,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,CAAC,CAAC,CAAC,OAAO,aAAa,EAAE,CAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,kBAAkB,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxF,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;IACrD,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3B,OAAO,EAAE,MAAM,EAAE,GAAG,GAAG,iBAAiB,OAAO,CAAC,MAAM,CAAC,KAAK,qBAAqB,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACxG,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AACjD,CAAC"}
|
package/dist/roles.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AuthorizationDecision, AuthorizationRequest, Authorizer } from "./authorizer.js";
|
|
2
|
+
import type { RoleConfig } from "./config.js";
|
|
3
|
+
export declare class RoleAuthorizer implements Authorizer {
|
|
4
|
+
readonly name = "roles";
|
|
5
|
+
private readonly roles;
|
|
6
|
+
constructor(roles: Record<string, RoleConfig>);
|
|
7
|
+
check(req: AuthorizationRequest): AuthorizationDecision;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=roles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.d.ts","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAU9C,qBAAa,cAAe,YAAW,UAAU;IAC/C,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;gBAE3B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC;IAU7C,KAAK,CAAC,GAAG,EAAE,oBAAoB,GAAG,qBAAqB;CAgBxD"}
|
package/dist/roles.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Role-based authorization from the config (`gateway.roles`):
|
|
3
|
+
*
|
|
4
|
+
* roles:
|
|
5
|
+
* maintainers: { members: [alice, bob], tools: ["github.*"] }
|
|
6
|
+
* readers: { members: ["*"], tools: ["github.read_*", "github.get_*"] }
|
|
7
|
+
*
|
|
8
|
+
* A call is allowed if a role the caller belongs to grants it: `tools` and
|
|
9
|
+
* `prompts` are `server.name` patterns (the same `*` wildcards as policy
|
|
10
|
+
* rules), `resources` are URI patterns. Everything else is denied. Members
|
|
11
|
+
* are principal ids; "*" means everyone, including an anonymous caller.
|
|
12
|
+
*/
|
|
13
|
+
import { globToRegExp } from "@adtl/labels";
|
|
14
|
+
export class RoleAuthorizer {
|
|
15
|
+
name = "roles";
|
|
16
|
+
roles;
|
|
17
|
+
constructor(roles) {
|
|
18
|
+
this.roles = Object.entries(roles).map(([name, r]) => ({
|
|
19
|
+
name,
|
|
20
|
+
members: new Set(r.members),
|
|
21
|
+
tools: r.tools.map(globToRegExp),
|
|
22
|
+
prompts: r.prompts.map(globToRegExp),
|
|
23
|
+
resources: r.resources.map(globToRegExp),
|
|
24
|
+
}));
|
|
25
|
+
}
|
|
26
|
+
check(req) {
|
|
27
|
+
const id = req.principal.id;
|
|
28
|
+
const [kind, what] = req.event === "tools/call"
|
|
29
|
+
? ["tools", `${req.server}.${req.tool}`]
|
|
30
|
+
: req.event === "prompts/get"
|
|
31
|
+
? ["prompts", `${req.server}.${req.prompt}`]
|
|
32
|
+
: ["resources", req.resource ?? ""];
|
|
33
|
+
const granted = this.roles.some((r) => (r.members.has("*") || (id !== undefined && r.members.has(id))) && r[kind].some((p) => p.test(what)));
|
|
34
|
+
if (granted)
|
|
35
|
+
return { allow: true };
|
|
36
|
+
const who = id ?? "an anonymous caller";
|
|
37
|
+
const noun = kind === "tools" ? "tool" : kind === "prompts" ? "prompt" : "resource";
|
|
38
|
+
return { allow: false, reason: `No role lets ${who} use the ${noun} ${what}` };
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=roles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"roles.js","sourceRoot":"","sources":["../src/roles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAY5C,MAAM,OAAO,cAAc;IAChB,IAAI,GAAG,OAAO,CAAC;IACP,KAAK,CAAiB;IAEvC,YAAY,KAAiC;QAC3C,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,IAAI;YACJ,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3B,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC;YAChC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;YACpC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,YAAY,CAAC;SACzC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAyB;QAC7B,MAAM,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAChB,GAAG,CAAC,KAAK,KAAK,YAAY;YACxB,CAAC,CAAE,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,IAAI,EAAE,CAAW;YACnD,CAAC,CAAC,GAAG,CAAC,KAAK,KAAK,aAAa;gBAC3B,CAAC,CAAE,CAAC,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAW;gBACvD,CAAC,CAAE,CAAC,WAAW,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAW,CAAC;QACrD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAC5G,CAAC;QACF,IAAI,OAAO;YAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACpC,MAAM,GAAG,GAAG,EAAE,IAAI,qBAAqB,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;QACpF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,GAAG,YAAY,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC;IACjF,CAAC;CACF"}
|
package/dist/startup.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
2
|
import { type AdtlConfig } from "@adtl/labels";
|
|
3
3
|
import { ApprovalBroker } from "./approvals.js";
|
|
4
|
+
import type { Authorizer, Principal } from "./authorizer.js";
|
|
4
5
|
import { type GatewayConfig, type Upstream } from "./config.js";
|
|
5
6
|
import { AdtlGateway, type GatewayLogger } from "./gateway.js";
|
|
6
7
|
export declare class GatewayConfigError extends Error {
|
|
@@ -19,6 +20,19 @@ export declare function bundledInterceptorsCli(): string;
|
|
|
19
20
|
export declare function connectUpstream(id: string, u: Upstream, baseDir: string): Promise<Client>;
|
|
20
21
|
/** Build the approval broker from `gateway.approvals`, or undefined if not configured. */
|
|
21
22
|
export declare function createApprovals(cfg: GatewayConfig, env: NodeJS.ProcessEnv, log: GatewayLogger): ApprovalBroker | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Check that every role a policy rule names under `approvers:` exists, has
|
|
25
|
+
* named members, and that each member has a channel in
|
|
26
|
+
* `gateway.approvals.approvers`. Returns each such role's members.
|
|
27
|
+
*/
|
|
28
|
+
export declare function approverRoles(labels: AdtlConfig, cfg: GatewayConfig): Map<string, string[]>;
|
|
29
|
+
/** `gateway.principal`, with `${VAR}` in its id expanded. */
|
|
30
|
+
export declare function gatewayPrincipal(cfg: GatewayConfig, env: NodeJS.ProcessEnv): Principal | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* The configured authorizers, in the order they are asked: roles, then cedar.
|
|
33
|
+
* Cedar files are read and parsed here, so a bad policy fails startup.
|
|
34
|
+
*/
|
|
35
|
+
export declare function gatewayAuthorizers(cfg: GatewayConfig, baseDir: string): Promise<Authorizer[]>;
|
|
22
36
|
/**
|
|
23
37
|
* Under Claude Code, which passes `CLAUDE_CODE_SESSION_ID` to stdio MCP
|
|
24
38
|
* servers, the gateway uses that id and keeps session labels in files, so the
|
package/dist/startup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,
|
|
1
|
+
{"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,EAAuC,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAGpF,OAAO,EAAE,cAAc,EAAiB,MAAM,gBAAgB,CAAC;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAML,KAAK,aAAa,EAElB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAmB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAKhF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAS3E;AAED,8GAA8G;AAC9G,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAqB/E;AAED,iDAAiD;AACjD,wBAAgB,sBAAsB,IAAI,MAAM,CAI/C;AAaD,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/F;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAwB1H;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAqB3F;AAED,6DAA6D;AAC7D,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,SAAS,GAAG,SAAS,CAMlG;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAWnG;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAGpG;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAO,GAC7D,OAAO,CAAC,cAAc,CAAC,CA2FzB"}
|