@openentity/sdk 0.2.0 → 0.3.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/dist/index.d.ts CHANGED
@@ -45,8 +45,9 @@ type VerifyResult = {
45
45
  };
46
46
  /** eddsa-jcs-2022 hashData: sha256(JCS(proof config)) || sha256(JCS(document)). */
47
47
  export declare function hashData(obj: object, config: Omit<Proof, "proofValue">): Uint8Array;
48
- export declare function signProof(obj: object, kp: KeyPair, created?: string): Promise<Proof>;
49
- export declare function signObject<T extends object>(obj: T, kp: KeyPair, created?: string): Promise<T & {
48
+ /** `verificationMethod` defaults to the did:key of `kp`; a did:web signer passes its own method id (for example `did:web:x#key-1`). */
49
+ export declare function signProof(obj: object, kp: KeyPair, created?: string, verificationMethod?: string): Promise<Proof>;
50
+ export declare function signObject<T extends object>(obj: T, kp: KeyPair, created?: string, verificationMethod?: string): Promise<T & {
50
51
  proof: Proof;
51
52
  }>;
52
53
  export declare function verifyProof(obj: object, proof: Proof, resolver?: Resolver): Promise<VerifyResult>;
@@ -74,9 +75,36 @@ export declare function buildDeclaration(input: {
74
75
  name: string;
75
76
  created?: string;
76
77
  }): object;
78
+ /** The successor's unsigned seq 1 Entity Document: `prev` re-keyed, aliases dropped (their proofs name the old EID), `continuity.previous` set. */
79
+ export declare function successorDocument(prev: Record<string, any>, next: KeyPair, created?: string): Record<string, any>;
80
+ /** A Continuity Link signed by both keys (spec 9.2) plus the successor's document signed by the successor: the body of `POST /v1/continuity`. */
81
+ export declare function buildRotation(previous: KeyPair, successor: KeyPair, document: Record<string, any>, o?: {
82
+ basis?: "rotation" | "migration";
83
+ created?: string;
84
+ nonce?: string;
85
+ }): Promise<{
86
+ link: Record<string, any>;
87
+ document: Record<string, any>;
88
+ }>;
89
+ /**
90
+ * Rotate `previous` to a new key in one call: fetch the current document, build and sign the link, mint the stamp for the
91
+ * successor and submit. Nothing is persisted: on success the caller saves `successor` (its `privateJwk`) and only then retires
92
+ * the old key. Throws on any non-2xx answer.
93
+ */
94
+ export declare function rotate(o: {
95
+ previous: KeyPair;
96
+ registry?: string;
97
+ successor?: KeyPair;
98
+ basis?: "rotation" | "migration";
99
+ }): Promise<{
100
+ successor: KeyPair;
101
+ link: Record<string, any>;
102
+ document: Record<string, any>;
103
+ response: any;
104
+ }>;
77
105
  /** sha256 hex of the canonical entry INCLUDING its proof: the next entry's `prev` (spec 7.4). */
78
106
  export declare function recordEntryHash(entry: object): Promise<string>;
79
- type ObjectType = "EntityDocument" | "Declaration" | "Withdrawal" | "RecordEntry" | "Attestation" | "Revocation" | "ContinuityLink" | "Dispute" | "Presentation" | "LogLeaf";
107
+ type ObjectType = "EntityDocument" | "Declaration" | "Withdrawal" | "Redaction" | "RecordEntry" | "Attestation" | "Revocation" | "ContinuityLink" | "Dispute" | "Presentation" | "LogLeaf";
80
108
  /** Schema check (spec Appendix A) plus size caps: 16 KB for a RecordEntry (7.4), 64 KB for anything else (5.2). */
81
109
  export declare function validate(type: ObjectType, obj: unknown): {
82
110
  ok: boolean;
@@ -132,4 +160,52 @@ export declare function verifyPresentation(p: any, opts: {
132
160
  errors: string[];
133
161
  attestations: AttestationCheck[];
134
162
  }>;
163
+ export declare const A2A_EXTENSION_URI = "https://openentity.org/spec/1.0";
164
+ /** The AgentExtension entry that carries an EID in an A2A Agent Card's `capabilities.extensions`. */
165
+ export declare function a2aExtension(eid: string, documentUrl: string): {
166
+ uri: string;
167
+ description: string;
168
+ required: boolean;
169
+ params: {
170
+ eid: string;
171
+ document: string;
172
+ };
173
+ };
174
+ /** A full A2A AgentCard for an Entity Document: each capability slug becomes a skill. `url` is the agent's A2A endpoint. */
175
+ export declare function agentCard(doc: {
176
+ eid: string;
177
+ name: string;
178
+ description: string;
179
+ capabilities?: string[];
180
+ }, opts: {
181
+ url: string;
182
+ documentUrl: string;
183
+ version?: string;
184
+ }): {
185
+ name: string;
186
+ description: string;
187
+ url: string;
188
+ version: string;
189
+ capabilities: {
190
+ streaming: boolean;
191
+ pushNotifications: boolean;
192
+ extensions: {
193
+ uri: string;
194
+ description: string;
195
+ required: boolean;
196
+ params: {
197
+ eid: string;
198
+ document: string;
199
+ };
200
+ }[];
201
+ };
202
+ defaultInputModes: string[];
203
+ defaultOutputModes: string[];
204
+ skills: {
205
+ id: string;
206
+ name: string;
207
+ description: string;
208
+ tags: string[];
209
+ }[];
210
+ };
135
211
  export {};
package/dist/index.js CHANGED
@@ -939,6 +939,46 @@ var openentity_1_0_default = {
939
939
  }
940
940
  ]
941
941
  },
942
+ Redaction: {
943
+ type: "object",
944
+ required: [
945
+ "spec",
946
+ "type",
947
+ "eid",
948
+ "seq",
949
+ "entry_sha256",
950
+ "created",
951
+ "nonce",
952
+ "proof"
953
+ ],
954
+ properties: {
955
+ spec: {
956
+ $ref: "#/$defs/spec"
957
+ },
958
+ type: {
959
+ const: "Redaction"
960
+ },
961
+ eid: {
962
+ $ref: "#/$defs/did"
963
+ },
964
+ seq: {
965
+ type: "integer",
966
+ minimum: 1
967
+ },
968
+ entry_sha256: {
969
+ $ref: "#/$defs/hex64"
970
+ },
971
+ created: {
972
+ $ref: "#/$defs/timestamp"
973
+ },
974
+ nonce: {
975
+ $ref: "#/$defs/nonce"
976
+ },
977
+ proof: {
978
+ $ref: "#/$defs/proof"
979
+ }
980
+ }
981
+ },
942
982
  Attestation: {
943
983
  type: "object",
944
984
  required: [
@@ -1355,19 +1395,19 @@ function unsecured(obj) {
1355
1395
  function hashData(obj, config) {
1356
1396
  return concat(sha256Sync(canonicalize(config)), sha256Sync(canonicalize(unsecured(obj))));
1357
1397
  }
1358
- async function signProof(obj, kp, created = nowSeconds()) {
1398
+ async function signProof(obj, kp, created = nowSeconds(), verificationMethod = verificationMethodId(kp.did)) {
1359
1399
  const config = {
1360
1400
  type: "DataIntegrityProof",
1361
1401
  cryptosuite: "eddsa-jcs-2022",
1362
1402
  created,
1363
- verificationMethod: verificationMethodId(kp.did),
1403
+ verificationMethod,
1364
1404
  proofPurpose: "assertionMethod"
1365
1405
  };
1366
1406
  const sig = new Uint8Array(await crypto.subtle.sign({ name: "Ed25519" }, kp.privateKey, hashData(obj, config)));
1367
1407
  return { ...config, proofValue: "z" + base58btcEncode(sig) };
1368
1408
  }
1369
- async function signObject(obj, kp, created) {
1370
- return { ...obj, proof: await signProof(obj, kp, created) };
1409
+ async function signObject(obj, kp, created, verificationMethod) {
1410
+ return { ...obj, proof: await signProof(obj, kp, created, verificationMethod) };
1371
1411
  }
1372
1412
  async function verifyProof(obj, proof, resolver = defaultResolver) {
1373
1413
  try {
@@ -1462,6 +1502,43 @@ function buildDeclaration(input) {
1462
1502
  nonce: randomNonce()
1463
1503
  };
1464
1504
  }
1505
+ function successorDocument(prev, next, created = nowSeconds()) {
1506
+ const { proof: _p, aliases: _a, ...d } = structuredClone(prev);
1507
+ return {
1508
+ ...d,
1509
+ eid: next.did,
1510
+ keys: [{ id: verificationMethodId(next.did), type: "Multikey", publicKeyMultibase: next.did.slice("did:key:".length) }],
1511
+ created,
1512
+ updated: created,
1513
+ seq: 1,
1514
+ continuity: { ...d.continuity, previous: prev.eid }
1515
+ };
1516
+ }
1517
+ async function buildRotation(previous, successor, document, o = {}) {
1518
+ const created = o.created ?? nowSeconds();
1519
+ const body = { spec: SPEC, type: "ContinuityLink", previous: previous.did, successor: successor.did, basis: o.basis ?? "rotation", created, nonce: o.nonce ?? randomNonce() };
1520
+ const link = { ...body, proofs: [await signProof(body, previous, created), await signProof(body, successor, created)] };
1521
+ return { link, document: await signObject(document, successor, created) };
1522
+ }
1523
+ async function rotate(o) {
1524
+ const registry = (o.registry ?? "https://openentity.org").replace(/\/+$/, "");
1525
+ const call = async (path2, init) => {
1526
+ const r = await fetch(registry + path2, init);
1527
+ const text = await r.text();
1528
+ if (!r.ok) throw new Error(`registry ${r.status} for ${path2}: ${text.slice(0, 200)}`);
1529
+ return JSON.parse(text);
1530
+ };
1531
+ const next = o.successor ?? await generateKeyPair();
1532
+ const prevDoc = await call(`/v1/entities/${o.previous.did}/document`);
1533
+ const { link, document } = await buildRotation(o.previous, next, successorDocument(prevDoc, next), { basis: o.basis });
1534
+ const { stamp_bits } = await call("/v1/spec");
1535
+ const response = await call("/v1/continuity", {
1536
+ method: "POST",
1537
+ headers: { "content-type": "application/json", "x-oe-stamp": await mintStamp(stamp_bits, next.did) },
1538
+ body: JSON.stringify({ link, document })
1539
+ });
1540
+ return { successor: next, link, document, response };
1541
+ }
1465
1542
  async function recordEntryHash(entry) {
1466
1543
  return sha256Hex(canonicalize(entry));
1467
1544
  }
@@ -1680,16 +1757,39 @@ async function verifyPresentation(p, opts) {
1680
1757
  }
1681
1758
  return { ok: errors.length === 0, eid, errors, attestations };
1682
1759
  }
1760
+ var A2A_EXTENSION_URI = "https://openentity.org/spec/1.0";
1761
+ function a2aExtension(eid, documentUrl) {
1762
+ return { uri: A2A_EXTENSION_URI, description: "Open Entity identity (OEIS-1) of this agent", required: false, params: { eid, document: documentUrl } };
1763
+ }
1764
+ function agentCard(doc, opts) {
1765
+ return {
1766
+ name: doc.name,
1767
+ description: doc.description,
1768
+ url: opts.url,
1769
+ version: opts.version ?? "1.0.0",
1770
+ capabilities: { streaming: false, pushNotifications: false, extensions: [a2aExtension(doc.eid, opts.documentUrl)] },
1771
+ defaultInputModes: ["text/plain"],
1772
+ defaultOutputModes: ["text/plain"],
1773
+ skills: (doc.capabilities ?? []).map((slug) => {
1774
+ const [ns, name] = slug.includes(":") ? slug.split(":", 2) : [void 0, slug];
1775
+ return { id: slug, name: name.replace(/[-.]/g, " "), description: `Self-declared capability: ${slug}`, tags: ns ? [ns, name] : [name] };
1776
+ })
1777
+ };
1778
+ }
1683
1779
  export {
1780
+ A2A_EXTENSION_URI,
1684
1781
  DECLARATION_SHA256,
1685
1782
  DECLARATION_TEXT,
1686
1783
  DECLARATION_VERSION,
1687
1784
  SPEC,
1785
+ a2aExtension,
1786
+ agentCard,
1688
1787
  base58btcDecode,
1689
1788
  base58btcEncode,
1690
1789
  buildDeclaration,
1691
1790
  buildDocument,
1692
1791
  buildPresentation,
1792
+ buildRotation,
1693
1793
  canonicalize,
1694
1794
  checkStamp,
1695
1795
  checkTimestamp,
@@ -1714,11 +1814,13 @@ export {
1714
1814
  randomNonce,
1715
1815
  recordEntryHash,
1716
1816
  recoverEip712,
1817
+ rotate,
1717
1818
  sha256,
1718
1819
  sha256Hex,
1719
1820
  signNote,
1720
1821
  signObject,
1721
1822
  signProof,
1823
+ successorDocument,
1722
1824
  validate,
1723
1825
  verificationMethodId,
1724
1826
  verifyConsistency,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openentity/sdk",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Reference TypeScript SDK for the Open Entity Identity Standard (OEIS-1)",
5
5
  "license": "MIT",
6
6
  "type": "module",