@decionis/agent-safe-pipeline 0.3.7 → 0.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,291 @@
1
+ import { createHash, sign, verify } from "node:crypto";
2
+ /**
3
+ * Signed producer signals, as the hosted authority verifies them and as this
4
+ * package's doubles and tests mint them.
5
+ *
6
+ * A producer (a card-presence provider such as `koard`) signs a standing
7
+ * statement about a subject: the cardholder granted this agent permission to
8
+ * buy on their behalf, within these limits, until then (Koard's "Tap to
9
+ * Authenticate"). The agent's proposal carries that compact JWS as evidence;
10
+ * the authority verifies it against the key the organisation registered for
11
+ * the producer (purpose `signed_signal`) or an admitted provider's JWKS,
12
+ * writes the verified FACTS under `agent_safe.signed_signals.<name>` for
13
+ * policy to name with `required_signals`, and records those facts in the
14
+ * binding, never the token. This module is that contract, letter for letter,
15
+ * so a test against the local double proves what the hosted route proves.
16
+ */
17
+ export const SIGNED_SIGNAL_TYPE = "decionis-signed-signal+jwt";
18
+ export const SIGNED_SIGNAL_REFUSAL_CODES = [
19
+ "SIGNED_SIGNAL_MALFORMED",
20
+ "SIGNED_SIGNAL_KEY_UNKNOWN",
21
+ "SIGNED_SIGNAL_SIGNATURE_INVALID",
22
+ "SIGNED_SIGNAL_EXPIRED",
23
+ "SIGNED_SIGNAL_AUDIENCE_MISMATCH",
24
+ "SIGNED_SIGNAL_ISSUER_MISMATCH",
25
+ "SIGNED_SIGNAL_NOT_VERIFIED",
26
+ "SIGNED_SIGNAL_DUPLICATE_NAME",
27
+ ];
28
+ /** A standing signal may live thirty days; a tap for one intent lives five minutes. */
29
+ export const SIGNED_SIGNAL_MAX_LIFETIME_SECONDS = 30 * 24 * 60 * 60;
30
+ const CLOCK_TOLERANCE_SECONDS = 300;
31
+ const SIGNAL_NAME = /^[a-z][a-z0-9_]{0,63}$/;
32
+ const OPEN_NAME = /^[a-z][a-z0-9_.:-]*$/;
33
+ const ACTION_NAME = /^[a-z][a-z0-9._:-]*$/;
34
+ const CURRENCY = /^[a-z]{3}$/i;
35
+ const SIGNAL_KEYS = new Set([
36
+ "name",
37
+ "method",
38
+ "result",
39
+ "agent",
40
+ "scope",
41
+ "limits",
42
+ "card_token_ref",
43
+ ]);
44
+ /** Decionis Presence's own provider name; a producer can never speak as it. */
45
+ const RESERVED_PRODUCER = "presence";
46
+ function text(value, max) {
47
+ return typeof value === "string" && value.length > 0 && value.length <= max ? value : null;
48
+ }
49
+ /** A primary account number must never reach a decision record. */
50
+ function looksLikePan(value) {
51
+ const digits = value.replace(/[\s-]/g, "");
52
+ if (!/^\d{12,19}$/.test(digits))
53
+ return false;
54
+ let sum = 0;
55
+ for (let index = 0; index < digits.length; index += 1) {
56
+ let digit = Number(digits[digits.length - 1 - index]);
57
+ if (index % 2 === 1) {
58
+ digit *= 2;
59
+ if (digit > 9)
60
+ digit -= 9;
61
+ }
62
+ sum += digit;
63
+ }
64
+ return sum % 10 === 0;
65
+ }
66
+ function decodeSegment(segment) {
67
+ try {
68
+ const parsed = JSON.parse(Buffer.from(segment, "base64url").toString("utf8"));
69
+ return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)
70
+ ? parsed
71
+ : null;
72
+ }
73
+ catch {
74
+ return null;
75
+ }
76
+ }
77
+ /** The `signal` claim read strictly: any key the contract does not name refuses the token. */
78
+ function signalClaims(value) {
79
+ if (typeof value !== "object" || value === null || Array.isArray(value))
80
+ return null;
81
+ const record = value;
82
+ if (Object.keys(record).some((key) => !SIGNAL_KEYS.has(key)))
83
+ return null;
84
+ const name = text(record.name, 64);
85
+ const method = text(record.method, 64);
86
+ if (name === null || !SIGNAL_NAME.test(name) || method === null || !OPEN_NAME.test(method)) {
87
+ return null;
88
+ }
89
+ if (record.result !== "VERIFIED" && record.result !== "FAILED")
90
+ return null;
91
+ const claims = { name, method, result: record.result };
92
+ if (record.agent !== undefined) {
93
+ const agent = text(record.agent, 200);
94
+ if (agent === null)
95
+ return null;
96
+ claims.agent = agent;
97
+ }
98
+ if (record.scope !== undefined) {
99
+ const scope = record.scope;
100
+ const actions = scope !== null && typeof scope === "object" ? scope.actions : undefined;
101
+ if (!Array.isArray(actions) ||
102
+ actions.length === 0 ||
103
+ actions.length > 32 ||
104
+ Object.keys(scope).length !== 1 ||
105
+ !actions.every((action) => typeof action === "string" && action.length <= 120 && ACTION_NAME.test(action))) {
106
+ return null;
107
+ }
108
+ claims.scope = { actions: [...actions] };
109
+ }
110
+ if (record.limits !== undefined) {
111
+ const limits = record.limits;
112
+ if (limits === null ||
113
+ typeof limits !== "object" ||
114
+ Object.keys(limits).length !== 2 ||
115
+ typeof limits.currency !== "string" ||
116
+ !CURRENCY.test(limits.currency) ||
117
+ typeof limits.amount_minor !== "number" ||
118
+ !Number.isSafeInteger(limits.amount_minor) ||
119
+ limits.amount_minor < 0) {
120
+ return null;
121
+ }
122
+ claims.limits = { currency: limits.currency.toUpperCase(), amount_minor: limits.amount_minor };
123
+ }
124
+ if (record.card_token_ref !== undefined) {
125
+ const ref = text(record.card_token_ref, 200);
126
+ if (ref === null || looksLikePan(ref))
127
+ return null;
128
+ claims.card_token_ref = ref;
129
+ }
130
+ return claims;
131
+ }
132
+ /**
133
+ * Verifies one token the way the hosted authority does: the protected header
134
+ * names an Ed25519 key registered for the producer with purpose
135
+ * `signed_signal`; the signature verifies under it; the issuer is the one
136
+ * registered with the key and the audience is the organisation; the claims
137
+ * are bounded, carry no card number, and the lifetime is within the cap.
138
+ */
139
+ export function verifySignedSignal(token, options) {
140
+ const refuse = (code) => ({ ok: false, code });
141
+ const parts = token.split(".");
142
+ if (parts.length !== 3)
143
+ return refuse("SIGNED_SIGNAL_MALFORMED");
144
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
145
+ const header = decodeSegment(encodedHeader);
146
+ const payload = decodeSegment(encodedPayload);
147
+ if (header === null || payload === null)
148
+ return refuse("SIGNED_SIGNAL_MALFORMED");
149
+ const kid = text(header.kid, 200);
150
+ if (header.alg !== "EdDSA" ||
151
+ header.typ !== SIGNED_SIGNAL_TYPE ||
152
+ kid === null ||
153
+ kid.trim() !== kid) {
154
+ return refuse("SIGNED_SIGNAL_MALFORMED");
155
+ }
156
+ const key = options.findKey(kid);
157
+ if (key === null)
158
+ return refuse("SIGNED_SIGNAL_KEY_UNKNOWN");
159
+ const signed = Buffer.from(`${encodedHeader}.${encodedPayload}`, "ascii");
160
+ if (!verify(null, signed, key.publicKey, Buffer.from(encodedSignature, "base64url"))) {
161
+ return refuse("SIGNED_SIGNAL_SIGNATURE_INVALID");
162
+ }
163
+ const nowMs = options.nowMs ?? Date.now();
164
+ const issuer = text(payload.iss, 100);
165
+ const subject = text(payload.sub, 200);
166
+ const signalId = text(payload.jti, 200);
167
+ const iat = payload.iat;
168
+ const exp = payload.exp;
169
+ const claims = signalClaims(payload.signal);
170
+ if (issuer === null ||
171
+ payload.aud === undefined ||
172
+ subject === null ||
173
+ looksLikePan(subject) ||
174
+ signalId === null ||
175
+ typeof iat !== "number" ||
176
+ typeof exp !== "number" ||
177
+ !Number.isFinite(iat) ||
178
+ !Number.isFinite(exp) ||
179
+ exp <= iat ||
180
+ exp - iat > SIGNED_SIGNAL_MAX_LIFETIME_SECONDS ||
181
+ iat * 1_000 > nowMs + CLOCK_TOLERANCE_SECONDS * 1_000 ||
182
+ claims === null) {
183
+ return refuse("SIGNED_SIGNAL_MALFORMED");
184
+ }
185
+ if (issuer === RESERVED_PRODUCER || issuer !== key.issuer)
186
+ return refuse("SIGNED_SIGNAL_ISSUER_MISMATCH");
187
+ if (payload.aud !== options.orgId)
188
+ return refuse("SIGNED_SIGNAL_AUDIENCE_MISMATCH");
189
+ if (exp * 1_000 + CLOCK_TOLERANCE_SECONDS * 1_000 <= nowMs)
190
+ return refuse("SIGNED_SIGNAL_EXPIRED");
191
+ if (claims.result !== "VERIFIED")
192
+ return refuse("SIGNED_SIGNAL_NOT_VERIFIED");
193
+ return {
194
+ ok: true,
195
+ signal: {
196
+ name: claims.name,
197
+ producer: key.issuer,
198
+ method: claims.method,
199
+ subject,
200
+ signal_id: signalId,
201
+ key_id: key.kid,
202
+ issued_at: new Date(iat * 1_000).toISOString(),
203
+ expires_at: new Date(exp * 1_000).toISOString(),
204
+ evidence_digest: `sha256:${createHash("sha256").update(token, "utf8").digest("hex")}`,
205
+ claims,
206
+ },
207
+ };
208
+ }
209
+ /**
210
+ * The facts a verified signal contributes against one intent. `covers` says
211
+ * what the signal asserts about the intent (null when it asserts nothing on
212
+ * that axis); `covers_intent` is true when nothing it asserts is false. A
213
+ * limit the intent gives nothing to check against is not covered.
214
+ */
215
+ export function signedSignalFacts(verified, intent) {
216
+ const { claims } = verified;
217
+ const amountMinor = intent.parameters.amountMinor;
218
+ const currency = intent.parameters.currency;
219
+ const cardTokenRef = intent.parameters.cardTokenRef;
220
+ const covers = {
221
+ action: claims.scope === undefined ? null : claims.scope.actions.includes(intent.action),
222
+ agent: claims.agent === undefined ? null : claims.agent === intent.actorId,
223
+ amount: claims.limits === undefined
224
+ ? null
225
+ : typeof amountMinor === "number" &&
226
+ Number.isSafeInteger(amountMinor) &&
227
+ amountMinor >= 0 &&
228
+ amountMinor <= claims.limits.amount_minor,
229
+ currency: claims.limits === undefined
230
+ ? null
231
+ : typeof currency === "string" && currency.toUpperCase() === claims.limits.currency,
232
+ card: claims.card_token_ref === undefined
233
+ ? null
234
+ : cardTokenRef === claims.card_token_ref ||
235
+ intent.resource === `card:${claims.card_token_ref}`,
236
+ };
237
+ return {
238
+ verified: true,
239
+ producer: verified.producer,
240
+ method: verified.method,
241
+ subject: verified.subject,
242
+ signal_id: verified.signal_id,
243
+ key_id: verified.key_id,
244
+ issued_at: verified.issued_at,
245
+ expires_at: verified.expires_at,
246
+ evidence_digest: verified.evidence_digest,
247
+ ...(claims.agent === undefined ? {} : { agent: claims.agent }),
248
+ ...(claims.scope === undefined ? {} : { scope: { actions: [...claims.scope.actions] } }),
249
+ ...(claims.limits === undefined ? {} : { limits: { ...claims.limits } }),
250
+ ...(claims.card_token_ref === undefined ? {} : { card_token_ref: claims.card_token_ref }),
251
+ covers,
252
+ covers_intent: Object.values(covers).every((entry) => entry !== false),
253
+ };
254
+ }
255
+ /** Every token verified and its facts keyed by name; two tokens with one name refuse the request. */
256
+ export function verifySignedSignals(tokens, options) {
257
+ const facts = {};
258
+ for (const token of tokens) {
259
+ const verification = verifySignedSignal(token, options);
260
+ if (!verification.ok)
261
+ return verification;
262
+ if (facts[verification.signal.name] !== undefined) {
263
+ return { ok: false, code: "SIGNED_SIGNAL_DUPLICATE_NAME" };
264
+ }
265
+ facts[verification.signal.name] = signedSignalFacts(verification.signal, options.intent);
266
+ }
267
+ return { ok: true, facts };
268
+ }
269
+ /**
270
+ * Mints a token as a producer does, for tests and demos: an Ed25519 private
271
+ * key, the key id the organisation registered, and the claims. The lifetime
272
+ * defaults to one day.
273
+ */
274
+ export function mintSignedSignal(input) {
275
+ const issuedAt = Math.floor((input.issuedAtMs ?? Date.now()) / 1_000);
276
+ const header = { alg: "EdDSA", typ: SIGNED_SIGNAL_TYPE, kid: input.kid, ...input.header };
277
+ const payload = {
278
+ iss: input.issuer,
279
+ aud: input.audience,
280
+ sub: input.subject,
281
+ iat: issuedAt,
282
+ exp: issuedAt + (input.lifetimeSeconds ?? 24 * 60 * 60),
283
+ jti: input.jti ?? `signal-${issuedAt}-${Math.random().toString(36).slice(2, 10)}`,
284
+ signal: input.signal,
285
+ };
286
+ const encode = (value) => Buffer.from(JSON.stringify(value), "utf8").toString("base64url");
287
+ const signingInput = `${encode(header)}.${encode(payload)}`;
288
+ const signature = sign(null, Buffer.from(signingInput, "ascii"), input.privateKey);
289
+ return `${signingInput}.${signature.toString("base64url")}`;
290
+ }
291
+ //# sourceMappingURL=SignedSignals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SignedSignals.js","sourceRoot":"","sources":["../../src/testing/SignedSignals.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decionis/agent-safe-pipeline",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Execution Authority for AI agents: agents propose, Decionis independently decides ALLOW / ESCALATE / BLOCK, Presence verifies human approval on escalation, and a SafeExecutor runs only on a single-use intent-bound grant. Every decision leaves a Decision Dossier.",
5
5
  "keywords": [
6
6
  "execution-authority",