@agentunion/fastaun-browser 0.5.18 → 0.5.19

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.
Files changed (118) hide show
  1. package/CHANGELOG.md +44 -2
  2. package/_packed_docs/CHANGELOG.md +44 -2
  3. package/_packed_docs/INDEX.md +136 -14
  4. package/_packed_docs/KITE_DOCS_GUIDE.md +42 -16
  5. package/_packed_docs/agent.md/SCHEMA.md +245 -205
  6. package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +42 -15
  7. package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +4 -4
  8. package/_packed_docs/protocol/01-/350/272/253/344/273/275/344/270/216/345/207/255/350/257/201/345/215/217/350/256/256-auth.md +45 -134
  9. package/_packed_docs/protocol/07-/351/224/231/350/257/257/347/240/201/344/270/216/347/212/266/346/200/201/346/234/272.md +5 -20
  10. package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +28 -9
  11. package/_packed_docs/protocol/11-Storage-/345/255/220/345/215/217/350/256/256.md +22 -27
  12. package/_packed_docs/protocol/agent.md/SCHEMA.md +4 -0
  13. package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +5 -2
  14. package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +250 -283
  15. package/_packed_docs/sdk/09-group-rpc-manual.md +46 -14
  16. package/_packed_docs/sdk/09-message-rpc-manual.md +40 -2
  17. package/_packed_docs/sdk/09-storage-rpc-manual.md +74 -64
  18. package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +25 -5
  19. package/_packed_docs/sdk/INDEX.md +76 -17
  20. package/dist/agent-md-schema.d.ts +3 -0
  21. package/dist/agent-md-schema.d.ts.map +1 -1
  22. package/dist/agent-md-schema.js +45 -11
  23. package/dist/agent-md-schema.js.map +1 -1
  24. package/dist/agent-md.d.ts +45 -2
  25. package/dist/agent-md.d.ts.map +1 -1
  26. package/dist/agent-md.js +519 -30
  27. package/dist/agent-md.js.map +1 -1
  28. package/dist/aid-store.d.ts +12 -46
  29. package/dist/aid-store.d.ts.map +1 -1
  30. package/dist/aid-store.js +113 -246
  31. package/dist/aid-store.js.map +1 -1
  32. package/dist/aid.d.ts.map +1 -1
  33. package/dist/aid.js +20 -7
  34. package/dist/aid.js.map +1 -1
  35. package/dist/auth.d.ts +4 -1
  36. package/dist/auth.d.ts.map +1 -1
  37. package/dist/auth.js +343 -23
  38. package/dist/auth.js.map +1 -1
  39. package/dist/bundle.js +37330 -32005
  40. package/dist/cert-utils.d.ts +1 -1
  41. package/dist/cert-utils.d.ts.map +1 -1
  42. package/dist/cert-utils.js +19 -7
  43. package/dist/cert-utils.js.map +1 -1
  44. package/dist/client/delivery.d.ts +15 -1
  45. package/dist/client/delivery.d.ts.map +1 -1
  46. package/dist/client/delivery.js +147 -51
  47. package/dist/client/delivery.js.map +1 -1
  48. package/dist/client/rpc-pipeline.d.ts.map +1 -1
  49. package/dist/client/rpc-pipeline.js +19 -5
  50. package/dist/client/rpc-pipeline.js.map +1 -1
  51. package/dist/client/v2-e2ee.d.ts +1 -0
  52. package/dist/client/v2-e2ee.d.ts.map +1 -1
  53. package/dist/client/v2-e2ee.js +104 -30
  54. package/dist/client/v2-e2ee.js.map +1 -1
  55. package/dist/client.d.ts +100 -1
  56. package/dist/client.d.ts.map +1 -1
  57. package/dist/client.js +1204 -23
  58. package/dist/client.js.map +1 -1
  59. package/dist/errors.d.ts.map +1 -1
  60. package/dist/errors.js +3 -2
  61. package/dist/errors.js.map +1 -1
  62. package/dist/events.d.ts +4 -0
  63. package/dist/events.d.ts.map +1 -1
  64. package/dist/events.js +41 -1
  65. package/dist/events.js.map +1 -1
  66. package/dist/facades.d.ts +82 -2
  67. package/dist/facades.d.ts.map +1 -1
  68. package/dist/facades.js +98 -4
  69. package/dist/facades.js.map +1 -1
  70. package/dist/index.d.ts +7 -3
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +3 -2
  73. package/dist/index.js.map +1 -1
  74. package/dist/keystore/index.d.ts +17 -0
  75. package/dist/keystore/index.d.ts.map +1 -1
  76. package/dist/keystore/indexeddb-shared.d.ts +10 -1
  77. package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
  78. package/dist/keystore/indexeddb-shared.js +111 -0
  79. package/dist/keystore/indexeddb-shared.js.map +1 -1
  80. package/dist/keystore/indexeddb-token-store.d.ts +7 -1
  81. package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
  82. package/dist/keystore/indexeddb-token-store.js +30 -1
  83. package/dist/keystore/indexeddb-token-store.js.map +1 -1
  84. package/dist/org-protocol.d.ts +98 -0
  85. package/dist/org-protocol.d.ts.map +1 -0
  86. package/dist/org-protocol.js +1742 -0
  87. package/dist/org-protocol.js.map +1 -0
  88. package/dist/ownership-proof.d.ts +93 -5
  89. package/dist/ownership-proof.d.ts.map +1 -1
  90. package/dist/ownership-proof.js +239 -53
  91. package/dist/ownership-proof.js.map +1 -1
  92. package/dist/ownership-v21.d.ts +177 -0
  93. package/dist/ownership-v21.d.ts.map +1 -0
  94. package/dist/ownership-v21.js +609 -0
  95. package/dist/ownership-v21.js.map +1 -0
  96. package/dist/ownership-workflow.d.ts +146 -0
  97. package/dist/ownership-workflow.d.ts.map +1 -0
  98. package/dist/ownership-workflow.js +1066 -0
  99. package/dist/ownership-workflow.js.map +1 -0
  100. package/dist/seq-tracker.d.ts +1 -0
  101. package/dist/seq-tracker.d.ts.map +1 -1
  102. package/dist/seq-tracker.js +10 -2
  103. package/dist/seq-tracker.js.map +1 -1
  104. package/dist/tools/cross-sdk-agent.d.ts +82 -0
  105. package/dist/tools/cross-sdk-agent.d.ts.map +1 -1
  106. package/dist/tools/cross-sdk-agent.js +332 -7
  107. package/dist/tools/cross-sdk-agent.js.map +1 -1
  108. package/dist/transport.d.ts +6 -0
  109. package/dist/transport.d.ts.map +1 -1
  110. package/dist/transport.js +88 -2
  111. package/dist/transport.js.map +1 -1
  112. package/dist/v2/e2ee/decrypt.d.ts +1 -0
  113. package/dist/v2/e2ee/decrypt.d.ts.map +1 -1
  114. package/dist/v2/e2ee/decrypt.js +9 -1
  115. package/dist/v2/e2ee/decrypt.js.map +1 -1
  116. package/dist/version.d.ts +1 -1
  117. package/dist/version.js +1 -1
  118. package/package.json +1 -1
@@ -4,9 +4,14 @@ import * as http from 'node:http';
4
4
  import * as https from 'node:https';
5
5
  import * as crypto from 'node:crypto';
6
6
  import * as fs from 'node:fs';
7
- import { URL } from 'node:url';
7
+ import * as path from 'node:path';
8
+ import { URL, fileURLToPath } from 'node:url';
8
9
  import { AID, AIDStore, AUNClient, __version__ } from '../index.js';
9
10
  import { publicKeyFingerprint } from '../cert-utils.js';
11
+ import { StateError } from '../errors.js';
12
+ import { OwnershipStorageAdapter } from '../ownership-v21.js';
13
+ import { ownershipErrorCode, ownershipTaskResult } from '../ownership-workflow.js';
14
+ import { canonicalJson, digest, buildRequestBinding, verifyMembershipBinding, ProtocolError } from '../org-protocol.js';
10
15
  function installNodeBrowserShims() {
11
16
  const root = globalThis;
12
17
  if (!root.WebSocket)
@@ -120,7 +125,7 @@ function envelopeMetadata(data) {
120
125
  out.protected_headers = jsonSafe(protectedHeaders);
121
126
  return out;
122
127
  }
123
- class CrossSdkJsAgent {
128
+ export class CrossSdkJsAgent {
124
129
  language = 'js';
125
130
  sdkVersion = __version__;
126
131
  aid = textOf(process.env.AUN_TEST_AID || `cross-js-${crypto.randomUUID().slice(0, 8)}.agentid.pub`).trim();
@@ -139,6 +144,8 @@ class CrossSdkJsAgent {
139
144
  rpcObservedTransports = new WeakSet();
140
145
  groupChangedEvents = [];
141
146
  groupInviteEvents = [];
147
+ readStateEvents = [];
148
+ ownershipEvents = [];
142
149
  traces = new Map();
143
150
  sendResults = new Map();
144
151
  inlineRealtimePayloadV1 = true;
@@ -178,6 +185,19 @@ class CrossSdkJsAgent {
178
185
  });
179
186
  this.client.on('group.changed', (data) => this.storeGroupChangedPublicEvent(data));
180
187
  this.client.on('group.invite_received', (data) => this.storeGroupInviteEvent(data));
188
+ for (const event of ['message.read_changed', 'group.read_changed', 'read_state_sync']) {
189
+ this.client.on(event, (payload) => { this.readStateEvents.push({ event, payload: jsonSafe(payload) }); });
190
+ }
191
+ for (const event of ['ownership.request', 'ownership.action_required', 'ownership.progress', 'ownership.completed', 'ownership.rejected', 'ownership.stopped', 'ownership.error']) {
192
+ this.client.on(event, (payload) => { this.ownershipEvents.push({ event, payload: jsonSafe(payload) }); });
193
+ }
194
+ for (const suffix of ['join_requested', 'join_approved', 'join_rejected', 'invite_created', 'invite_accepted', 'invite_rejected']) {
195
+ const event = 'org.member.' + suffix;
196
+ this.client.on(event, (value) => {
197
+ const payload = value;
198
+ this.recordTrace(textOf(payload.org_id), { stage: event, payload });
199
+ });
200
+ }
181
201
  }
182
202
  installTransportRpcObserver() {
183
203
  const transport = this.client._transport;
@@ -317,10 +337,38 @@ class CrossSdkJsAgent {
317
337
  '',
318
338
  ].join('\n');
319
339
  }
340
+ async agentMdContentForUpload(aid, name, type, description) {
341
+ let content = '';
342
+ try {
343
+ const manager = this.client._agentMdManager;
344
+ const managed = await Promise.resolve(manager?.readContent?.(aid));
345
+ content = typeof managed === 'string' ? managed : '';
346
+ }
347
+ catch {
348
+ content = '';
349
+ }
350
+ if (content && (content.includes('owner:') || content.includes('ownership_proof:') || content.includes('ownership_release:')))
351
+ return content;
352
+ try {
353
+ content = fs.readFileSync(path.join(this.aunPath, 'AIDs', aid, 'agent.md'), 'utf-8');
354
+ if (content.includes('owner:') || content.includes('ownership_proof:') || content.includes('ownership_release:'))
355
+ return content;
356
+ }
357
+ catch {
358
+ }
359
+ return this.agentMdContent(aid, name, type, description);
360
+ }
320
361
  async ensureConnected(backgroundSync = true) {
321
362
  const store = this.aidStore();
322
363
  try {
323
- const registered = await store.register(this.aid);
364
+ const fixedIdentityFile = textOf(process.env.AUN_TEST_FIXED_IDENTITY_FILE).trim();
365
+ if (fixedIdentityFile) {
366
+ const identity = JSON.parse(fs.readFileSync(fixedIdentityFile, 'utf-8'));
367
+ if (identity.aid !== this.aid)
368
+ throw new Error('固定测试身份与配置 AID 不一致');
369
+ await store._keystore.saveIdentity(this.aid, identity);
370
+ }
371
+ const registered = fixedIdentityFile ? await store.load(this.aid) : await store.register(this.aid, { type: 'service' });
324
372
  if (!registered.ok) {
325
373
  const loaded = await store.load(this.aid);
326
374
  if (!loaded.ok) {
@@ -331,9 +379,16 @@ class CrossSdkJsAgent {
331
379
  if (!loaded.ok) {
332
380
  throw new Error(`load identity failed: ${loaded.error.code}: ${loaded.error.message}`);
333
381
  }
334
- const uploaded = await store.uploadAgentMd(this.aid, this.agentMdContent(this.aid, this.aid, 'agent', 'Cross-SDK JavaScript test agent'));
335
- if (!uploaded.ok) {
336
- throw new Error(`upload agent.md failed: ${uploaded.error.code}: ${uploaded.error.message}`);
382
+ const checked = await store.checkAgentMd(this.aid);
383
+ const localEtag = checked.ok ? String(checked.data.local_etag ?? '').trim() : '';
384
+ const remoteEtag = checked.ok ? String(checked.data.remote_etag ?? '').trim() : '';
385
+ const inSync = Boolean(localEtag && remoteEtag && localEtag === remoteEtag);
386
+ const remoteFound = checked.ok && checked.data.remote_found === true;
387
+ if (!inSync && !remoteFound) {
388
+ const uploaded = await store.uploadAgentMd(this.aid, await this.agentMdContentForUpload(this.aid, this.aid, 'agent', 'Cross-SDK JavaScript test agent'));
389
+ if (!uploaded.ok) {
390
+ throw new Error(`upload agent.md failed: ${uploaded.error.code}: ${uploaded.error.message}`);
391
+ }
337
392
  }
338
393
  let identity = loaded.data.aid;
339
394
  if (this.debug && !identity.debug) {
@@ -439,6 +494,106 @@ class CrossSdkJsAgent {
439
494
  ...envelopeMetadata(data),
440
495
  };
441
496
  }
497
+ async ownershipControl(req, res, action) {
498
+ const body = await readJson(req);
499
+ const required = { bind: ['role', 'peer_aid'], accept: ['operation_id'], reject: ['operation_id'], release: ['sub_aid'], transfer: ['sub_aid', 'new_owner_aid'] };
500
+ const fields = required[action];
501
+ if (!fields || fields.some((key) => typeof body[key] !== 'string' || !textOf(body[key]).trim()) || Object.keys(body).some((key) => !fields.includes(key) && !(action === 'reject' && key === 'reason')) || action === 'reject' && body.reason !== undefined && typeof body.reason !== 'string' || action === 'bind' && !['owner', 'subject'].includes(textOf(body.role))) {
502
+ sendJson(res, 400, { ok: false, error_code: 'bad_request', error_message: 'Ownership 2.1 control parameters are invalid' });
503
+ return;
504
+ }
505
+ try {
506
+ let task;
507
+ switch (action) {
508
+ case 'bind':
509
+ task = body.role === 'owner' ? await this.client.bindSubaid(textOf(body.peer_aid)) : await this.client.bindOwneraid(textOf(body.peer_aid));
510
+ break;
511
+ case 'accept':
512
+ task = await this.client.acceptOwnershipRequest(textOf(body.operation_id));
513
+ break;
514
+ case 'reject':
515
+ task = await this.client.rejectOwnershipRequest(textOf(body.operation_id), body.reason);
516
+ break;
517
+ case 'release':
518
+ task = await this.client.releaseSubaid(textOf(body.sub_aid));
519
+ break;
520
+ default: task = await this.client.transferSubaid(textOf(body.sub_aid), textOf(body.new_owner_aid));
521
+ }
522
+ sendJson(res, 200, { ok: true, operation_id: task.operation_id, task: jsonSafe(task) });
523
+ }
524
+ catch (error) {
525
+ sendJson(res, 500, { ok: false, error_code: ownershipErrorCode(error), error_message: error instanceof Error ? error.message : String(error) });
526
+ }
527
+ }
528
+ async ownershipStatus(url, res) {
529
+ try {
530
+ const internal = this.client;
531
+ if (!internal._tokenStore?.listOwnershipTasks)
532
+ throw new StateError('ownership durable task storage is unavailable', { stringCode: 'persistence_unavailable' });
533
+ const operationId = textOf(url.searchParams.get('operation_id')).trim();
534
+ const requestedSub = textOf(url.searchParams.get('sub_aid')).trim();
535
+ const records = (await internal._tokenStore.listOwnershipTasks(this.aid))
536
+ .map((snapshot) => snapshot.record)
537
+ .filter((record) => (!operationId || record.operation_id === operationId) && (!requestedSub || record.sub_aid === requestedSub))
538
+ .sort((first, second) => second.created_at - first.created_at);
539
+ const publicTask = (record) => {
540
+ const localApproval = { pending: 'pending', accept: 'accepted', reject: 'rejected' }[record.local_decision];
541
+ if (!localApproval || typeof record.initiator_aid !== 'string' || !record.initiator_aid)
542
+ throw new StateError('ownership persisted approval is damaged', { stringCode: 'persistence_unavailable' });
543
+ return { ...ownershipTaskResult(record), initiator_aid: record.initiator_aid, local_approval: localApproval };
544
+ };
545
+ const tasks = records.map(publicTask), task = tasks[0] ?? null, record = records[0];
546
+ const subAid = record?.sub_aid || requestedSub || this.aid;
547
+ const consensus = await this.client.checkOwnershipConsensus(subAid);
548
+ const files = { agent_md: null, owner_md: null, storage_agent_md: null };
549
+ const fileErrors = {};
550
+ const evidence = (raw, revision) => ({ raw_base64: Buffer.from(raw, 'utf-8').toString('base64'), sha256: crypto.createHash('sha256').update(raw, 'utf-8').digest('hex'), ...(revision ? { revision } : {}) });
551
+ const errorText = (error) => ownershipErrorCode(error) + ': ' + (error instanceof Error ? error.message : String(error));
552
+ let ns = null;
553
+ try {
554
+ if (!internal._agentMdManager)
555
+ throw new StateError('NS fresh reader is unavailable', { stringCode: 'unavailable' });
556
+ ns = await internal._agentMdManager.readOwnershipFresh(subAid);
557
+ if (ns.exists)
558
+ files.agent_md = evidence(ns.content);
559
+ else
560
+ fileErrors.agent_md = 'not_found';
561
+ }
562
+ catch (error) {
563
+ fileErrors.agent_md = errorText(error);
564
+ }
565
+ const storage = new OwnershipStorageAdapter({ currentAid: () => this.aid, call: (method, params) => this.client.call(method, params) });
566
+ const ownerAid = record ? record.operation === 'transfer' ? record.new_owner_aid : record.owner_aid : consensus.owner_aid;
567
+ if (ownerAid) {
568
+ try {
569
+ const owner = await storage.readOwnerMd(ownerAid, subAid);
570
+ if (owner.exists)
571
+ files.owner_md = evidence(owner.content, owner.revision);
572
+ else
573
+ fileErrors.owner_md = 'not_found';
574
+ }
575
+ catch (error) {
576
+ fileErrors.owner_md = errorText(error);
577
+ }
578
+ }
579
+ else
580
+ fileErrors.owner_md = 'owner_unavailable';
581
+ try {
582
+ const copy = await storage.readFile(subAid, 'agent.md');
583
+ if (copy.exists)
584
+ files.storage_agent_md = evidence(copy.content, copy.revision);
585
+ else
586
+ fileErrors.storage_agent_md = 'not_found';
587
+ }
588
+ catch (error) {
589
+ fileErrors.storage_agent_md = errorText(error);
590
+ }
591
+ sendJson(res, 200, { ok: true, aid: this.aid, task: jsonSafe(task), tasks: jsonSafe(tasks), events: this.ownershipEvents, consensus: jsonSafe(consensus), ns_protocol: ns?.protocol ?? null, files, file_errors: fileErrors });
592
+ }
593
+ catch (error) {
594
+ sendJson(res, 500, { ok: false, error_code: ownershipErrorCode(error), error_message: error instanceof Error ? error.message : String(error) });
595
+ }
596
+ }
442
597
  async handle(req, res) {
443
598
  const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
444
599
  try {
@@ -478,6 +633,7 @@ class CrossSdkJsAgent {
478
633
  this.rawPushRpcMethods = [];
479
634
  this.groupChangedEvents = [];
480
635
  this.groupInviteEvents = [];
636
+ this.readStateEvents = [];
481
637
  this.rawPushObservationId = textOf(body.observation_id ?? '');
482
638
  sendJson(res, 200, { ok: true, observation_id: this.rawPushObservationId });
483
639
  return;
@@ -516,6 +672,7 @@ class CrossSdkJsAgent {
516
672
  rpc_calls: rpcEntries,
517
673
  group_changed_events: groupChangedEvents.slice(-limit),
518
674
  group_invite_events: groupInviteEvents.slice(-limit),
675
+ read_state_events: this.readStateEvents.slice(-limit),
519
676
  });
520
677
  return;
521
678
  }
@@ -523,6 +680,18 @@ class CrossSdkJsAgent {
523
680
  sendJson(res, 200, await this.identity());
524
681
  return;
525
682
  }
683
+ if (req.method === 'POST' && ['/ownership/bind', '/ownership/accept', '/ownership/reject', '/ownership/release', '/ownership/transfer'].includes(url.pathname)) {
684
+ await this.ownershipControl(req, res, url.pathname.slice('/ownership/'.length));
685
+ return;
686
+ }
687
+ if (req.method === 'GET' && url.pathname === '/ownership/status') {
688
+ await this.ownershipStatus(url, res);
689
+ return;
690
+ }
691
+ if (req.method === 'GET' && url.pathname === '/ownership/events') {
692
+ sendJson(res, 200, { ok: true, events: this.ownershipEvents });
693
+ return;
694
+ }
526
695
  if (req.method === 'POST' && url.pathname === '/send') {
527
696
  await this.send(req, res);
528
697
  return;
@@ -535,6 +704,10 @@ class CrossSdkJsAgent {
535
704
  await this.pull(req, res);
536
705
  return;
537
706
  }
707
+ if (req.method === 'POST' && url.pathname === '/message/call') {
708
+ await this.messageCall(req, res);
709
+ return;
710
+ }
538
711
  if (req.method === 'GET' && url.pathname === '/sync/state') {
539
712
  this.syncState(url, res);
540
713
  return;
@@ -678,6 +851,76 @@ class CrossSdkJsAgent {
678
851
  sendJson(res, 500, error);
679
852
  }
680
853
  }
854
+ async orgProtocol(params) {
855
+ const op = textOf(params.op);
856
+ const now = Math.floor(Date.now() / 1000);
857
+ if (op === 'request')
858
+ return buildRequestBinding(textOf(params.method), textOf(params.target), params.params, textOf(params.credential_cid), textOf(params.nonce), textOf(params.request_id), now, now + 300);
859
+ if (['register', 'sign', 'certificate', 'create'].includes(op)) {
860
+ const store = this.aidStore();
861
+ try {
862
+ if (op === 'register') {
863
+ const registered = await store.register(textOf(params.org_id), { type: 'org', owner: this.aid, exttype: 'company' });
864
+ if (!registered.ok)
865
+ throw new Error(String(registered.error));
866
+ }
867
+ const loaded = op === 'certificate'
868
+ ? await store.resolve(textOf(params.as_aid), { skipAgentMd: true })
869
+ : (params.as_aid || params.org_id) ? await store.load(textOf(params.as_aid ?? params.org_id)) : null;
870
+ if (loaded && !loaded.ok)
871
+ throw new Error(String(loaded.error));
872
+ const identity = loaded?.data?.aid ?? this.client.currentAid;
873
+ const result = { cert_fingerprint: identity.certFingerprint, certificate: identity.certPem };
874
+ if (op === 'sign') {
875
+ const signed = await identity.sign(canonicalJson(params.payload));
876
+ if (!signed.ok)
877
+ throw new Error(String(signed.error));
878
+ result.signature = { cert_fingerprint: identity.certFingerprint, timestamp: now, signature: signed.data.signature };
879
+ }
880
+ else if (op === 'create') {
881
+ result.credential = params.membership_binding
882
+ ? await this.client.org.member.createCredential(params.membership_binding, identity, params.options)
883
+ : await this.client.credential.create(params.options, identity);
884
+ }
885
+ return result;
886
+ }
887
+ finally {
888
+ store.close();
889
+ }
890
+ }
891
+ const value = params.document ?? params.payload;
892
+ const result = { canonical: new TextDecoder().decode(canonicalJson(value)), digest: digest(value), error_code: '' };
893
+ if (op === 'verify' || op === 'verify_full') {
894
+ const certificates = params.certificates;
895
+ const resolver = (fingerprint) => certificates[fingerprint];
896
+ try {
897
+ if (op === 'verify_full') {
898
+ const actual = jsonObjectOf(params.context) ?? params;
899
+ const memberships = jsonObjectOf(params.memberships) ?? {};
900
+ result.verification = { ...await this.client.credential.verify(value, { resolveCertificate: resolver, resolveActorCertificate: resolver,
901
+ resolveStatus: (cid) => params.statuses?.[cid], now, audience: textOf(actual.audience), subject: textOf(actual.subject) || undefined,
902
+ ns: textOf(actual.ns), action: textOf(actual.action), resource: textOf(actual.resource), rootIssuer: textOf(actual.root_issuer) || undefined,
903
+ params: jsonObjectOf(actual.params) ?? {}, units: jsonObjectOf(actual.units) ?? {}, clientIp: textOf(actual.client_ip), method: textOf(actual.method), target: textOf(actual.target),
904
+ requestId: textOf(actual.request_id), nonce: textOf(actual.nonce), requestBinding: actual.request_binding, proofChain: actual.proof_chain, membershipBinding: actual.membership_binding,
905
+ orgSigner: textOf(actual.org_signer) || undefined, actor: textOf(actual.actor) || undefined, for: textOf(actual.for) || undefined, representationProof: actual.representation_proof,
906
+ resolveMembershipStatus: (binding, credential) => { const current = jsonObjectOf(memberships[String(binding.membership_id)]); return current?.status === 'active' && current.credential_cid === credential.cid; },
907
+ resolveOwnership: (subject, owner) => (jsonObjectOf(params.ownerships) ?? {})[subject] === owner, checkRateLimit: () => params.rate_limit_allowed === true }) };
908
+ }
909
+ else if (params.kind === 'credential')
910
+ result.verification = { ...await this.client.credential.verifySignature(value, resolver, now, textOf(params.audience)) };
911
+ else if (params.kind === 'binding')
912
+ await verifyMembershipBinding(value, resolver, now, textOf(params.expected_org_signer));
913
+ else
914
+ result.verification = { ...await this.client.credential.verifyRegistrationReceipt(value, params.credential, params.request, resolver, textOf(params.service_aid), now) };
915
+ }
916
+ catch (error) {
917
+ if (!(error instanceof ProtocolError))
918
+ throw error;
919
+ result.error_code = error.code;
920
+ }
921
+ }
922
+ return result;
923
+ }
681
924
  async groupCall(req, res) {
682
925
  const body = await readJson(req);
683
926
  const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
@@ -693,6 +936,48 @@ class CrossSdkJsAgent {
693
936
  try {
694
937
  let result;
695
938
  switch (method) {
939
+ case 'sdk.org.protocol':
940
+ result = await this.orgProtocol(params);
941
+ break;
942
+ case 'org.lifecycle.create':
943
+ result = await this.client.org.lifecycle.create(params);
944
+ break;
945
+ case 'org.lifecycle.dissolve':
946
+ result = await this.client.org.lifecycle.dissolve(params);
947
+ break;
948
+ case 'org.lifecycle.transfer':
949
+ result = await this.client.org.lifecycle.transfer(params);
950
+ break;
951
+ case 'org.lifecycle.transferAccept':
952
+ result = await this.client.org.lifecycle.transferAccept(params);
953
+ break;
954
+ case 'org.member.join':
955
+ result = await this.client.org.member.join(params);
956
+ break;
957
+ case 'org.member.approveJoin':
958
+ result = await this.client.org.member.approveJoin(params);
959
+ break;
960
+ case 'org.member.rejectJoin':
961
+ result = await this.client.org.member.rejectJoin(params);
962
+ break;
963
+ case 'org.member.invite':
964
+ result = await this.client.org.member.invite(params);
965
+ break;
966
+ case 'org.member.inviteAccept':
967
+ result = await this.client.org.member.inviteAccept(params);
968
+ break;
969
+ case 'org.member.inviteReject':
970
+ result = await this.client.org.member.inviteReject(params);
971
+ break;
972
+ case 'org.member.leave':
973
+ result = await this.client.org.member.leave(params);
974
+ break;
975
+ case 'org.member.offboard':
976
+ result = await this.client.org.member.offboard(params);
977
+ break;
978
+ case 'org.credential.getStatus':
979
+ result = await this.client.org.credential.getStatus(params);
980
+ break;
696
981
  case 'sdk.update_group_index':
697
982
  result = await this.client.group.updateGroupIndex(params);
698
983
  break;
@@ -726,6 +1011,12 @@ class CrossSdkJsAgent {
726
1011
  case 'group.get_member_statuses':
727
1012
  result = await this.client.group.getMemberStatuses(params);
728
1013
  break;
1014
+ case 'group.read':
1015
+ result = await this.client.group.read(params);
1016
+ break;
1017
+ case 'group.read_state':
1018
+ result = await this.client.group.readState(params);
1019
+ break;
729
1020
  default: result = await this.client.call(method, params);
730
1021
  }
731
1022
  const response = { ok: true, trace_id: traceId, method, result: jsonSafe(result) };
@@ -1395,6 +1686,39 @@ class CrossSdkJsAgent {
1395
1686
  });
1396
1687
  }
1397
1688
  }
1689
+ async messageCall(req, res) {
1690
+ const body = await readJson(req);
1691
+ const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
1692
+ const method = textOf(body.method).trim();
1693
+ const params = jsonObjectOf(body.params) ?? {};
1694
+ if (!method) {
1695
+ sendJson(res, 400, { ok: false, trace_id: traceId, error_code: 'bad_request', error_message: 'method is required' });
1696
+ return;
1697
+ }
1698
+ try {
1699
+ let result;
1700
+ if (method === 'message.read')
1701
+ result = await this.client.message.read(params);
1702
+ else if (method === 'message.read_state')
1703
+ result = await this.client.message.readState(params);
1704
+ else
1705
+ result = await this.client.call(method, params);
1706
+ const response = { ok: true, trace_id: traceId, method, result: jsonSafe(result) };
1707
+ this.recordTrace(traceId, { stage: 'message_call', method, result: response });
1708
+ sendJson(res, 200, response);
1709
+ }
1710
+ catch (err) {
1711
+ const error = {
1712
+ ok: false,
1713
+ trace_id: traceId,
1714
+ method,
1715
+ error_code: err instanceof Error ? err.name : 'Error',
1716
+ error_message: err instanceof Error ? err.message : String(err),
1717
+ };
1718
+ this.recordTrace(traceId, { stage: 'message_call_error', method, error });
1719
+ sendJson(res, 500, error);
1720
+ }
1721
+ }
1398
1722
  syncNamespace(scope, groupId = '') {
1399
1723
  if (scope === 'p2p')
1400
1724
  return `p2p:${this.aid}`;
@@ -1831,5 +2155,6 @@ async function main() {
1831
2155
  process.on('SIGINT', () => { void shutdown(); });
1832
2156
  process.on('SIGTERM', () => { void shutdown(); });
1833
2157
  }
1834
- void main();
2158
+ if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url))
2159
+ void main();
1835
2160
  //# sourceMappingURL=cross-sdk-agent.js.map