inamprotocol 0.1.0 → 0.3.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 +31 -1
- package/dist/client.d.ts +25 -1
- package/dist/client.js +42 -0
- package/dist/client.js.map +1 -1
- package/dist/core/verificationContent.d.ts +25 -0
- package/dist/core/verificationContent.js +14 -0
- package/dist/core/verificationContent.js.map +1 -0
- package/dist/crypto/canonical.d.ts +11 -0
- package/dist/crypto/canonical.js +14 -0
- package/dist/crypto/canonical.js.map +1 -1
- package/dist/crypto/keys.d.ts +6 -0
- package/dist/crypto/keys.js +17 -0
- package/dist/crypto/keys.js.map +1 -1
- package/dist/crypto/p256.d.ts +21 -0
- package/dist/crypto/p256.js +18 -0
- package/dist/crypto/p256.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +35 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -40,9 +40,39 @@ const receipt = await worker.submitWork(poster.did, {
|
|
|
40
40
|
await poster.acceptWork(receipt); // finalizes the receipt and auto-completes the job
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
`poster.cancelJob(job.jobId)` cancels a not-yet-completed job (poster only); `client.getJob(id)` / `client.searchJobs({ capability, status })` / `client.listOffers(jobId)` round out discovery.
|
|
44
|
+
|
|
45
|
+
### External identity linking (challenge-response)
|
|
46
|
+
|
|
47
|
+
Linking a key-derived external identity (`agentpass_id` / `aitp_id` / `passport_id`; SPEC.md §2.1) requires proving control of that external key via a single-use, ~60s challenge — a bare claim is no longer enough. `a2a_endpoint` isn't key-derived, so it skips straight to `linkIdentity(protocol, value)`.
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// externalKeypair stands in for whatever key AgentPass/AITP/Passport Alliance
|
|
51
|
+
// already issued this agent -- not an INAM keypair.
|
|
52
|
+
const challenge = await client.requestLinkChallenge("agentpass_id", toBase64(externalKeypair.publicKey), "ed25519");
|
|
53
|
+
const proof = toBase64(sign(fromHex(challenge.challenge), externalKeypair.privateKey));
|
|
54
|
+
await client.completeLink("agentpass_id", "ap_my_external_id", challenge.challengeId, proof);
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Verification (independent attestation)
|
|
58
|
+
|
|
59
|
+
A third party — anyone but the receipt's own worker (`agentB`) — can attest that a finalized receipt's output actually holds up (SPEC.md §12), feeding a reputation boost:
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const verification = await verifierClient.submitVerification({
|
|
63
|
+
receiptId: receipt.receiptId,
|
|
64
|
+
method: "deterministic", // or "agent_attestation"
|
|
65
|
+
outputHash: receipt.result.outputHash,
|
|
66
|
+
result: "verified", // or "rejected"
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await verifierClient.getVerification(verification.verificationId);
|
|
70
|
+
await verifierClient.listReceiptVerifications(receipt.receiptId);
|
|
71
|
+
```
|
|
72
|
+
|
|
43
73
|
## What's exported
|
|
44
74
|
|
|
45
|
-
`InamClient`, `generateKeypair`/`keypairFromPrivateKey`/`publicKeyToDid`/`didToPublicKey`/`sign`/`verify`/`sha256Hex`, `canonicalize` (the canonical-JSON serializer every INAM signature is computed over), `computeReceiptId`/`buildSignableContent`, and the full set of wire-format types (`AgentRecord`, `ExecutionReceipt`, `JobRecord`, `JobOffer`, `ReputationResult`, ...).
|
|
75
|
+
`InamClient`, `generateKeypair`/`keypairFromPrivateKey`/`publicKeyToDid`/`didToPublicKey`/`sign`/`verify`/`verifyRawEd25519`/`sha256Hex`, `generateP256Keypair`/`p256Sign`/`p256Verify` (used for external-identity link-challenge proofs, SPEC.md §2.1), `canonicalize` (the canonical-JSON serializer every INAM signature is computed over), `computeReceiptId`/`buildSignableContent`, `computeVerificationId`/`buildSignableVerificationContent`, and the full set of wire-format types (`AgentRecord`, `ExecutionReceipt`, `JobRecord`, `JobOffer`, `ReputationResult`, `LinkChallenge`, `VerificationRecord`, ...).
|
|
46
76
|
|
|
47
77
|
## Building from source
|
|
48
78
|
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type Keypair } from "./crypto/keys.js";
|
|
2
2
|
import { type ReceiptContentInput } from "./core/receiptContent.js";
|
|
3
|
-
import
|
|
3
|
+
import { type VerificationContentInput } from "./core/verificationContent.js";
|
|
4
|
+
import type { AgentRecord, ExecutionReceipt, ExternalKeyType, JobOffer, JobRecord, LinkChallenge, ReputationResult, VerificationRecord } from "./types.js";
|
|
4
5
|
/**
|
|
5
6
|
* Minimal reference client — the seed of the future `@inamprotocol/agent-sdk`
|
|
6
7
|
* package. Everything here is transport plumbing plus the two signature
|
|
@@ -16,7 +17,19 @@ export declare class InamClient {
|
|
|
16
17
|
private request;
|
|
17
18
|
registerAgent(capabilities: string[], metadata?: Record<string, unknown>): Promise<AgentRecord>;
|
|
18
19
|
getAgent(id: string): Promise<AgentRecord>;
|
|
20
|
+
/** Links `a2a_endpoint` — the one protocol that isn't a key-derived
|
|
21
|
+
* identity, so there's nothing to prove control of beyond this request's
|
|
22
|
+
* own INAM signature. For `agentpass_id` / `aitp_id` / `passport_id`, use
|
|
23
|
+
* `requestLinkChallenge` + `completeLink` instead. */
|
|
19
24
|
linkIdentity(protocol: string, value: string): Promise<AgentRecord>;
|
|
25
|
+
/** Step 1 of linking a key-derived external identity: request a single-use,
|
|
26
|
+
* ~60s challenge that must be signed with the *external* private key
|
|
27
|
+
* corresponding to `externalPublicKey` (not this INAM keypair). */
|
|
28
|
+
requestLinkChallenge(protocol: string, externalPublicKey: string, keyType: ExternalKeyType): Promise<LinkChallenge>;
|
|
29
|
+
/** Step 2: submit the signed challenge to complete the link. `proofSignature`
|
|
30
|
+
* must be a signature over the raw bytes of `challenge.challenge` (hex-decoded)
|
|
31
|
+
* produced by the external private key, base64-encoded. */
|
|
32
|
+
completeLink(protocol: string, value: string, challengeId: string, proofSignature: string): Promise<AgentRecord>;
|
|
20
33
|
searchAgents(query: {
|
|
21
34
|
capability?: string;
|
|
22
35
|
minReputation?: number;
|
|
@@ -25,6 +38,7 @@ export declare class InamClient {
|
|
|
25
38
|
agents: AgentRecord[];
|
|
26
39
|
}>;
|
|
27
40
|
getReputation(id: string): Promise<ReputationResult>;
|
|
41
|
+
getReceipt(receiptId: string): Promise<ExecutionReceipt>;
|
|
28
42
|
listReceipts(agentId: string): Promise<{
|
|
29
43
|
receipts: ExecutionReceipt[];
|
|
30
44
|
}>;
|
|
@@ -57,4 +71,14 @@ export declare class InamClient {
|
|
|
57
71
|
acceptOffer(jobId: string, agentId: string): Promise<JobRecord>;
|
|
58
72
|
/** Called by the job's poster to cancel a not-yet-completed job. */
|
|
59
73
|
cancelJob(jobId: string): Promise<JobRecord>;
|
|
74
|
+
/** Called by the verifier (who must not be the receipt's own provider/agentB).
|
|
75
|
+
* `jobId`/`provider` are derived from the referenced receipt (fetched here)
|
|
76
|
+
* rather than taken as caller input — the server independently derives the
|
|
77
|
+
* same values and would reject a signature built over the wrong ones, so
|
|
78
|
+
* there's no correct way for a caller to supply them manually anyway. */
|
|
79
|
+
submitVerification(input: Omit<VerificationContentInput, "verifier" | "jobId" | "provider">): Promise<VerificationRecord>;
|
|
80
|
+
getVerification(id: string): Promise<VerificationRecord>;
|
|
81
|
+
listReceiptVerifications(receiptId: string): Promise<{
|
|
82
|
+
verifications: VerificationRecord[];
|
|
83
|
+
}>;
|
|
60
84
|
}
|
package/dist/client.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { canonicalize } from "./crypto/canonical.js";
|
|
2
2
|
import { sha256Hex, sign, toBase64 } from "./crypto/keys.js";
|
|
3
3
|
import { buildSignableContent } from "./core/receiptContent.js";
|
|
4
|
+
import { buildSignableVerificationContent } from "./core/verificationContent.js";
|
|
4
5
|
/**
|
|
5
6
|
* Minimal reference client — the seed of the future `@inamprotocol/agent-sdk`
|
|
6
7
|
* package. Everything here is transport plumbing plus the two signature
|
|
@@ -49,11 +50,31 @@ export class InamClient {
|
|
|
49
50
|
getAgent(id) {
|
|
50
51
|
return this.request("GET", `/v1/agents/${encodeURIComponent(id)}`);
|
|
51
52
|
}
|
|
53
|
+
/** Links `a2a_endpoint` — the one protocol that isn't a key-derived
|
|
54
|
+
* identity, so there's nothing to prove control of beyond this request's
|
|
55
|
+
* own INAM signature. For `agentpass_id` / `aitp_id` / `passport_id`, use
|
|
56
|
+
* `requestLinkChallenge` + `completeLink` instead. */
|
|
52
57
|
linkIdentity(protocol, value) {
|
|
53
58
|
return this.request("POST", `/v1/agents/${encodeURIComponent(this.did)}/link`, { protocol, value }, {
|
|
54
59
|
idempotencyKey: `link:${protocol}:${value}`,
|
|
55
60
|
});
|
|
56
61
|
}
|
|
62
|
+
/** Step 1 of linking a key-derived external identity: request a single-use,
|
|
63
|
+
* ~60s challenge that must be signed with the *external* private key
|
|
64
|
+
* corresponding to `externalPublicKey` (not this INAM keypair). */
|
|
65
|
+
requestLinkChallenge(protocol, externalPublicKey, keyType) {
|
|
66
|
+
return this.request("POST", `/v1/agents/${encodeURIComponent(this.did)}/link/challenge`, { protocol, externalPublicKey, keyType }, {
|
|
67
|
+
idempotencyKey: `link-challenge:${protocol}:${externalPublicKey}:${Date.now()}`,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/** Step 2: submit the signed challenge to complete the link. `proofSignature`
|
|
71
|
+
* must be a signature over the raw bytes of `challenge.challenge` (hex-decoded)
|
|
72
|
+
* produced by the external private key, base64-encoded. */
|
|
73
|
+
completeLink(protocol, value, challengeId, proofSignature) {
|
|
74
|
+
return this.request("POST", `/v1/agents/${encodeURIComponent(this.did)}/link`, { protocol, value, challengeId, proofSignature }, {
|
|
75
|
+
idempotencyKey: `link:${protocol}:${challengeId}`,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
57
78
|
searchAgents(query) {
|
|
58
79
|
const params = new URLSearchParams();
|
|
59
80
|
if (query.capability)
|
|
@@ -67,6 +88,9 @@ export class InamClient {
|
|
|
67
88
|
getReputation(id) {
|
|
68
89
|
return this.request("GET", `/v1/agents/${encodeURIComponent(id)}/reputation`);
|
|
69
90
|
}
|
|
91
|
+
getReceipt(receiptId) {
|
|
92
|
+
return this.request("GET", `/v1/receipts/${encodeURIComponent(receiptId)}`);
|
|
93
|
+
}
|
|
70
94
|
listReceipts(agentId) {
|
|
71
95
|
return this.request("GET", `/v1/agents/${encodeURIComponent(agentId)}/receipts`);
|
|
72
96
|
}
|
|
@@ -129,5 +153,23 @@ export class InamClient {
|
|
|
129
153
|
idempotencyKey: `cancel:${jobId}`,
|
|
130
154
|
});
|
|
131
155
|
}
|
|
156
|
+
// ---- Verification (SPEC.md §12) — independent attestation of a finalized receipt ----
|
|
157
|
+
/** Called by the verifier (who must not be the receipt's own provider/agentB).
|
|
158
|
+
* `jobId`/`provider` are derived from the referenced receipt (fetched here)
|
|
159
|
+
* rather than taken as caller input — the server independently derives the
|
|
160
|
+
* same values and would reject a signature built over the wrong ones, so
|
|
161
|
+
* there's no correct way for a caller to supply them manually anyway. */
|
|
162
|
+
async submitVerification(input) {
|
|
163
|
+
const receipt = await this.getReceipt(input.receiptId);
|
|
164
|
+
const content = buildSignableVerificationContent({ ...input, jobId: receipt.jobId, provider: receipt.agentB.id, verifier: this.did });
|
|
165
|
+
const signature = toBase64(sign(new TextEncoder().encode(canonicalize(content)), this.keypair.privateKey));
|
|
166
|
+
return this.request("POST", "/v1/verifications", { receiptId: input.receiptId, verifier: this.did, method: input.method, outputHash: input.outputHash, result: input.result, score: input.score, evidenceUri: input.evidenceUri, signature }, { idempotencyKey: `verification:${content.verificationId}` });
|
|
167
|
+
}
|
|
168
|
+
getVerification(id) {
|
|
169
|
+
return this.request("GET", `/v1/verifications/${encodeURIComponent(id)}`);
|
|
170
|
+
}
|
|
171
|
+
listReceiptVerifications(receiptId) {
|
|
172
|
+
return this.request("GET", `/v1/receipts/${encodeURIComponent(receiptId)}/verifications`);
|
|
173
|
+
}
|
|
132
174
|
}
|
|
133
175
|
//# sourceMappingURL=client.js.map
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAgB,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAA4B,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { IndependentVerificationMethod, VerificationResult } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pure, dependency-free verification content logic (SPEC.md §12) — same
|
|
4
|
+
* "shared by server and any SDK/client" contract as receiptContent.ts.
|
|
5
|
+
*/
|
|
6
|
+
export interface VerificationContentInput {
|
|
7
|
+
receiptId: string;
|
|
8
|
+
jobId: string;
|
|
9
|
+
provider: string;
|
|
10
|
+
verifier: string;
|
|
11
|
+
method: IndependentVerificationMethod;
|
|
12
|
+
outputHash: string;
|
|
13
|
+
result: VerificationResult;
|
|
14
|
+
score?: number;
|
|
15
|
+
evidenceUri?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Content-addressed, same principle as computeReceiptId (SPEC.md §12.2). */
|
|
18
|
+
export declare function computeVerificationId(input: VerificationContentInput): string;
|
|
19
|
+
/** The exact object shape that must be signed — mirrors buildSignableContent:
|
|
20
|
+
* embeds the already-computed verificationId alongside the fields that were
|
|
21
|
+
* hashed to produce it. */
|
|
22
|
+
export declare function buildSignableVerificationContent(input: VerificationContentInput): {
|
|
23
|
+
verificationVersion: "1.0";
|
|
24
|
+
verificationId: string;
|
|
25
|
+
} & VerificationContentInput;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { canonicalize } from "../crypto/canonical.js";
|
|
2
|
+
import { sha256Hex } from "../crypto/keys.js";
|
|
3
|
+
/** Content-addressed, same principle as computeReceiptId (SPEC.md §12.2). */
|
|
4
|
+
export function computeVerificationId(input) {
|
|
5
|
+
return `sha256:${sha256Hex(canonicalize({ ...input }))}`;
|
|
6
|
+
}
|
|
7
|
+
/** The exact object shape that must be signed — mirrors buildSignableContent:
|
|
8
|
+
* embeds the already-computed verificationId alongside the fields that were
|
|
9
|
+
* hashed to produce it. */
|
|
10
|
+
export function buildSignableVerificationContent(input) {
|
|
11
|
+
const verificationId = computeVerificationId(input);
|
|
12
|
+
return { verificationVersion: "1.0", verificationId, ...input };
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=verificationContent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verificationContent.js","sourceRoot":"","sources":["../../src/core/verificationContent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAoB9C,6EAA6E;AAC7E,MAAM,UAAU,qBAAqB,CAAC,KAA+B;IACnE,OAAO,UAAU,SAAS,CAAC,YAAY,CAAC,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED;;2BAE2B;AAC3B,MAAM,UAAU,gCAAgC,CAAC,KAA+B;IAC9E,MAAM,cAAc,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;IACpD,OAAO,EAAE,mBAAmB,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,KAAK,EAAE,CAAC;AAClE,CAAC"}
|
|
@@ -4,5 +4,16 @@
|
|
|
4
4
|
* not handle every JCS number-formatting edge case, but it is deterministic
|
|
5
5
|
* for the plain string/number/boolean/array/object shapes used by Inam Protocol's own
|
|
6
6
|
* schemas, which is all that's required for our signer and verifier to agree.
|
|
7
|
+
*
|
|
8
|
+
* Number formatting here (via native `JSON.stringify`) already follows the
|
|
9
|
+
* ECMA-262 `Number::toString` algorithm, which is what
|
|
10
|
+
* sdk-python/inamprotocol/canonical.py's `_format_number` was written to
|
|
11
|
+
* replicate byte-for-byte after a real cross-language signature failure
|
|
12
|
+
* (`score: 1.0` verified in Python, rejected here, because Python's own
|
|
13
|
+
* `json.dumps` renders it "1.0" where this renders it "1"). One gap native
|
|
14
|
+
* `JSON.stringify` has that Python's fix doesn't: `JSON.stringify(NaN)` and
|
|
15
|
+
* `JSON.stringify(Infinity)` both silently produce the string `"null"`
|
|
16
|
+
* rather than erroring, which would corrupt a signature without any error on
|
|
17
|
+
* either side — guarded against explicitly below.
|
|
7
18
|
*/
|
|
8
19
|
export declare function canonicalize(value: unknown): string;
|
package/dist/crypto/canonical.js
CHANGED
|
@@ -4,11 +4,25 @@
|
|
|
4
4
|
* not handle every JCS number-formatting edge case, but it is deterministic
|
|
5
5
|
* for the plain string/number/boolean/array/object shapes used by Inam Protocol's own
|
|
6
6
|
* schemas, which is all that's required for our signer and verifier to agree.
|
|
7
|
+
*
|
|
8
|
+
* Number formatting here (via native `JSON.stringify`) already follows the
|
|
9
|
+
* ECMA-262 `Number::toString` algorithm, which is what
|
|
10
|
+
* sdk-python/inamprotocol/canonical.py's `_format_number` was written to
|
|
11
|
+
* replicate byte-for-byte after a real cross-language signature failure
|
|
12
|
+
* (`score: 1.0` verified in Python, rejected here, because Python's own
|
|
13
|
+
* `json.dumps` renders it "1.0" where this renders it "1"). One gap native
|
|
14
|
+
* `JSON.stringify` has that Python's fix doesn't: `JSON.stringify(NaN)` and
|
|
15
|
+
* `JSON.stringify(Infinity)` both silently produce the string `"null"`
|
|
16
|
+
* rather than erroring, which would corrupt a signature without any error on
|
|
17
|
+
* either side — guarded against explicitly below.
|
|
7
18
|
*/
|
|
8
19
|
export function canonicalize(value) {
|
|
9
20
|
return stringify(value);
|
|
10
21
|
}
|
|
11
22
|
function stringify(value) {
|
|
23
|
+
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
24
|
+
throw new Error(`Cannot canonicalize non-finite number: ${value}`);
|
|
25
|
+
}
|
|
12
26
|
if (value === null || typeof value !== "object") {
|
|
13
27
|
return JSON.stringify(value);
|
|
14
28
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/crypto/canonical.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../src/crypto/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IACzC,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,0CAA0C,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;IACpD,CAAC;IACD,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI;SACjB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,OAAO,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;AACvC,CAAC"}
|
package/dist/crypto/keys.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export declare function generateKeypair(): Keypair;
|
|
|
9
9
|
export declare function keypairFromPrivateKey(privateKey: Uint8Array): Keypair;
|
|
10
10
|
export declare function sign(message: Uint8Array, privateKey: Uint8Array): Uint8Array;
|
|
11
11
|
export declare function verify(signature: Uint8Array, message: Uint8Array, did: string): boolean;
|
|
12
|
+
/** Verifies against a raw Ed25519 public key rather than a did:key — for
|
|
13
|
+
* externally-issued identities (e.g. an AgentPass/AITP key) that aren't
|
|
14
|
+
* necessarily encoded as an INAM did:key. */
|
|
15
|
+
export declare function verifyRawEd25519(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean;
|
|
12
16
|
export declare function sha256Hex(data: Uint8Array | string): string;
|
|
13
17
|
export declare function toBase64(bytes: Uint8Array): string;
|
|
14
18
|
export declare function fromBase64(b64: string): Uint8Array;
|
|
19
|
+
export declare function toHex(bytes: Uint8Array): string;
|
|
20
|
+
export declare function fromHex(hex: string): Uint8Array;
|
package/dist/crypto/keys.js
CHANGED
|
@@ -41,6 +41,17 @@ export function verify(signature, message, did) {
|
|
|
41
41
|
return false;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
/** Verifies against a raw Ed25519 public key rather than a did:key — for
|
|
45
|
+
* externally-issued identities (e.g. an AgentPass/AITP key) that aren't
|
|
46
|
+
* necessarily encoded as an INAM did:key. */
|
|
47
|
+
export function verifyRawEd25519(signature, message, publicKey) {
|
|
48
|
+
try {
|
|
49
|
+
return ed25519.verify(signature, message, publicKey);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
44
55
|
export function sha256Hex(data) {
|
|
45
56
|
const bytes = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
46
57
|
return Buffer.from(sha256(bytes)).toString("hex");
|
|
@@ -51,4 +62,10 @@ export function toBase64(bytes) {
|
|
|
51
62
|
export function fromBase64(b64) {
|
|
52
63
|
return new Uint8Array(Buffer.from(b64, "base64"));
|
|
53
64
|
}
|
|
65
|
+
export function toHex(bytes) {
|
|
66
|
+
return Buffer.from(bytes).toString("hex");
|
|
67
|
+
}
|
|
68
|
+
export function fromHex(hex) {
|
|
69
|
+
return new Uint8Array(Buffer.from(hex, "hex"));
|
|
70
|
+
}
|
|
54
71
|
//# sourceMappingURL=keys.js.map
|
package/dist/crypto/keys.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/crypto/keys.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,6EAA6E;AAC7E,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,GAAG,IAAkB,EAAE,EAAE,CACjD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC;AAE3C,qEAAqE;AACrE,MAAM,yBAAyB,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;AAQhE,MAAM,UAAU,cAAc,CAAC,SAAqB;IAClD,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,yBAAyB,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACrF,QAAQ,CAAC,GAAG,CAAC,yBAAyB,EAAE,CAAC,CAAC,CAAC;IAC3C,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,yBAAyB,CAAC,MAAM,CAAC,CAAC;IAC1D,OAAO,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IAC3D,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,qBAAqB,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,UAAsB;IAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;IACnD,OAAO,EAAE,GAAG,EAAE,cAAc,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC;AACnE,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAmB,EAAE,UAAsB;IAC9D,OAAO,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,SAAqB,EAAE,OAAmB,EAAE,GAAW;IAC5E,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;QACtC,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAyB;IACjD,MAAM,KAAK,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAAiB;IACxC,OAAO,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AACpD,CAAC"}
|
|
1
|
+
{"version":3,"file":"keys.js","sourceRoot":"","sources":["../../src/crypto/keys.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ECDSA P-256, used alongside Ed25519 for external-identity challenge proofs
|
|
3
|
+
* (SPEC.md's external-identity linking section) because it's the primary
|
|
4
|
+
* curve mandated by ATTP (draft-sharif-attp-00, the trust-transport protocol
|
|
5
|
+
* AgentPass is built on): "Each agent MUST have a unique ECDSA key pair using
|
|
6
|
+
* the P-256 curve." Not used anywhere else in INAM — the protocol's own
|
|
7
|
+
* did:key identity stays Ed25519-only.
|
|
8
|
+
*
|
|
9
|
+
* `p256.sign`/`p256.verify` already do standard ECDSA-with-SHA256 internally
|
|
10
|
+
* (no manual pre-hashing needed) and return/accept the 64-byte compact r||s
|
|
11
|
+
* encoding — this matches ATTP's wire format exactly: "signature =
|
|
12
|
+
* ECDSA-Sign(SHA-256(challenge), agentPrivateKey)" with "IEEE P1363
|
|
13
|
+
* fixed-length r||s encoding (64 bytes for P-256)".
|
|
14
|
+
*/
|
|
15
|
+
export interface P256Keypair {
|
|
16
|
+
publicKey: Uint8Array;
|
|
17
|
+
privateKey: Uint8Array;
|
|
18
|
+
}
|
|
19
|
+
export declare function generateP256Keypair(): P256Keypair;
|
|
20
|
+
export declare function p256Sign(message: Uint8Array, privateKey: Uint8Array): Uint8Array;
|
|
21
|
+
export declare function p256Verify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { p256 } from "@noble/curves/nist.js";
|
|
2
|
+
export function generateP256Keypair() {
|
|
3
|
+
const privateKey = p256.utils.randomSecretKey();
|
|
4
|
+
const publicKey = p256.getPublicKey(privateKey, true);
|
|
5
|
+
return { privateKey, publicKey };
|
|
6
|
+
}
|
|
7
|
+
export function p256Sign(message, privateKey) {
|
|
8
|
+
return p256.sign(message, privateKey);
|
|
9
|
+
}
|
|
10
|
+
export function p256Verify(signature, message, publicKey) {
|
|
11
|
+
try {
|
|
12
|
+
return p256.verify(signature, message, publicKey);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=p256.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"p256.js","sourceRoot":"","sources":["../../src/crypto/p256.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAsB7C,MAAM,UAAU,mBAAmB;IACjC,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,EAAE,CAAC;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;IACtD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,OAAmB,EAAE,UAAsB;IAClE,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,SAAqB,EAAE,OAAmB,EAAE,SAAqB;IAC1F,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { InamClient } from "./client.js";
|
|
2
|
-
export { generateKeypair, keypairFromPrivateKey, publicKeyToDid, didToPublicKey, sign, verify, sha256Hex, toBase64, fromBase64, type Keypair, } from "./crypto/keys.js";
|
|
2
|
+
export { generateKeypair, keypairFromPrivateKey, publicKeyToDid, didToPublicKey, sign, verify, verifyRawEd25519, sha256Hex, toBase64, fromBase64, toHex, fromHex, type Keypair, } from "./crypto/keys.js";
|
|
3
|
+
export { generateP256Keypair, p256Sign, p256Verify, type P256Keypair } from "./crypto/p256.js";
|
|
3
4
|
export { canonicalize } from "./crypto/canonical.js";
|
|
4
5
|
export { computeReceiptId, buildSignableContent, type ReceiptContentInput } from "./core/receiptContent.js";
|
|
5
|
-
export
|
|
6
|
+
export { computeVerificationId, buildSignableVerificationContent, type VerificationContentInput } from "./core/verificationContent.js";
|
|
7
|
+
export type { LinkedIdentities, ExternalKeyType, LinkChallenge, AgentRecord, VerificationMethod, ReceiptOutcome, ReceiptStatus, DisputeStatus, ExecutionReceipt, SignableReceiptContent, ReputationComponents, ReputationResult, JobStatus, JobOffer, JobRecord, IndependentVerificationMethod, VerificationResult, VerificationRecord, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { InamClient } from "./client.js";
|
|
2
|
-
export { generateKeypair, keypairFromPrivateKey, publicKeyToDid, didToPublicKey, sign, verify, sha256Hex, toBase64, fromBase64, } from "./crypto/keys.js";
|
|
2
|
+
export { generateKeypair, keypairFromPrivateKey, publicKeyToDid, didToPublicKey, sign, verify, verifyRawEd25519, sha256Hex, toBase64, fromBase64, toHex, fromHex, } from "./crypto/keys.js";
|
|
3
|
+
export { generateP256Keypair, p256Sign, p256Verify } from "./crypto/p256.js";
|
|
3
4
|
export { canonicalize } from "./crypto/canonical.js";
|
|
4
5
|
export { computeReceiptId, buildSignableContent } from "./core/receiptContent.js";
|
|
6
|
+
export { computeVerificationId, buildSignableVerificationContent } from "./core/verificationContent.js";
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,IAAI,EACJ,MAAM,EACN,SAAS,EACT,QAAQ,EACR,UAAU,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,IAAI,EACJ,MAAM,EACN,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,UAAU,EACV,KAAK,EACL,OAAO,GAER,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,UAAU,EAAoB,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAA4B,MAAM,0BAA0B,CAAC;AAE5G,OAAO,EAAE,qBAAqB,EAAE,gCAAgC,EAAiC,MAAM,+BAA+B,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -10,6 +10,17 @@ export interface LinkedIdentities {
|
|
|
10
10
|
passport_id?: string;
|
|
11
11
|
a2a_endpoint?: string;
|
|
12
12
|
}
|
|
13
|
+
/** Key type used to prove control of an external identity's public key
|
|
14
|
+
* before linking it (SPEC.md's external-identity linking section). P-256
|
|
15
|
+
* matches ATTP (the protocol AgentPass is built on); Ed25519 is offered as
|
|
16
|
+
* the same primitive INAM's own did:key already uses. */
|
|
17
|
+
export type ExternalKeyType = "ed25519" | "p256";
|
|
18
|
+
/** Response shape from POST /agents/:id/link/challenge. */
|
|
19
|
+
export interface LinkChallenge {
|
|
20
|
+
challengeId: string;
|
|
21
|
+
challenge: string;
|
|
22
|
+
expiresAt: string;
|
|
23
|
+
}
|
|
13
24
|
export interface AgentRecord {
|
|
14
25
|
id: string;
|
|
15
26
|
capabilities: string[];
|
|
@@ -80,6 +91,10 @@ export interface ReputationComponents {
|
|
|
80
91
|
volumeUsd: number;
|
|
81
92
|
stakeUsd: number;
|
|
82
93
|
decayHalfLifeDays: number;
|
|
94
|
+
/** Count of finalized receipts backed by at least one `verified` Verification
|
|
95
|
+
* (SPEC.md §12.5) — distinct from `verifiedReceipts` above, which really
|
|
96
|
+
* means "two-party finalized," not independently attested. */
|
|
97
|
+
attestedReceipts: number;
|
|
83
98
|
}
|
|
84
99
|
export interface ReputationResult {
|
|
85
100
|
trustScore: number;
|
|
@@ -108,3 +123,23 @@ export interface JobRecord {
|
|
|
108
123
|
createdAt: string;
|
|
109
124
|
expiresAt?: string;
|
|
110
125
|
}
|
|
126
|
+
/** SPEC.md §12: independent attestation that a finalized receipt's output
|
|
127
|
+
* actually satisfies its job's requirements. Single verifier, no
|
|
128
|
+
* draft/countersign step — complete and signed on submission. */
|
|
129
|
+
export type IndependentVerificationMethod = "deterministic" | "agent_attestation";
|
|
130
|
+
export type VerificationResult = "verified" | "rejected";
|
|
131
|
+
export interface VerificationRecord {
|
|
132
|
+
verificationVersion: "1.0";
|
|
133
|
+
verificationId: string;
|
|
134
|
+
receiptId: string;
|
|
135
|
+
jobId: string;
|
|
136
|
+
provider: string;
|
|
137
|
+
verifier: string;
|
|
138
|
+
method: IndependentVerificationMethod;
|
|
139
|
+
outputHash: string;
|
|
140
|
+
result: VerificationResult;
|
|
141
|
+
score?: number;
|
|
142
|
+
evidenceUri?: string;
|
|
143
|
+
createdAt: string;
|
|
144
|
+
signature: string;
|
|
145
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inamprotocol",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Reference TypeScript/JavaScript SDK for the INAM Protocol — agent identity, execution receipts, jobs, and reputation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -40,11 +40,13 @@
|
|
|
40
40
|
"prepublishOnly": "npm run build"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
+
"@noble/curves": "^2.3.0",
|
|
43
44
|
"@noble/ed25519": "^2.1.0",
|
|
44
45
|
"@noble/hashes": "^1.5.0",
|
|
45
46
|
"bs58": "^6.0.0"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
49
|
+
"@types/node": "^22.5.0",
|
|
48
50
|
"typescript": "^5.5.4"
|
|
49
51
|
}
|
|
50
52
|
}
|