salt-agent-sdk 0.1.0 → 0.19.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/LICENSE +21 -0
- package/README.md +941 -30
- package/dist/actions.d.ts +21 -5
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +673 -54
- package/dist/actions.js.map +1 -1
- package/dist/ask.d.ts +83 -0
- package/dist/ask.d.ts.map +1 -0
- package/dist/ask.js +215 -0
- package/dist/ask.js.map +1 -0
- package/dist/chatPrivacy.d.ts +34 -0
- package/dist/chatPrivacy.d.ts.map +1 -0
- package/dist/chatPrivacy.js +60 -0
- package/dist/chatPrivacy.js.map +1 -0
- package/dist/client.d.ts +3123 -35
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +1267 -143
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +16 -6
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +16 -5
- package/dist/config.js.map +1 -1
- package/dist/crypto.d.ts +62 -0
- package/dist/crypto.d.ts.map +1 -1
- package/dist/crypto.js +121 -0
- package/dist/crypto.js.map +1 -1
- package/dist/delegations.d.ts +25 -8
- package/dist/delegations.d.ts.map +1 -1
- package/dist/delegations.js +67 -11
- package/dist/delegations.js.map +1 -1
- package/dist/device/client.d.ts +161 -0
- package/dist/device/client.d.ts.map +1 -0
- package/dist/device/client.js +601 -0
- package/dist/device/client.js.map +1 -0
- package/dist/device/host.d.ts +222 -0
- package/dist/device/host.d.ts.map +1 -0
- package/dist/device/host.js +891 -0
- package/dist/device/host.js.map +1 -0
- package/dist/device/http.d.ts +12 -0
- package/dist/device/http.d.ts.map +1 -0
- package/dist/device/http.js +124 -0
- package/dist/device/http.js.map +1 -0
- package/dist/device/index.d.ts +5 -0
- package/dist/device/index.d.ts.map +1 -0
- package/dist/device/index.js +27 -0
- package/dist/device/index.js.map +1 -0
- package/dist/device/protocol.d.ts +312 -0
- package/dist/device/protocol.d.ts.map +1 -0
- package/dist/device/protocol.js +435 -0
- package/dist/device/protocol.js.map +1 -0
- package/dist/identities.d.ts +9 -2
- package/dist/identities.d.ts.map +1 -1
- package/dist/identities.js +33 -3
- package/dist/identities.js.map +1 -1
- package/dist/identity.d.ts +155 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +196 -0
- package/dist/identity.js.map +1 -0
- package/dist/identityShare.d.ts +129 -0
- package/dist/identityShare.d.ts.map +1 -0
- package/dist/identityShare.js +308 -0
- package/dist/identityShare.js.map +1 -0
- package/dist/ids.d.ts +11 -0
- package/dist/ids.d.ts.map +1 -0
- package/dist/ids.js +17 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -1
- package/dist/reconcile.d.ts +25 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +60 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/recovery.d.ts +51 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +59 -0
- package/dist/recovery.js.map +1 -0
- package/dist/register.d.ts +32 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +65 -0
- package/dist/register.js.map +1 -0
- package/dist/scriptJob.d.ts +92 -0
- package/dist/scriptJob.d.ts.map +1 -0
- package/dist/scriptJob.js +270 -0
- package/dist/scriptJob.js.map +1 -0
- package/dist/sessions.d.ts +131 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +240 -0
- package/dist/sessions.js.map +1 -0
- package/dist/socket.d.ts +115 -0
- package/dist/socket.d.ts.map +1 -0
- package/dist/socket.js +1038 -0
- package/dist/socket.js.map +1 -0
- package/dist/webhook.d.ts +627 -28
- package/dist/webhook.d.ts.map +1 -1
- package/dist/webhook.js +1388 -84
- package/dist/webhook.js.map +1 -1
- package/dist/work.d.ts +57 -0
- package/dist/work.d.ts.map +1 -0
- package/dist/work.js +213 -0
- package/dist/work.js.map +1 -0
- package/package.json +26 -4
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fixed set of CLAIM sections an agent may set about itself via
|
|
3
|
+
* `identity.set` in R1. Per the plan (section 2): "Claim sections (name,
|
|
4
|
+
* bio, link, avatar, category, price, funding disclosure) are editable by
|
|
5
|
+
* their subject." Keyed here the way salt-api's registry names them
|
|
6
|
+
* (snake_case, matching the agent's own existing field names where one
|
|
7
|
+
* already exists -- `display_name`, `message_price` -- rather than the
|
|
8
|
+
* plan's prose shorthand).
|
|
9
|
+
*/
|
|
10
|
+
export declare const AGENT_CLAIM_SECTION_KEYS: readonly ["display_name", "bio", "link", "avatar", "category", "message_price", "funding_disclosure"];
|
|
11
|
+
export type AgentClaimSectionKey = (typeof AGENT_CLAIM_SECTION_KEYS)[number];
|
|
12
|
+
/** One line of an agent's "What I can do" list (salt-api 0.107.0): a title of at most 60 characters and an optional one-line detail of at most 120. */
|
|
13
|
+
export interface Capability {
|
|
14
|
+
title: string;
|
|
15
|
+
detail?: string;
|
|
16
|
+
}
|
|
17
|
+
/** At most this many capabilities; salt-api refuses more. */
|
|
18
|
+
export declare const MAX_CAPABILITIES = 5;
|
|
19
|
+
/**
|
|
20
|
+
* What `identity.set` accepts: any subset of the fixed claim vocabulary,
|
|
21
|
+
* each a plain string value, plus `capabilities` -- the agent's "What I can
|
|
22
|
+
* do" list, which is what visitors see on its card and what its A2A card's
|
|
23
|
+
* `skills` are generated from.
|
|
24
|
+
*/
|
|
25
|
+
export type IdentityClaims = Partial<Record<AgentClaimSectionKey, string>> & {
|
|
26
|
+
capabilities?: Capability[];
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The PROOF sections a card or an identity response can carry, for
|
|
30
|
+
* reference -- these are never written through this SDK. Kept here (not
|
|
31
|
+
* just in a comment) so a caller can check `PROOF_SECTION_KEYS.includes(key)`
|
|
32
|
+
* instead of hardcoding the list a second time.
|
|
33
|
+
*/
|
|
34
|
+
export declare const PROOF_SECTION_KEYS: readonly ["pgp_fingerprint", "salt_did", "verified_did", "health", "trust_score", "rail_address"];
|
|
35
|
+
export type ProofSectionKey = (typeof PROOF_SECTION_KEYS)[number];
|
|
36
|
+
export type IdentitySectionKind = "claim" | "proof";
|
|
37
|
+
/**
|
|
38
|
+
* One row of the OWNER's own identity view (`GET /api/v1/identity` /
|
|
39
|
+
* `PATCH /api/v1/identity/sections`) -- richer than what a public card
|
|
40
|
+
* serves, since only the subject (or Salt, for a proof) ever sees `scope`,
|
|
41
|
+
* `editable_by`, `checked_by`.
|
|
42
|
+
*/
|
|
43
|
+
export interface IdentitySection {
|
|
44
|
+
key: string;
|
|
45
|
+
label: string;
|
|
46
|
+
value: string | null;
|
|
47
|
+
/** "everyone" in R1 -- other scopes (`verified contacts`, `named`, `nobody`) ship in R2. */
|
|
48
|
+
scope: string;
|
|
49
|
+
kind: IdentitySectionKind;
|
|
50
|
+
/** Who may edit this section's value -- null/absent for a proof. */
|
|
51
|
+
editable_by?: string | null;
|
|
52
|
+
/** Who checked and signed this section -- null/absent for a claim. */
|
|
53
|
+
checked_by?: string | null;
|
|
54
|
+
}
|
|
55
|
+
export interface IdentitySections {
|
|
56
|
+
sections: IdentitySection[];
|
|
57
|
+
/** The public, signed card this identity is served as -- see `card()`. */
|
|
58
|
+
card_url: string;
|
|
59
|
+
}
|
|
60
|
+
export interface CardSaltIdentity {
|
|
61
|
+
did?: string;
|
|
62
|
+
pgpFingerprint?: string;
|
|
63
|
+
/** Present only once Salt has actually verified a DIFFERENT, externally-verified identity for the subject. */
|
|
64
|
+
verifiedDid?: string;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* One section as it rides on a PUBLIC signed card: just `{key, value,
|
|
68
|
+
* proof}`. `proof` is `null` for a claim; any other value marks a proof
|
|
69
|
+
* section Salt itself checked and signed ("Checked by Salt.", plan section
|
|
70
|
+
* 6) -- this SDK never inspects what shape a non-null proof takes, since
|
|
71
|
+
* that is Salt's business, not the reader's.
|
|
72
|
+
*/
|
|
73
|
+
export interface CardSection {
|
|
74
|
+
key: string;
|
|
75
|
+
value: string | null;
|
|
76
|
+
proof: unknown;
|
|
77
|
+
}
|
|
78
|
+
export interface CardSignatureEntry {
|
|
79
|
+
protected: string;
|
|
80
|
+
signature: string;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The shape `AgentCardSigner.sign` produces: an A2A AgentCard (or, once
|
|
84
|
+
* `GET /api/v1/users/:username/card.json` ships, the same shape for a
|
|
85
|
+
* person) plus `sections` and, when a signing key is configured,
|
|
86
|
+
* `signatures`. Left open (`[key: string]: unknown`) for every other A2A
|
|
87
|
+
* field (`name`, `description`, `supportedInterfaces`, `capabilities`,
|
|
88
|
+
* `skills`, ...) this module has no reason to type narrowly.
|
|
89
|
+
*/
|
|
90
|
+
export interface SignedCard {
|
|
91
|
+
saltIdentity?: CardSaltIdentity;
|
|
92
|
+
sections?: CardSection[];
|
|
93
|
+
signatures?: CardSignatureEntry[];
|
|
94
|
+
[key: string]: unknown;
|
|
95
|
+
}
|
|
96
|
+
/** Thrown by `verifySignedCard` (and so by `client.card()`) for any card whose signature this SDK cannot confirm -- untrusted, tampered, unsigned, or signed by a key this deployment doesn't publish. Never returned as `verified: false`; a card either verifies or this throws. */
|
|
97
|
+
export declare class IdentityCardInvalidError extends Error {
|
|
98
|
+
constructor(message: string);
|
|
99
|
+
}
|
|
100
|
+
/** One entry of the Web Bot Auth key directory (`/.well-known/http-message-signatures-directory`) -- see salt-api's `SaltSigningKey#public_jwk`. */
|
|
101
|
+
export interface Ed25519Jwk {
|
|
102
|
+
kty: string;
|
|
103
|
+
crv: string;
|
|
104
|
+
kid?: string;
|
|
105
|
+
x: string;
|
|
106
|
+
}
|
|
107
|
+
export declare class JcsUnsupportedValueError extends Error {
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Canonicalizes `value` exactly the way salt-api's `Jcs.canonicalize` does:
|
|
111
|
+
* object keys sorted by UTF-16 code unit (plain `Array#sort` on strings
|
|
112
|
+
* already does this in JS, matching Ruby's default `String#<=>` for the
|
|
113
|
+
* ASCII-only keys a card uses), no whitespace, integers as bare digits,
|
|
114
|
+
* strings via JSON string escaping, and a hard refusal on anything else
|
|
115
|
+
* (a non-integer number, undefined, a function) rather than guessing at a
|
|
116
|
+
* serialization another implementation wouldn't match.
|
|
117
|
+
*/
|
|
118
|
+
export declare function canonicalizeJcs(value: unknown): string;
|
|
119
|
+
export declare function base64urlEncode(bytes: Buffer): string;
|
|
120
|
+
export declare function base64urlDecode(str: string): Buffer;
|
|
121
|
+
export interface CardSignatureHeader {
|
|
122
|
+
alg?: string;
|
|
123
|
+
kid?: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Parses (never verifies) `card`'s first signature's protected header --
|
|
127
|
+
* just enough to read `kid` without a network round trip. Used by
|
|
128
|
+
* `client.card()` to notice a kid its cached key set doesn't have (Salt
|
|
129
|
+
* rotated its signing key since the last directory fetch) and force one
|
|
130
|
+
* refetch BEFORE spending a verification attempt that would otherwise fail
|
|
131
|
+
* for a perfectly legitimate card. Returns undefined for a card with no
|
|
132
|
+
* signature at all or an unparseable header -- `verifySignedCard` raises
|
|
133
|
+
* the actual, specific error for those cases at verify time; this helper
|
|
134
|
+
* only ever informs a caching decision.
|
|
135
|
+
*/
|
|
136
|
+
export declare function parseCardSignatureHeader(card: SignedCard): CardSignatureHeader | undefined;
|
|
137
|
+
/**
|
|
138
|
+
* Verifies `card`'s first signature against the Web Bot Auth key directory
|
|
139
|
+
* entries in `jwks`, reconstructing the signing input exactly the way
|
|
140
|
+
* `AgentCardSigner.verify` does server-side: `protected_b64` is reused
|
|
141
|
+
* verbatim from the card (never recomputed -- only the payload is), the
|
|
142
|
+
* payload is the JCS canonicalization of the card with `signatures`
|
|
143
|
+
* removed, and the whole thing is Ed25519-verified with no digest
|
|
144
|
+
* (RFC 8032 pure EdDSA, not Ed25519ph).
|
|
145
|
+
*
|
|
146
|
+
* Throws `IdentityCardInvalidError` for every failure mode -- no signature
|
|
147
|
+
* at all, an unparseable protected header, an unsupported algorithm, no
|
|
148
|
+
* matching published key, or a signature that doesn't match -- so a caller
|
|
149
|
+
* never has to remember to check a boolean before trusting the result. This
|
|
150
|
+
* function itself never refetches anything -- see `parseCardSignatureHeader`
|
|
151
|
+
* for the kid-rotation retry, which happens in client.ts BEFORE this is
|
|
152
|
+
* called a second time with a freshened `jwks`.
|
|
153
|
+
*/
|
|
154
|
+
export declare function verifySignedCard(card: SignedCard, jwks: Ed25519Jwk[]): void;
|
|
155
|
+
//# sourceMappingURL=identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
|
package/dist/identity.js
ADDED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Identity on Salt (design-fleet/runs/2026-09-22-identity/plan.md): the
|
|
3
|
+
// signed card Salt already serves for agents (A2A AgentCard, 0.72.0) made
|
|
4
|
+
// editable, section by section. This is R1 only: `identity.set`/`identity.get`
|
|
5
|
+
// on the SDK surface (plan section 7) -- reading/writing an agent's own
|
|
6
|
+
// CLAIM sections, and fetching + verifying anyone's signed public card.
|
|
7
|
+
// `identity.share` (an E2E slice into a chat) and `onIdentityAsk` are later
|
|
8
|
+
// releases, and there is deliberately no `setScope` here at all: scope is
|
|
9
|
+
// owner-authenticated through the agent-management API only (an agent may
|
|
10
|
+
// state a claim, never decide who else gets to see it).
|
|
11
|
+
//
|
|
12
|
+
// The card vocabulary is fixed (plan section 9.5 -- "like the Cards block
|
|
13
|
+
// vocabulary; a new section is a release"), split into two kinds:
|
|
14
|
+
// - CLAIM sections: the subject's own word about themselves. An agent may
|
|
15
|
+
// set its own claim sections via `identity.set`. Never signed as true --
|
|
16
|
+
// only signed as "this is what they said".
|
|
17
|
+
// - PROOF sections (pgp fingerprint, Salt DID, verified DID, health, trust
|
|
18
|
+
// score, rail address): read-only, computed and signed by Salt itself.
|
|
19
|
+
// No client-side API sets these -- they exist here only so a reader of
|
|
20
|
+
// a fetched card can tell a proof row from a claim row and never launder
|
|
21
|
+
// one as the other (plan section 6: "A proof glyph on a claim row would
|
|
22
|
+
// launder the claim").
|
|
23
|
+
//
|
|
24
|
+
// Card signing (see salt-api's AgentCardSigner + Jcs + SaltSigningKey,
|
|
25
|
+
// read to get these bytes exactly right): a JWS-shaped (RFC 7515)
|
|
26
|
+
// signature over the card's own RFC 8785 canonical JSON (JCS), flattened
|
|
27
|
+
// without a `payload` field -- the payload IS the card itself, minus
|
|
28
|
+
// `signatures`. `canonicalizeJcs` below is a deliberately narrow port of
|
|
29
|
+
// salt-api's Jcs.rb: only what an identity card ever contains (nested
|
|
30
|
+
// objects/arrays, strings, booleans, null, integers), sorted by UTF-16
|
|
31
|
+
// code unit (JS's default string sort already does this for the plain
|
|
32
|
+
// ASCII keys a card uses). A float reaching it is a bug in the caller, so
|
|
33
|
+
// it throws rather than guessing at a serialization another implementation
|
|
34
|
+
// wouldn't match.
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.JcsUnsupportedValueError = exports.IdentityCardInvalidError = exports.PROOF_SECTION_KEYS = exports.MAX_CAPABILITIES = exports.AGENT_CLAIM_SECTION_KEYS = void 0;
|
|
37
|
+
exports.canonicalizeJcs = canonicalizeJcs;
|
|
38
|
+
exports.base64urlEncode = base64urlEncode;
|
|
39
|
+
exports.base64urlDecode = base64urlDecode;
|
|
40
|
+
exports.parseCardSignatureHeader = parseCardSignatureHeader;
|
|
41
|
+
exports.verifySignedCard = verifySignedCard;
|
|
42
|
+
const node_crypto_1 = require("node:crypto");
|
|
43
|
+
// --- Section vocabulary --------------------------------------------------
|
|
44
|
+
/**
|
|
45
|
+
* The fixed set of CLAIM sections an agent may set about itself via
|
|
46
|
+
* `identity.set` in R1. Per the plan (section 2): "Claim sections (name,
|
|
47
|
+
* bio, link, avatar, category, price, funding disclosure) are editable by
|
|
48
|
+
* their subject." Keyed here the way salt-api's registry names them
|
|
49
|
+
* (snake_case, matching the agent's own existing field names where one
|
|
50
|
+
* already exists -- `display_name`, `message_price` -- rather than the
|
|
51
|
+
* plan's prose shorthand).
|
|
52
|
+
*/
|
|
53
|
+
exports.AGENT_CLAIM_SECTION_KEYS = [
|
|
54
|
+
"display_name",
|
|
55
|
+
"bio",
|
|
56
|
+
"link",
|
|
57
|
+
"avatar",
|
|
58
|
+
"category",
|
|
59
|
+
"message_price",
|
|
60
|
+
"funding_disclosure",
|
|
61
|
+
];
|
|
62
|
+
/** At most this many capabilities; salt-api refuses more. */
|
|
63
|
+
exports.MAX_CAPABILITIES = 5;
|
|
64
|
+
/**
|
|
65
|
+
* The PROOF sections a card or an identity response can carry, for
|
|
66
|
+
* reference -- these are never written through this SDK. Kept here (not
|
|
67
|
+
* just in a comment) so a caller can check `PROOF_SECTION_KEYS.includes(key)`
|
|
68
|
+
* instead of hardcoding the list a second time.
|
|
69
|
+
*/
|
|
70
|
+
exports.PROOF_SECTION_KEYS = [
|
|
71
|
+
"pgp_fingerprint",
|
|
72
|
+
"salt_did",
|
|
73
|
+
"verified_did",
|
|
74
|
+
"health",
|
|
75
|
+
"trust_score",
|
|
76
|
+
"rail_address",
|
|
77
|
+
];
|
|
78
|
+
/** Thrown by `verifySignedCard` (and so by `client.card()`) for any card whose signature this SDK cannot confirm -- untrusted, tampered, unsigned, or signed by a key this deployment doesn't publish. Never returned as `verified: false`; a card either verifies or this throws. */
|
|
79
|
+
class IdentityCardInvalidError extends Error {
|
|
80
|
+
constructor(message) {
|
|
81
|
+
super(message);
|
|
82
|
+
this.name = "IdentityCardInvalid";
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exports.IdentityCardInvalidError = IdentityCardInvalidError;
|
|
86
|
+
// --- RFC 8785 JCS (narrow port of salt-api's Jcs.rb) ---------------------
|
|
87
|
+
class JcsUnsupportedValueError extends Error {
|
|
88
|
+
}
|
|
89
|
+
exports.JcsUnsupportedValueError = JcsUnsupportedValueError;
|
|
90
|
+
/**
|
|
91
|
+
* Canonicalizes `value` exactly the way salt-api's `Jcs.canonicalize` does:
|
|
92
|
+
* object keys sorted by UTF-16 code unit (plain `Array#sort` on strings
|
|
93
|
+
* already does this in JS, matching Ruby's default `String#<=>` for the
|
|
94
|
+
* ASCII-only keys a card uses), no whitespace, integers as bare digits,
|
|
95
|
+
* strings via JSON string escaping, and a hard refusal on anything else
|
|
96
|
+
* (a non-integer number, undefined, a function) rather than guessing at a
|
|
97
|
+
* serialization another implementation wouldn't match.
|
|
98
|
+
*/
|
|
99
|
+
function canonicalizeJcs(value) {
|
|
100
|
+
if (value === null)
|
|
101
|
+
return "null";
|
|
102
|
+
if (typeof value === "boolean")
|
|
103
|
+
return value ? "true" : "false";
|
|
104
|
+
if (typeof value === "string")
|
|
105
|
+
return JSON.stringify(value);
|
|
106
|
+
if (typeof value === "number") {
|
|
107
|
+
if (!Number.isInteger(value)) {
|
|
108
|
+
throw new JcsUnsupportedValueError(`canonicalizeJcs: unsupported non-integer number ${value}`);
|
|
109
|
+
}
|
|
110
|
+
return String(value);
|
|
111
|
+
}
|
|
112
|
+
if (Array.isArray(value)) {
|
|
113
|
+
return "[" + value.map((v) => canonicalizeJcs(v)).join(",") + "]";
|
|
114
|
+
}
|
|
115
|
+
if (typeof value === "object") {
|
|
116
|
+
const obj = value;
|
|
117
|
+
const keys = Object.keys(obj).sort();
|
|
118
|
+
return "{" + keys.map((k) => `${JSON.stringify(k)}:${canonicalizeJcs(obj[k])}`).join(",") + "}";
|
|
119
|
+
}
|
|
120
|
+
throw new JcsUnsupportedValueError(`canonicalizeJcs: unsupported value of type ${typeof value}`);
|
|
121
|
+
}
|
|
122
|
+
// --- base64url (no padding), matching SaltSigningKey.b64/unb64 ----------
|
|
123
|
+
function base64urlEncode(bytes) {
|
|
124
|
+
return bytes.toString("base64url");
|
|
125
|
+
}
|
|
126
|
+
function base64urlDecode(str) {
|
|
127
|
+
return Buffer.from(str, "base64url");
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Parses (never verifies) `card`'s first signature's protected header --
|
|
131
|
+
* just enough to read `kid` without a network round trip. Used by
|
|
132
|
+
* `client.card()` to notice a kid its cached key set doesn't have (Salt
|
|
133
|
+
* rotated its signing key since the last directory fetch) and force one
|
|
134
|
+
* refetch BEFORE spending a verification attempt that would otherwise fail
|
|
135
|
+
* for a perfectly legitimate card. Returns undefined for a card with no
|
|
136
|
+
* signature at all or an unparseable header -- `verifySignedCard` raises
|
|
137
|
+
* the actual, specific error for those cases at verify time; this helper
|
|
138
|
+
* only ever informs a caching decision.
|
|
139
|
+
*/
|
|
140
|
+
function parseCardSignatureHeader(card) {
|
|
141
|
+
const sigEntry = card.signatures?.[0];
|
|
142
|
+
if (!sigEntry?.protected)
|
|
143
|
+
return undefined;
|
|
144
|
+
try {
|
|
145
|
+
return JSON.parse(base64urlDecode(sigEntry.protected).toString("utf8"));
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Verifies `card`'s first signature against the Web Bot Auth key directory
|
|
153
|
+
* entries in `jwks`, reconstructing the signing input exactly the way
|
|
154
|
+
* `AgentCardSigner.verify` does server-side: `protected_b64` is reused
|
|
155
|
+
* verbatim from the card (never recomputed -- only the payload is), the
|
|
156
|
+
* payload is the JCS canonicalization of the card with `signatures`
|
|
157
|
+
* removed, and the whole thing is Ed25519-verified with no digest
|
|
158
|
+
* (RFC 8032 pure EdDSA, not Ed25519ph).
|
|
159
|
+
*
|
|
160
|
+
* Throws `IdentityCardInvalidError` for every failure mode -- no signature
|
|
161
|
+
* at all, an unparseable protected header, an unsupported algorithm, no
|
|
162
|
+
* matching published key, or a signature that doesn't match -- so a caller
|
|
163
|
+
* never has to remember to check a boolean before trusting the result. This
|
|
164
|
+
* function itself never refetches anything -- see `parseCardSignatureHeader`
|
|
165
|
+
* for the kid-rotation retry, which happens in client.ts BEFORE this is
|
|
166
|
+
* called a second time with a freshened `jwks`.
|
|
167
|
+
*/
|
|
168
|
+
function verifySignedCard(card, jwks) {
|
|
169
|
+
const sigEntry = card.signatures?.[0];
|
|
170
|
+
if (!sigEntry || !sigEntry.protected || !sigEntry.signature) {
|
|
171
|
+
throw new IdentityCardInvalidError("This card carries no signature -- Salt has not signed it (signing may be unconfigured on this deployment, or this isn't really a Salt identity card).");
|
|
172
|
+
}
|
|
173
|
+
const header = parseCardSignatureHeader(card);
|
|
174
|
+
if (!header) {
|
|
175
|
+
throw new IdentityCardInvalidError("This card's signature header could not be parsed.");
|
|
176
|
+
}
|
|
177
|
+
if (header.alg !== "EdDSA") {
|
|
178
|
+
throw new IdentityCardInvalidError(`This card is signed with an unsupported algorithm (${header.alg ?? "none"}); only EdDSA (Ed25519) is trusted.`);
|
|
179
|
+
}
|
|
180
|
+
const key = jwks.find((k) => k.kid === header.kid && k.kty === "OKP" && k.crv === "Ed25519");
|
|
181
|
+
if (!key) {
|
|
182
|
+
throw new IdentityCardInvalidError(`No published Salt key matches this card's signing key id (${header.kid ?? "unknown"}).`);
|
|
183
|
+
}
|
|
184
|
+
const { signatures: _signatures, ...unsigned } = card;
|
|
185
|
+
const payloadB64 = base64urlEncode(Buffer.from(canonicalizeJcs(unsigned), "utf8"));
|
|
186
|
+
const signingInput = Buffer.from(`${sigEntry.protected}.${payloadB64}`, "utf8");
|
|
187
|
+
const signatureBytes = base64urlDecode(sigEntry.signature);
|
|
188
|
+
const publicKey = (0, node_crypto_1.createPublicKey)({ key: { kty: "OKP", crv: "Ed25519", x: key.x }, format: "jwk" });
|
|
189
|
+
// No digest -- Ed25519 (pure EdDSA) signs the message directly, mirroring
|
|
190
|
+
// SaltSigningKey#sign/#verify server-side (`@pkey.sign(nil, message)`).
|
|
191
|
+
const ok = (0, node_crypto_1.verify)(null, signingInput, publicKey, signatureBytes);
|
|
192
|
+
if (!ok) {
|
|
193
|
+
throw new IdentityCardInvalidError("This card's signature does not match its contents -- it may have been tampered with.");
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
//# sourceMappingURL=identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import type { IdentityDisclosure, SaltClient } from "./client";
|
|
2
|
+
import { type CardSection } from "./identity.js";
|
|
3
|
+
import type { AgentIdentity } from "./identities";
|
|
4
|
+
import { type SaltId } from "./ids.js";
|
|
5
|
+
/** Every SALT-IDENTITY-* marker starts with this -- webhook.ts checks it before attempting the more specific parse, the same way it gates on delegations.FLOOR_REQUEST_MARKER. */
|
|
6
|
+
export declare const IDENTITY_MARKER_PREFIX = "[[SALT-IDENTITY-";
|
|
7
|
+
export interface IdentitySlicePayload {
|
|
8
|
+
sections: CardSection[];
|
|
9
|
+
signature: string;
|
|
10
|
+
}
|
|
11
|
+
export type ParsedIdentityMarker = {
|
|
12
|
+
kind: "ask";
|
|
13
|
+
id: string;
|
|
14
|
+
keys: string[];
|
|
15
|
+
text?: string;
|
|
16
|
+
} | {
|
|
17
|
+
kind: "slice";
|
|
18
|
+
id: string;
|
|
19
|
+
askId?: string;
|
|
20
|
+
payload: IdentitySlicePayload;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "decline";
|
|
23
|
+
id: string;
|
|
24
|
+
askId?: string;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "revoke";
|
|
27
|
+
id: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Parses one SALT-IDENTITY-* marker (plus, for SLICE, its JSON line) out of
|
|
31
|
+
* a decrypted plaintext. Returns null for anything that isn't one of these
|
|
32
|
+
* four markers, or that starts as one but is malformed (a bad id, an ASK
|
|
33
|
+
* with no keys, a SLICE whose JSON doesn't parse into {sections,
|
|
34
|
+
* signature}) -- webhook.ts treats either case as "starts with the prefix
|
|
35
|
+
* but nothing usable came out of it" and drops the message rather than
|
|
36
|
+
* guessing.
|
|
37
|
+
*/
|
|
38
|
+
export declare function parseIdentityMarker(plaintext: string): ParsedIdentityMarker | null;
|
|
39
|
+
/** `[[SALT-IDENTITY-ASK id=… keys=k1,k2]]`, optionally followed by a text line. */
|
|
40
|
+
export declare function formatIdentityAsk(id: string, keys: string[], text?: string): string;
|
|
41
|
+
/** `[[SALT-IDENTITY-SLICE id=… [ask=…]]]` followed by the {sections, signature} JSON line. */
|
|
42
|
+
export declare function formatIdentitySlice(id: string, sections: CardSection[], signature: string, askId?: string): string;
|
|
43
|
+
/** `[[SALT-IDENTITY-DECLINE id=… [ask=…]]]`. */
|
|
44
|
+
export declare function formatIdentityDecline(id: string, askId?: string): string;
|
|
45
|
+
/** `[[SALT-IDENTITY-REVOKE id=…]]`. */
|
|
46
|
+
export declare function formatIdentityRevoke(id: string): string;
|
|
47
|
+
export interface IdentityAskInfo {
|
|
48
|
+
id: string;
|
|
49
|
+
keys: string[];
|
|
50
|
+
text?: string;
|
|
51
|
+
chatId: SaltId;
|
|
52
|
+
from: SaltId;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Handed to `onIdentityAsk`. Return the subset of `info.keys` to share
|
|
56
|
+
* (shares those, replying with a SLICE carrying `ask=info.id`) or
|
|
57
|
+
* `null`/`false` (sends a DECLINE carrying `ask=info.id`). Returning an
|
|
58
|
+
* empty array behaves like declining -- there is nothing to build a slice
|
|
59
|
+
* from. Leaving `onIdentityAsk` unset entirely means an incoming ask is
|
|
60
|
+
* never intercepted at all: it reaches `onMessage` as ordinary text with
|
|
61
|
+
* just the marker line stripped (see webhook.ts), unanswered.
|
|
62
|
+
*/
|
|
63
|
+
export type IdentityAskHandler = (info: IdentityAskInfo) => Promise<string[] | null | false | undefined> | string[] | null | false | undefined;
|
|
64
|
+
export interface IdentitySliceEvent {
|
|
65
|
+
kind: "slice";
|
|
66
|
+
id: string;
|
|
67
|
+
askId?: string;
|
|
68
|
+
from: SaltId;
|
|
69
|
+
chatId: SaltId;
|
|
70
|
+
sections: CardSection[];
|
|
71
|
+
/** True only when the signature verified against the sender's own public key (fetched fresh from the chat's member list). False for a bad/missing signature, an unknown sender key, or a verification that itself failed -- never thrown. */
|
|
72
|
+
verified: boolean;
|
|
73
|
+
}
|
|
74
|
+
export interface IdentityDeclineEvent {
|
|
75
|
+
kind: "decline";
|
|
76
|
+
id: string;
|
|
77
|
+
askId?: string;
|
|
78
|
+
from: SaltId;
|
|
79
|
+
chatId: SaltId;
|
|
80
|
+
}
|
|
81
|
+
export interface IdentityRevokeEvent {
|
|
82
|
+
kind: "revoke";
|
|
83
|
+
id: string;
|
|
84
|
+
from: SaltId;
|
|
85
|
+
chatId: SaltId;
|
|
86
|
+
}
|
|
87
|
+
export type IdentitySharedEvent = IdentitySliceEvent | IdentityDeclineEvent | IdentityRevokeEvent;
|
|
88
|
+
/** Handed every incoming SLICE, DECLINE and REVOKE from someone else -- never called for this identity's own outgoing messages. None of the three ever reach `onMessage`. */
|
|
89
|
+
export type IdentitySharedHandler = (event: IdentitySharedEvent) => Promise<void> | void;
|
|
90
|
+
export interface ShareOptions {
|
|
91
|
+
/** Set when this share answers an incoming SALT-IDENTITY-ASK -- rides on the SLICE marker as `ask=`. */
|
|
92
|
+
ask?: string;
|
|
93
|
+
}
|
|
94
|
+
export interface ShareResult {
|
|
95
|
+
/** Names the whole share -- what rides on the wire SLICE's `id=`, what every ledger row was posted under, and what `revoke(id)` takes to pull it all back at once. */
|
|
96
|
+
id: string;
|
|
97
|
+
messageId: SaltId;
|
|
98
|
+
/** Every non-observer chat member other than the caller this was disclosed to, in the same order client.getChatMembers returned -- one ledger row was written per entry, all under `id`. */
|
|
99
|
+
recipients: SaltId[];
|
|
100
|
+
}
|
|
101
|
+
export interface IdentitySharer {
|
|
102
|
+
/**
|
|
103
|
+
* Shares `keys` from this agent's own identity into `chatId`: ONE fresh
|
|
104
|
+
* id for the whole share, one ledger row posted under it per
|
|
105
|
+
* non-observer member other than the caller (salt-api keys a row on
|
|
106
|
+
* subject + recipient + id, so this is the same id every time; aborts
|
|
107
|
+
* on the first refusal with nothing sent), then ONE signed, encrypted
|
|
108
|
+
* SLICE message carrying that id to the whole chat, then a single
|
|
109
|
+
* message_id PATCH (every row shares the id, so one PATCH reaches all
|
|
110
|
+
* of them).
|
|
111
|
+
*/
|
|
112
|
+
share(caller: AgentIdentity, chatId: SaltId, keys: string[], opts?: ShareOptions): Promise<ShareResult>;
|
|
113
|
+
/** Sends an ASK for `keys` into a 1:1 chat and returns its id. Refuses (before sending anything) outside a 1:1. */
|
|
114
|
+
ask(caller: AgentIdentity, chatId: SaltId, keys: string[], text?: string): Promise<string>;
|
|
115
|
+
/** Sends a bare DECLINE (optionally answering `askId`) with no ledger row -- there is nothing to disclose. Returns the decline message's own id. */
|
|
116
|
+
decline(caller: AgentIdentity, chatId: SaltId, askId?: string): Promise<{
|
|
117
|
+
id: string;
|
|
118
|
+
}>;
|
|
119
|
+
/** This agent's own disclosure ledger, newest first. */
|
|
120
|
+
disclosures(caller: AgentIdentity, opts?: {
|
|
121
|
+
before?: string;
|
|
122
|
+
limit?: number;
|
|
123
|
+
}): Promise<IdentityDisclosure[]>;
|
|
124
|
+
/** Revokes every ledger row under `id` (the id `share()` returned) in one call, then sends a REVOKE marker into the chat it was disclosed in. */
|
|
125
|
+
revoke(caller: AgentIdentity, id: string): Promise<IdentityDisclosure[]>;
|
|
126
|
+
}
|
|
127
|
+
/** Builds the {share, ask, decline, disclosures, revoke} surface bound to one client. */
|
|
128
|
+
export declare function createIdentitySharer(client: SaltClient, pgpPassphrase: string): IdentitySharer;
|
|
129
|
+
//# sourceMappingURL=identityShare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identityShare.d.ts","sourceRoot":"","sources":["../src/identityShare.ts"],"names":[],"mappings":"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"}
|