@adtl/gateway 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +143 -11
- package/dist/audit.d.ts +3 -1
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/cli.js +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +167 -713
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +64 -7
- package/dist/config.js.map +1 -1
- package/dist/elicitation.d.ts +7 -1
- package/dist/elicitation.d.ts.map +1 -1
- package/dist/elicitation.js +21 -14
- package/dist/elicitation.js.map +1 -1
- package/dist/gateway.d.ts +11 -1
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +13 -5
- package/dist/gateway.js.map +1 -1
- package/dist/hooks/agentLinks.d.ts +18 -0
- package/dist/hooks/agentLinks.d.ts.map +1 -0
- package/dist/hooks/agentLinks.js +48 -0
- package/dist/hooks/agentLinks.js.map +1 -0
- package/dist/hooks/claudeCode.d.ts +4 -0
- package/dist/hooks/claudeCode.d.ts.map +1 -1
- package/dist/hooks/claudeCode.js +35 -8
- package/dist/hooks/claudeCode.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/run.d.ts.map +1 -1
- package/dist/hooks/run.js +5 -2
- package/dist/hooks/run.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/init/suggest.d.ts +3 -1
- package/dist/init/suggest.d.ts.map +1 -1
- package/dist/init/suggest.js +8 -0
- package/dist/init/suggest.js.map +1 -1
- package/dist/invoker.d.ts +56 -6
- package/dist/invoker.d.ts.map +1 -1
- package/dist/invoker.js +121 -19
- package/dist/invoker.js.map +1 -1
- package/dist/openfga.d.ts +13 -0
- package/dist/openfga.d.ts.map +1 -0
- package/dist/openfga.js +101 -0
- package/dist/openfga.js.map +1 -0
- package/dist/startup.d.ts +10 -1
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +82 -11
- package/dist/startup.js.map +1 -1
- package/dist/totp.d.ts +42 -0
- package/dist/totp.d.ts.map +1 -0
- package/dist/totp.js +176 -0
- package/dist/totp.js.map +1 -0
- package/dist/totpCli.d.ts +11 -0
- package/dist/totpCli.d.ts.map +1 -0
- package/dist/totpCli.js +46 -0
- package/dist/totpCli.js.map +1 -0
- package/package.json +8 -7
- package/playground/server.mjs +13 -3
- package/src/audit.ts +3 -1
- package/src/cli.ts +10 -1
- package/src/config.ts +71 -7
- package/src/elicitation.ts +35 -17
- package/src/gateway.ts +18 -5
- package/src/hooks/agentLinks.ts +58 -0
- package/src/hooks/claudeCode.ts +40 -9
- package/src/hooks/index.ts +1 -0
- package/src/hooks/run.ts +5 -2
- package/src/index.ts +3 -0
- package/src/init/suggest.ts +10 -1
- package/src/invoker.ts +153 -21
- package/src/openfga.ts +101 -0
- package/src/startup.ts +79 -11
- package/src/totp.ts +191 -0
- package/src/totpCli.ts +52 -0
- package/src/types/qrcode-terminal.d.ts +4 -0
package/dist/invoker.js
CHANGED
|
@@ -1,38 +1,116 @@
|
|
|
1
1
|
import { DECISION_INFO_KEY, INVOKE_METHOD, LIST_METHOD, } from "@adtl/interceptors";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
const AnyResult = z.object({}).passthrough();
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* Untyped request: interceptor methods are extension methods the SDK does not type.
|
|
6
|
+
* The timeout is enforced here too, so a client that ignores it can't hang a phase.
|
|
7
|
+
*/
|
|
5
8
|
function request(client, method, params, timeout) {
|
|
6
9
|
const r = client.request;
|
|
7
|
-
|
|
10
|
+
const controller = new AbortController();
|
|
11
|
+
let timer;
|
|
12
|
+
const expired = new Promise((_, reject) => {
|
|
13
|
+
timer = setTimeout(() => {
|
|
14
|
+
controller.abort();
|
|
15
|
+
reject(new Error(`timed out after ${timeout} ms`));
|
|
16
|
+
}, timeout);
|
|
17
|
+
});
|
|
18
|
+
return Promise.race([r.call(client, { method, params }, AnyResult, { timeout, signal: controller.signal }), expired]).finally(() => clearTimeout(timer));
|
|
8
19
|
}
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
/** SEP-2624 `resolvePriority`: the override's hint, else the interceptor's. */
|
|
21
|
+
export function resolvePriority(def, overrides, phase) {
|
|
22
|
+
const p = overrides?.priorityHint ?? def.priorityHint;
|
|
11
23
|
if (p === undefined)
|
|
12
24
|
return 0;
|
|
13
25
|
if (typeof p === "number")
|
|
14
26
|
return p;
|
|
15
27
|
return p[phase] ?? 0;
|
|
16
28
|
}
|
|
17
|
-
function hooks
|
|
18
|
-
return
|
|
29
|
+
function matches(hooks, event, phase) {
|
|
30
|
+
return hooks.some((h) => h.phase === phase && (h.events.includes(event) || h.events.includes("*")));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Problems with `overrides` for these interceptors: an unknown name, or hooks
|
|
34
|
+
* that widen what the interceptor declares (which SEP-2624 says to reject).
|
|
35
|
+
*/
|
|
36
|
+
export function checkOverrides(defs, overrides) {
|
|
37
|
+
const problems = [];
|
|
38
|
+
for (const [name, o] of Object.entries(overrides)) {
|
|
39
|
+
const def = defs.find((d) => d.name === name);
|
|
40
|
+
if (!def) {
|
|
41
|
+
problems.push(`${name}: no such interceptor (offered: ${defs.map((d) => d.name).join(", ")})`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
for (const h of o.hooks ?? []) {
|
|
45
|
+
for (const event of h.events) {
|
|
46
|
+
const declared = def.hooks.some((d) => d.phase === h.phase && (d.events.includes("*") || (event !== "*" && d.events.includes(event))));
|
|
47
|
+
if (!declared)
|
|
48
|
+
problems.push(`${name}: hooks may only narrow the declared hooks, and ${event} (${h.phase}) is not declared`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return problems;
|
|
53
|
+
}
|
|
54
|
+
/** Interceptors of a type this invoker doesn't run (e.g. the proposed `sink`). They are never invoked. */
|
|
55
|
+
export function unsupportedInterceptors(bound) {
|
|
56
|
+
return bound
|
|
57
|
+
.filter((b) => b.definition.type !== "validation" && b.definition.type !== "mutation")
|
|
58
|
+
.map((b) => `${b.definition.name} (${String(b.definition.type)})`);
|
|
59
|
+
}
|
|
60
|
+
/** Interceptor names offered by more than one server: each must be invoked on its own server, so names must be unique. */
|
|
61
|
+
export function duplicateInterceptors(bound) {
|
|
62
|
+
const servers = new Map();
|
|
63
|
+
for (const b of bound)
|
|
64
|
+
servers.set(b.definition.name, [...(servers.get(b.definition.name) ?? []), b.server ?? "?"]);
|
|
65
|
+
return [...servers].filter(([, s]) => s.length > 1).map(([name, s]) => `${name} (offered by ${s.join(", ")})`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Mutators that would run after `name` on a phase both hook, so they see (and
|
|
69
|
+
* could change or drop) what it wrote. Used to warn when another server's
|
|
70
|
+
* mutator runs after adtl.label.
|
|
71
|
+
*/
|
|
72
|
+
export function mutatorsAfter(bound, name, overrides = {}) {
|
|
73
|
+
const target = bound.find((b) => b.definition.name === name);
|
|
74
|
+
if (!target)
|
|
75
|
+
return [];
|
|
76
|
+
const hooksOf = (b) => overrides[b.definition.name]?.hooks ?? b.definition.hooks;
|
|
77
|
+
const shares = (b, phase) => hooksOf(b).some((h) => h.phase === phase && hooksOf(target).some((t) => t.phase === phase && (h.events.includes("*") || t.events.includes("*") || h.events.some((e) => t.events.includes(e)))));
|
|
78
|
+
const after = [];
|
|
79
|
+
for (const b of bound) {
|
|
80
|
+
if (b === target || b.definition.type !== "mutation")
|
|
81
|
+
continue;
|
|
82
|
+
const late = ["request", "response"].some((phase) => {
|
|
83
|
+
if (!shares(b, phase))
|
|
84
|
+
return false;
|
|
85
|
+
const p = resolvePriority(b.definition, overrides[b.definition.name], phase);
|
|
86
|
+
const t = resolvePriority(target.definition, overrides[name], phase);
|
|
87
|
+
return p > t || (p === t && b.definition.name.localeCompare(name) > 0);
|
|
88
|
+
});
|
|
89
|
+
if (late)
|
|
90
|
+
after.push(b.definition.name);
|
|
91
|
+
}
|
|
92
|
+
return after;
|
|
19
93
|
}
|
|
20
94
|
export class InterceptorInvoker {
|
|
21
95
|
interceptors;
|
|
22
96
|
timeoutMs;
|
|
23
97
|
modeOverride;
|
|
98
|
+
overrides;
|
|
24
99
|
constructor(interceptors, timeoutMs = 5000,
|
|
25
100
|
/** Overrides the mode every interceptor declares. */
|
|
26
|
-
modeOverride
|
|
101
|
+
modeOverride,
|
|
102
|
+
/** Per-interceptor overrides, by name. Check them with `checkOverrides` first. */
|
|
103
|
+
overrides = {}) {
|
|
27
104
|
this.interceptors = interceptors;
|
|
28
105
|
this.timeoutMs = timeoutMs;
|
|
29
106
|
this.modeOverride = modeOverride;
|
|
107
|
+
this.overrides = overrides;
|
|
30
108
|
}
|
|
31
109
|
/** Discover the interceptors an interceptor server offers. */
|
|
32
|
-
static async discover(client) {
|
|
110
|
+
static async discover(client, opts = {}) {
|
|
33
111
|
const res = await request(client, LIST_METHOD, {}, 10_000);
|
|
34
112
|
const defs = (res.interceptors ?? []);
|
|
35
|
-
return defs.map((definition) => ({ client, definition }));
|
|
113
|
+
return defs.map((definition) => ({ client, definition, ...opts }));
|
|
36
114
|
}
|
|
37
115
|
get definitions() {
|
|
38
116
|
return this.interceptors.map((i) => i.definition);
|
|
@@ -51,33 +129,56 @@ export class InterceptorInvoker {
|
|
|
51
129
|
await this.mutate("response", opts, out);
|
|
52
130
|
return out;
|
|
53
131
|
}
|
|
132
|
+
override(i) {
|
|
133
|
+
return this.overrides[i.definition.name];
|
|
134
|
+
}
|
|
135
|
+
mode(i) {
|
|
136
|
+
return this.modeOverride ?? this.override(i)?.mode ?? i.definition.mode ?? "active";
|
|
137
|
+
}
|
|
54
138
|
isAudit(i) {
|
|
55
|
-
return
|
|
139
|
+
return this.mode(i) === "audit";
|
|
56
140
|
}
|
|
57
|
-
|
|
141
|
+
failOpen(i) {
|
|
142
|
+
return (this.override(i)?.failOpen ?? i.definition.failOpen) === true;
|
|
143
|
+
}
|
|
144
|
+
timeout(i) {
|
|
145
|
+
return this.override(i)?.timeoutMs ?? this.timeoutMs;
|
|
146
|
+
}
|
|
147
|
+
/** Record that `i` runs in `phase`, with its resolved policy. */
|
|
58
148
|
run(i, phase, out) {
|
|
149
|
+
const o = this.override(i);
|
|
59
150
|
const r = {
|
|
60
151
|
name: i.definition.name,
|
|
61
152
|
phase,
|
|
62
|
-
mode: this.
|
|
63
|
-
modeFrom: this.modeOverride ? "override" : "default",
|
|
64
|
-
failOpen:
|
|
65
|
-
failOpenFrom: "default",
|
|
153
|
+
mode: this.mode(i),
|
|
154
|
+
modeFrom: this.modeOverride || o?.mode ? "override" : "default",
|
|
155
|
+
failOpen: this.failOpen(i),
|
|
156
|
+
failOpenFrom: o?.failOpen !== undefined ? "override" : "default",
|
|
157
|
+
timeoutMs: this.timeout(i),
|
|
66
158
|
};
|
|
67
159
|
out.ran.push(r);
|
|
68
160
|
return r;
|
|
69
161
|
}
|
|
70
162
|
select(type, event, phase) {
|
|
71
|
-
return this.interceptors.filter((i) => i.definition.type === type &&
|
|
163
|
+
return this.interceptors.filter((i) => i.definition.type === type && matches(this.override(i)?.hooks ?? i.definition.hooks, event, phase));
|
|
72
164
|
}
|
|
73
165
|
async invoke(i, phase, opts, payload) {
|
|
74
|
-
const
|
|
166
|
+
const timeoutMs = this.timeout(i);
|
|
167
|
+
const res = await request(i.client, INVOKE_METHOD, {
|
|
168
|
+
name: i.definition.name,
|
|
169
|
+
event: opts.event,
|
|
170
|
+
phase,
|
|
171
|
+
payload,
|
|
172
|
+
...(i.sendConfig === false ? {} : { config: opts.config }),
|
|
173
|
+
timeoutMs,
|
|
174
|
+
context: opts.context,
|
|
175
|
+
}, timeoutMs);
|
|
75
176
|
return res;
|
|
76
177
|
}
|
|
77
178
|
/** Handle an interceptor failure. Returns false if the phase must stop. */
|
|
78
179
|
failed(i, err, out) {
|
|
79
180
|
const msg = `${i.definition.name} failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
80
|
-
if (this.isAudit(i) ||
|
|
181
|
+
if (this.isAudit(i) || this.failOpen(i)) {
|
|
81
182
|
out.warnings.push(msg);
|
|
82
183
|
return true;
|
|
83
184
|
}
|
|
@@ -86,7 +187,8 @@ export class InterceptorInvoker {
|
|
|
86
187
|
}
|
|
87
188
|
/** Sequential mutations, atomic: on failure the original payload is kept. */
|
|
88
189
|
async mutate(phase, opts, out) {
|
|
89
|
-
const selected = this.select("mutation", opts.event, phase).sort((a, b) =>
|
|
190
|
+
const selected = this.select("mutation", opts.event, phase).sort((a, b) => resolvePriority(a.definition, this.override(a), phase) - resolvePriority(b.definition, this.override(b), phase) ||
|
|
191
|
+
a.definition.name.localeCompare(b.definition.name));
|
|
90
192
|
let payload = out.payload;
|
|
91
193
|
for (const i of selected) {
|
|
92
194
|
const ran = this.run(i, phase, out);
|
package/dist/invoker.js.map
CHANGED
|
@@ -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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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { AuthorizationDecision, AuthorizationRequest, Authorizer } from "./authorizer.js";
|
|
2
|
+
import type { OpenFgaConfig } from "./config.js";
|
|
3
|
+
export declare class OpenFgaAuthorizer implements Authorizer {
|
|
4
|
+
private readonly cfg;
|
|
5
|
+
private readonly fetchFn;
|
|
6
|
+
readonly name = "openfga";
|
|
7
|
+
constructor(cfg: OpenFgaConfig, fetchFn?: typeof fetch);
|
|
8
|
+
private user;
|
|
9
|
+
/** The object of this call, or a reason it can't be built. "listing" means: decide when called. */
|
|
10
|
+
private object;
|
|
11
|
+
check(req: AuthorizationRequest): Promise<AuthorizationDecision>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=openfga.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openfga.d.ts","sourceRoot":"","sources":["../src/openfga.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC/F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAYjD,qBAAa,iBAAkB,YAAW,UAAU;IAIhD,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,QAAQ,CAAC,IAAI,aAAa;gBAGP,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,OAAO,KAAa;IAGhD,OAAO,CAAC,IAAI;IAMZ,mGAAmG;IACnG,OAAO,CAAC,MAAM;IAqBR,KAAK,CAAC,GAAG,EAAE,oBAAoB,GAAG,OAAO,CAAC,qBAAqB,CAAC;CAuBvE"}
|
package/dist/openfga.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Relationship-based authorization with OpenFGA (`gateway.openfga`):
|
|
3
|
+
*
|
|
4
|
+
* openfga:
|
|
5
|
+
* url: http://localhost:8080
|
|
6
|
+
* storeId: "${FGA_STORE_ID}"
|
|
7
|
+
* modelId: "${FGA_MODEL_ID}" # optional: pin an authorization model
|
|
8
|
+
* token: "${FGA_TOKEN}" # optional: bearer token
|
|
9
|
+
* relation: can_use # optional: the default relation
|
|
10
|
+
* timeoutMs: 2000 # optional
|
|
11
|
+
* tools: # optional: per-resource rules, from the call's arguments
|
|
12
|
+
* github.add_issue_comment: { relation: can_comment, object: "repo:{owner}/{repo}" }
|
|
13
|
+
*
|
|
14
|
+
* Every call becomes one OpenFGA check:
|
|
15
|
+
*
|
|
16
|
+
* user user:<id>, service:<id>, or user:anonymous without an id
|
|
17
|
+
* relation the tool's rule, else `relation`
|
|
18
|
+
* object the tool's rule, else tool:<server>.<tool>, prompt:<server>.<name> or resource:<uri>
|
|
19
|
+
*
|
|
20
|
+
* Ids are percent-encoded, because OpenFGA ids can't hold `:`, `#`, `@` or
|
|
21
|
+
* spaces; ids too long for OpenFGA are replaced by their SHA-256. A rule's
|
|
22
|
+
* `{argument}` must be a string or number, or the call is denied. Tool lists
|
|
23
|
+
* have no arguments, so tools whose object needs them stay listed and are
|
|
24
|
+
* checked when called. An unreachable server or an error denies the call.
|
|
25
|
+
*
|
|
26
|
+
* Works with Auth0 FGA too, by pointing `url` at its API and passing a token.
|
|
27
|
+
*/
|
|
28
|
+
import { createHash } from "node:crypto";
|
|
29
|
+
/** OpenFGA's limit on the id part of an object or user. */
|
|
30
|
+
const MAX_ID = 254;
|
|
31
|
+
function fgaId(value) {
|
|
32
|
+
const id = encodeURIComponent(value);
|
|
33
|
+
return id.length <= MAX_ID ? id : `sha256-${createHash("sha256").update(value).digest("hex")}`;
|
|
34
|
+
}
|
|
35
|
+
const PLACEHOLDER = /\{([A-Za-z0-9_.-]+)\}/g;
|
|
36
|
+
export class OpenFgaAuthorizer {
|
|
37
|
+
cfg;
|
|
38
|
+
fetchFn;
|
|
39
|
+
name = "openfga";
|
|
40
|
+
constructor(cfg, fetchFn = fetch) {
|
|
41
|
+
this.cfg = cfg;
|
|
42
|
+
this.fetchFn = fetchFn;
|
|
43
|
+
}
|
|
44
|
+
user(req) {
|
|
45
|
+
const p = req.principal;
|
|
46
|
+
if (p.type === "anonymous" || !p.id)
|
|
47
|
+
return "user:anonymous";
|
|
48
|
+
return `${p.type === "service" ? "service" : "user"}:${fgaId(p.id)}`;
|
|
49
|
+
}
|
|
50
|
+
/** The object of this call, or a reason it can't be built. "listing" means: decide when called. */
|
|
51
|
+
object(req, template) {
|
|
52
|
+
if (template !== undefined) {
|
|
53
|
+
if (req.arguments === undefined && template.search(PLACEHOLDER) !== -1)
|
|
54
|
+
return "listing";
|
|
55
|
+
const colon = template.indexOf(":");
|
|
56
|
+
const type = template.slice(0, colon + 1);
|
|
57
|
+
let missing;
|
|
58
|
+
const id = template.slice(colon + 1).replace(PLACEHOLDER, (_, name) => {
|
|
59
|
+
const v = req.arguments?.[name];
|
|
60
|
+
if (typeof v !== "string" && typeof v !== "number") {
|
|
61
|
+
missing ??= name;
|
|
62
|
+
return "";
|
|
63
|
+
}
|
|
64
|
+
return String(v);
|
|
65
|
+
});
|
|
66
|
+
return missing !== undefined ? { missing } : { object: `${type}${fgaId(id)}` };
|
|
67
|
+
}
|
|
68
|
+
if (req.tool !== undefined)
|
|
69
|
+
return { object: `tool:${fgaId(`${req.server}.${req.tool}`)}` };
|
|
70
|
+
if (req.prompt !== undefined)
|
|
71
|
+
return { object: `prompt:${fgaId(`${req.server}.${req.prompt}`)}` };
|
|
72
|
+
return { object: `resource:${fgaId(req.resource ?? "")}` };
|
|
73
|
+
}
|
|
74
|
+
async check(req) {
|
|
75
|
+
const rule = req.tool !== undefined ? this.cfg.tools[`${req.server}.${req.tool}`] : undefined;
|
|
76
|
+
const target = this.object(req, rule?.object);
|
|
77
|
+
if (target === "listing")
|
|
78
|
+
return { allow: true };
|
|
79
|
+
const what = req.tool ?? req.prompt ?? req.resource;
|
|
80
|
+
if ("missing" in target)
|
|
81
|
+
return { allow: false, reason: `openfga: ${what} has no usable argument "${target.missing}"` };
|
|
82
|
+
const user = this.user(req);
|
|
83
|
+
const relation = rule?.relation ?? this.cfg.relation;
|
|
84
|
+
const res = await this.fetchFn(`${this.cfg.url.replace(/\/+$/, "")}/stores/${encodeURIComponent(this.cfg.storeId)}/check`, {
|
|
85
|
+
method: "POST",
|
|
86
|
+
headers: { "content-type": "application/json", ...(this.cfg.token ? { authorization: `Bearer ${this.cfg.token}` } : {}) },
|
|
87
|
+
body: JSON.stringify({
|
|
88
|
+
tuple_key: { user, relation, object: target.object },
|
|
89
|
+
...(this.cfg.modelId ? { authorization_model_id: this.cfg.modelId } : {}),
|
|
90
|
+
}),
|
|
91
|
+
signal: AbortSignal.timeout(this.cfg.timeoutMs),
|
|
92
|
+
});
|
|
93
|
+
if (!res.ok)
|
|
94
|
+
throw new Error(`OpenFGA answered ${res.status}`);
|
|
95
|
+
const body = (await res.json());
|
|
96
|
+
if (body.allowed === true)
|
|
97
|
+
return { allow: true };
|
|
98
|
+
return { allow: false, reason: `OpenFGA: ${user} has no ${relation} on ${target.object}` };
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=openfga.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openfga.js","sourceRoot":"","sources":["../src/openfga.ts"],"names":[],"mappings":"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"}
|
package/dist/startup.d.ts
CHANGED
|
@@ -32,16 +32,25 @@ export declare function gatewayPrincipal(cfg: GatewayConfig, env: NodeJS.Process
|
|
|
32
32
|
* The configured authorizers, in the order they are asked: roles, then cedar.
|
|
33
33
|
* Cedar files are read and parsed here, so a bad policy fails startup.
|
|
34
34
|
*/
|
|
35
|
-
export declare function gatewayAuthorizers(cfg: GatewayConfig, baseDir: string): Promise<Authorizer[]>;
|
|
35
|
+
export declare function gatewayAuthorizers(cfg: GatewayConfig, baseDir: string, env?: NodeJS.ProcessEnv): Promise<Authorizer[]>;
|
|
36
36
|
/**
|
|
37
37
|
* Under Claude Code, which passes `CLAUDE_CODE_SESSION_ID` to stdio MCP
|
|
38
38
|
* servers, the gateway uses that id and keeps session labels in files, so the
|
|
39
39
|
* Claude Code hooks (`adtl-gateway hook`) add to the same session label.
|
|
40
|
+
*
|
|
41
|
+
* `ADTL_SESSION_ID` does the same for any agent framework, and wins over
|
|
42
|
+
* Claude Code's: a sub-agent's gateway started with its parent's session id
|
|
43
|
+
* starts from the parent's label, and what it reads taints the parent too.
|
|
40
44
|
*/
|
|
41
45
|
export declare function sharedSession(env: NodeJS.ProcessEnv): {
|
|
42
46
|
sessionId: string;
|
|
43
47
|
dir: string;
|
|
44
48
|
} | undefined;
|
|
49
|
+
/** `ADTL_AGENT_ID` (and `ADTL_AGENT_TYPE`): which agent this gateway serves, for the audit log. */
|
|
50
|
+
export declare function gatewayAgent(env: NodeJS.ProcessEnv): {
|
|
51
|
+
id: string;
|
|
52
|
+
type?: string;
|
|
53
|
+
} | undefined;
|
|
45
54
|
export interface StartedGateway {
|
|
46
55
|
gateway: AdtlGateway;
|
|
47
56
|
close(): Promise<void>;
|
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,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;
|
|
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;AAOhF,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,CAyB1H;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,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAwBzI;AAED;;;;;;;;GAQG;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,mGAAmG;AACnG,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAI9F;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,CAoIzB"}
|
package/dist/startup.js
CHANGED
|
@@ -18,7 +18,9 @@ import { CedarAuthorizer } from "./cedar.js";
|
|
|
18
18
|
import { GatewayConfigSchema, expandApprovals, expandEnv, expandUpstream, isHttpUpstream, } from "./config.js";
|
|
19
19
|
import { EmailNotifier } from "./email.js";
|
|
20
20
|
import { AdtlGateway, GATEWAY_VERSION } from "./gateway.js";
|
|
21
|
-
import { InterceptorInvoker } from "./invoker.js";
|
|
21
|
+
import { InterceptorInvoker, checkOverrides, duplicateInterceptors, mutatorsAfter, unsupportedInterceptors } from "./invoker.js";
|
|
22
|
+
import { OpenFgaAuthorizer } from "./openfga.js";
|
|
23
|
+
import { loadTotpVerifier } from "./totp.js";
|
|
22
24
|
import { NtfyNotifier } from "./ntfy.js";
|
|
23
25
|
import { RoleAuthorizer } from "./roles.js";
|
|
24
26
|
export class GatewayConfigError extends Error {
|
|
@@ -103,13 +105,14 @@ export function createApprovals(cfg, env, log) {
|
|
|
103
105
|
notifiers.push(new EmailNotifier({ smtp: a.email.smtp, from: a.email.from, to: [a.email.to].flat(), on: a.email.on }));
|
|
104
106
|
}
|
|
105
107
|
const approverChannels = new Map(Object.entries(a.approvers ?? {}).map(([id, c]) => [id, [new NtfyNotifier({ ...c.ntfy, name: `ntfy:${id}` })]]));
|
|
106
|
-
if (notifiers.length === 0 && approverChannels.size === 0 && !a.elicitation)
|
|
108
|
+
if (notifiers.length === 0 && approverChannels.size === 0 && !a.elicitation && !a.totp)
|
|
107
109
|
return undefined;
|
|
108
|
-
if (!notifiers.some((n) => n.listen) && approverChannels.size === 0 && !a.elicitation) {
|
|
110
|
+
if (!notifiers.some((n) => n.listen) && approverChannels.size === 0 && !a.elicitation && !a.totp) {
|
|
109
111
|
log.warn('no approval channel can carry answers (configure gateway.approvals.ntfy); "ask" still blocks');
|
|
110
112
|
}
|
|
111
113
|
const approvers = approverChannels.size ? `; approvers: ${[...approverChannels.keys()].join(", ")}` : "";
|
|
112
|
-
const
|
|
114
|
+
const inClient = a.totp ? ["authenticator code (if the client supports elicitation)"] : a.elicitation ? ["elicitation (if the client supports it)"] : [];
|
|
115
|
+
const shared = [...notifiers.map((n) => n.name), ...inClient];
|
|
113
116
|
log.info(`approvals: ${shared.join(", ") || "none shared"}${approvers} (timeout ${a.timeoutSeconds}s)`);
|
|
114
117
|
return new ApprovalBroker({ notifiers, approverChannels, timeoutMs: a.timeoutSeconds * 1000, log });
|
|
115
118
|
}
|
|
@@ -158,7 +161,7 @@ export function gatewayPrincipal(cfg, env) {
|
|
|
158
161
|
* The configured authorizers, in the order they are asked: roles, then cedar.
|
|
159
162
|
* Cedar files are read and parsed here, so a bad policy fails startup.
|
|
160
163
|
*/
|
|
161
|
-
export async function gatewayAuthorizers(cfg, baseDir) {
|
|
164
|
+
export async function gatewayAuthorizers(cfg, baseDir, env = process.env) {
|
|
162
165
|
const out = [];
|
|
163
166
|
if (cfg.roles)
|
|
164
167
|
out.push(new RoleAuthorizer(cfg.roles));
|
|
@@ -170,23 +173,44 @@ export async function gatewayAuthorizers(cfg, baseDir) {
|
|
|
170
173
|
throw new GatewayConfigError(err.message);
|
|
171
174
|
}
|
|
172
175
|
}
|
|
176
|
+
if (cfg.openfga) {
|
|
177
|
+
const f = cfg.openfga;
|
|
178
|
+
const expand = (v, key) => expandEnv(v, env, `gateway.openfga.${key}`);
|
|
179
|
+
out.push(new OpenFgaAuthorizer({
|
|
180
|
+
...f,
|
|
181
|
+
url: expand(f.url, "url"),
|
|
182
|
+
storeId: expand(f.storeId, "storeId"),
|
|
183
|
+
...(f.modelId !== undefined ? { modelId: expand(f.modelId, "modelId") } : {}),
|
|
184
|
+
...(f.token !== undefined ? { token: expand(f.token, "token") } : {}),
|
|
185
|
+
}));
|
|
186
|
+
}
|
|
173
187
|
return out;
|
|
174
188
|
}
|
|
175
189
|
/**
|
|
176
190
|
* Under Claude Code, which passes `CLAUDE_CODE_SESSION_ID` to stdio MCP
|
|
177
191
|
* servers, the gateway uses that id and keeps session labels in files, so the
|
|
178
192
|
* Claude Code hooks (`adtl-gateway hook`) add to the same session label.
|
|
193
|
+
*
|
|
194
|
+
* `ADTL_SESSION_ID` does the same for any agent framework, and wins over
|
|
195
|
+
* Claude Code's: a sub-agent's gateway started with its parent's session id
|
|
196
|
+
* starts from the parent's label, and what it reads taints the parent too.
|
|
179
197
|
*/
|
|
180
198
|
export function sharedSession(env) {
|
|
181
|
-
const sessionId = env.CLAUDE_CODE_SESSION_ID?.trim();
|
|
199
|
+
const sessionId = env.ADTL_SESSION_ID?.trim() || env.CLAUDE_CODE_SESSION_ID?.trim();
|
|
182
200
|
return sessionId ? { sessionId, dir: defaultSessionsDir(env) } : undefined;
|
|
183
201
|
}
|
|
202
|
+
/** `ADTL_AGENT_ID` (and `ADTL_AGENT_TYPE`): which agent this gateway serves, for the audit log. */
|
|
203
|
+
export function gatewayAgent(env) {
|
|
204
|
+
const id = env.ADTL_AGENT_ID?.trim();
|
|
205
|
+
const type = env.ADTL_AGENT_TYPE?.trim();
|
|
206
|
+
return id ? { id, ...(type ? { type } : {}) } : undefined;
|
|
207
|
+
}
|
|
184
208
|
export async function startGateway(loaded, opts = {}) {
|
|
185
209
|
const env = opts.env ?? process.env;
|
|
186
210
|
// Config problems that need no process: fail before starting any.
|
|
187
211
|
const approverMembers = approverRoles(loaded.labels, loaded.gateway);
|
|
188
212
|
const baseDir = dirname(loaded.path);
|
|
189
|
-
const authorizers = await gatewayAuthorizers(loaded.gateway, baseDir);
|
|
213
|
+
const authorizers = await gatewayAuthorizers(loaded.gateway, baseDir, env);
|
|
190
214
|
const log = opts.logger ?? { info: (m) => console.error(`[adtl-gateway] ${m}`), warn: (m) => console.error(`[adtl-gateway] warning: ${m}`) };
|
|
191
215
|
const clients = [];
|
|
192
216
|
const closeAll = () => Promise.allSettled(clients.map((c) => c.close())).then(() => undefined);
|
|
@@ -211,15 +235,54 @@ export async function startGateway(loaded, opts = {}) {
|
|
|
211
235
|
if (!interceptors.getServerCapabilities()?.extensions?.[INTERCEPTORS_EXTENSION]) {
|
|
212
236
|
throw new GatewayConfigError(`The interceptor server does not declare the ${INTERCEPTORS_EXTENSION} extension`);
|
|
213
237
|
}
|
|
214
|
-
const
|
|
215
|
-
const
|
|
238
|
+
const own = await InterceptorInvoker.discover(interceptors, { server: "interceptors" });
|
|
239
|
+
const ownNames = own.map((b) => b.definition.name);
|
|
216
240
|
for (const required of [POLICY_INTERCEPTOR, LABEL_INTERCEPTOR]) {
|
|
217
|
-
if (!
|
|
241
|
+
if (!ownNames.includes(required)) {
|
|
218
242
|
throw new GatewayConfigError(`The interceptor server does not offer ${required}; refusing to start without it`);
|
|
219
243
|
}
|
|
220
244
|
}
|
|
245
|
+
// More interceptor servers (SEP-2624: interceptors may come from N servers, each invoked where it was advertised).
|
|
246
|
+
// A server that can't be reached stops startup: the owner asked for its interceptors.
|
|
247
|
+
const bound = [...own];
|
|
248
|
+
for (const [id, server] of Object.entries(loaded.gateway.interceptorServers)) {
|
|
249
|
+
const where = `gateway.interceptorServers.${id}`;
|
|
250
|
+
let client;
|
|
251
|
+
try {
|
|
252
|
+
client = await connectUpstream(`interceptors:${id}`, expandUpstream(id, server, env), baseDir);
|
|
253
|
+
}
|
|
254
|
+
catch (err) {
|
|
255
|
+
throw new GatewayConfigError(`${where}: could not connect: ${err instanceof Error ? err.message : String(err)}`);
|
|
256
|
+
}
|
|
257
|
+
clients.push(client);
|
|
258
|
+
if (!client.getServerCapabilities()?.extensions?.[INTERCEPTORS_EXTENSION]) {
|
|
259
|
+
throw new GatewayConfigError(`${where} does not declare the ${INTERCEPTORS_EXTENSION} extension`);
|
|
260
|
+
}
|
|
261
|
+
bound.push(...(await InterceptorInvoker.discover(client, { server: id, sendConfig: false })));
|
|
262
|
+
}
|
|
263
|
+
const duplicates = duplicateInterceptors(bound);
|
|
264
|
+
if (duplicates.length)
|
|
265
|
+
throw new GatewayConfigError(`Interceptor names must be unique across servers: ${duplicates.join("; ")}`);
|
|
266
|
+
const names = bound.map((b) => b.definition.name);
|
|
267
|
+
const overrides = loaded.gateway.interceptorOverrides;
|
|
268
|
+
const problems = checkOverrides(bound.map((b) => b.definition), overrides);
|
|
269
|
+
if (problems.length)
|
|
270
|
+
throw new GatewayConfigError(`gateway.interceptorOverrides: ${problems.join("; ")}`);
|
|
271
|
+
const unsupported = unsupportedInterceptors(bound);
|
|
272
|
+
if (unsupported.length)
|
|
273
|
+
log.warn(`not running interceptors of an unknown type: ${unsupported.join(", ")}`);
|
|
274
|
+
const late = mutatorsAfter(bound, LABEL_INTERCEPTOR, overrides);
|
|
275
|
+
if (late.length) {
|
|
276
|
+
log.warn(`${late.join(", ")} run after ${LABEL_INTERCEPTOR} and could change or drop its label; give them a lower priorityHint`);
|
|
277
|
+
}
|
|
278
|
+
for (const name of [POLICY_INTERCEPTOR, LABEL_INTERCEPTOR]) {
|
|
279
|
+
const o = overrides[name];
|
|
280
|
+
if (o?.mode === "audit" || o?.failOpen === true || o?.hooks) {
|
|
281
|
+
log.warn(`gateway.interceptorOverrides relaxes ${name} (${Object.keys(o).join(", ")}): calls it would stop may get through`);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
221
284
|
const audit = loaded.gateway.mode === "audit";
|
|
222
|
-
const invoker = new InterceptorInvoker(bound, loaded.gateway.interceptorTimeoutMs, audit ? "audit" : undefined);
|
|
285
|
+
const invoker = new InterceptorInvoker(bound, loaded.gateway.interceptorTimeoutMs, audit ? "audit" : undefined, overrides);
|
|
223
286
|
log.info(`interceptors: ${names.join(", ")}`);
|
|
224
287
|
if (shared)
|
|
225
288
|
log.info(`sharing session labels with Claude Code hooks (${shared.dir})`);
|
|
@@ -257,8 +320,16 @@ export async function startGateway(loaded, opts = {}) {
|
|
|
257
320
|
for (const a of authorizers)
|
|
258
321
|
if (a.name !== "roles")
|
|
259
322
|
log.info(`authorizer: ${a.name}`);
|
|
323
|
+
const totp = loaded.gateway.approvals?.totp ? loadTotpVerifier(env) : undefined;
|
|
324
|
+
if (loaded.gateway.approvals?.totp && !totp)
|
|
325
|
+
throw new GatewayConfigError("gateway.approvals.totp is on, but no secret is set up: run adtl-gateway totp setup");
|
|
326
|
+
const agent = gatewayAgent(env);
|
|
327
|
+
if (agent)
|
|
328
|
+
log.info(`agent: ${agent.id}${agent.type ? ` (${agent.type})` : ""}`);
|
|
260
329
|
const gateway = new AdtlGateway({
|
|
261
330
|
...(shared ? { sessionId: shared.sessionId } : {}),
|
|
331
|
+
...(agent ? { agent } : {}),
|
|
332
|
+
...(totp ? { totp } : {}),
|
|
262
333
|
upstreams,
|
|
263
334
|
invoker,
|
|
264
335
|
...(auditLog ? { audit: auditLog } : {}),
|