@kubun/plugin-p2p 0.12.1 → 0.13.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.
Files changed (62) hide show
  1. package/lib/context/group.js +3 -0
  2. package/lib/context/join.js +3 -0
  3. package/lib/context/peer.js +7 -2
  4. package/lib/context/sync.js +63 -5
  5. package/lib/context/types.d.ts +14 -1
  6. package/lib/context/types.js +12 -0
  7. package/lib/groups/access-default-apply.d.ts +42 -0
  8. package/lib/groups/access-default-apply.js +75 -0
  9. package/lib/groups/broadcast-codec.d.ts +1 -1
  10. package/lib/groups/broadcast-message.d.ts +240 -0
  11. package/lib/groups/broadcast-message.js +1 -0
  12. package/lib/groups/broadcast.d.ts +19 -266
  13. package/lib/groups/broadcast.js +30 -204
  14. package/lib/groups/credential-apply.d.ts +82 -0
  15. package/lib/groups/credential-apply.js +410 -0
  16. package/lib/groups/credential-grant-token.d.ts +42 -0
  17. package/lib/groups/credential-grant-token.js +51 -0
  18. package/lib/groups/credential-grant.d.ts +98 -0
  19. package/lib/groups/credential-grant.js +165 -0
  20. package/lib/groups/group-handlers.js +25 -2
  21. package/lib/groups/group-mls.d.ts +5 -0
  22. package/lib/groups/group-mls.js +4 -1
  23. package/lib/groups/group-peer-manager.d.ts +7 -1
  24. package/lib/groups/group-peer-manager.js +44 -1
  25. package/lib/groups/group-protocols.d.ts +227 -0
  26. package/lib/groups/group-protocols.js +146 -0
  27. package/lib/groups/join-utils.d.ts +5 -0
  28. package/lib/groups/join-utils.js +5 -1
  29. package/lib/groups/ledger-adopt.d.ts +84 -0
  30. package/lib/groups/ledger-adopt.js +142 -0
  31. package/lib/groups/ledger-commit-fold.d.ts +3 -1
  32. package/lib/groups/ledger-commit-fold.js +3 -0
  33. package/lib/groups/ledger-ingest.d.ts +23 -1
  34. package/lib/groups/ledger-ingest.js +30 -1
  35. package/lib/groups/manager.d.ts +5 -0
  36. package/lib/groups/manager.js +6 -1
  37. package/lib/groups/peer-presence.d.ts +9 -2
  38. package/lib/groups/peer-presence.js +14 -2
  39. package/lib/groups/peer-selection.d.ts +9 -0
  40. package/lib/groups/peer-selection.js +10 -0
  41. package/lib/hub/wiring.d.ts +6 -1
  42. package/lib/hub/wiring.js +2 -1
  43. package/lib/index.d.ts +5 -1
  44. package/lib/index.js +58 -6
  45. package/lib/peer/blob-fetch.d.ts +45 -0
  46. package/lib/peer/blob-fetch.js +89 -0
  47. package/lib/peer/blob-handlers.d.ts +11 -0
  48. package/lib/peer/blob-handlers.js +123 -0
  49. package/lib/peer/controller-fetch.d.ts +6 -0
  50. package/lib/peer/controller-fetch.js +59 -0
  51. package/lib/peer/controller-handlers.d.ts +10 -0
  52. package/lib/peer/controller-handlers.js +28 -0
  53. package/lib/protocol.d.ts +279 -0
  54. package/lib/protocol.js +358 -0
  55. package/lib/sync/access-default-sender.d.ts +1 -1
  56. package/lib/sync/broadcast-queue.d.ts +1 -1
  57. package/lib/sync/forwarder.d.ts +1 -1
  58. package/lib/sync/handlers.js +98 -1
  59. package/lib/sync/sync-manager.d.ts +10 -1
  60. package/lib/sync/sync-manager.js +24 -2
  61. package/lib/types.d.ts +18 -0
  62. package/package.json +41 -32
package/lib/protocol.d.ts CHANGED
@@ -203,6 +203,170 @@ export declare const syncProtocol: {
203
203
  readonly additionalProperties: false;
204
204
  };
205
205
  };
206
+ readonly 'sync/reconcile-credentials': {
207
+ readonly type: "request";
208
+ readonly param: {
209
+ readonly type: "object";
210
+ readonly properties: {
211
+ readonly held: {
212
+ readonly type: "array";
213
+ readonly items: {
214
+ readonly type: "object";
215
+ readonly properties: {
216
+ readonly subjectKind: {
217
+ readonly type: "string";
218
+ readonly enum: readonly ["key", "wrapping", "entry"];
219
+ };
220
+ readonly subjectID: {
221
+ readonly type: "string";
222
+ };
223
+ readonly opHash: {
224
+ readonly type: "string";
225
+ };
226
+ };
227
+ readonly required: readonly ["subjectKind", "subjectID", "opHash"];
228
+ readonly additionalProperties: false;
229
+ };
230
+ readonly description: "Signed subject states the caller holds, for updates and revocation GC";
231
+ };
232
+ };
233
+ readonly required: readonly ["held"];
234
+ readonly additionalProperties: false;
235
+ };
236
+ readonly result: {
237
+ readonly type: "object";
238
+ readonly properties: {
239
+ readonly bundles: {
240
+ readonly type: "array";
241
+ readonly items: {
242
+ readonly type: "object";
243
+ readonly properties: {
244
+ readonly keyID: {
245
+ readonly type: "string";
246
+ };
247
+ readonly keyVersion: {
248
+ readonly type: "number";
249
+ };
250
+ readonly suite: {
251
+ readonly type: "number";
252
+ };
253
+ readonly ownerDID: {
254
+ readonly type: "string";
255
+ };
256
+ readonly keyOp: {
257
+ readonly type: "string";
258
+ };
259
+ readonly keyBranches: {
260
+ readonly type: "array";
261
+ readonly items: {
262
+ readonly type: "string";
263
+ };
264
+ readonly description: "The proven key-op JWTs that introduced this key version's branches.";
265
+ };
266
+ readonly wrapping: {
267
+ readonly type: "object";
268
+ readonly properties: {
269
+ readonly wrappingID: {
270
+ readonly type: "string";
271
+ };
272
+ readonly factors: {
273
+ readonly type: "array";
274
+ readonly items: {
275
+ readonly type: "object";
276
+ readonly properties: {
277
+ readonly kind: {
278
+ readonly type: "string";
279
+ };
280
+ readonly params: {
281
+ readonly type: "object";
282
+ readonly additionalProperties: true;
283
+ };
284
+ };
285
+ readonly required: readonly ["kind", "params"];
286
+ readonly additionalProperties: false;
287
+ };
288
+ };
289
+ readonly iv: {
290
+ readonly type: "string";
291
+ };
292
+ readonly wrappedKey: {
293
+ readonly type: "string";
294
+ };
295
+ readonly recipientDID: {
296
+ readonly type: "string";
297
+ };
298
+ readonly op: {
299
+ readonly type: "string";
300
+ };
301
+ };
302
+ readonly required: readonly ["wrappingID", "factors", "iv", "wrappedKey", "recipientDID", "op"];
303
+ readonly additionalProperties: false;
304
+ };
305
+ readonly entries: {
306
+ readonly type: "array";
307
+ readonly items: {
308
+ readonly type: "object";
309
+ readonly properties: {
310
+ readonly entryID: {
311
+ readonly type: "string";
312
+ };
313
+ readonly iv: {
314
+ readonly type: "string";
315
+ };
316
+ readonly ciphertext: {
317
+ readonly type: "string";
318
+ };
319
+ readonly hlc: {
320
+ readonly type: "string";
321
+ };
322
+ readonly op: {
323
+ readonly type: "string";
324
+ };
325
+ };
326
+ readonly required: readonly ["entryID", "iv", "ciphertext", "hlc", "op"];
327
+ readonly additionalProperties: false;
328
+ };
329
+ };
330
+ };
331
+ readonly required: readonly ["keyID", "keyVersion", "suite", "ownerDID", "keyOp", "keyBranches", "wrapping", "entries"];
332
+ readonly additionalProperties: false;
333
+ };
334
+ readonly description: "The caller's recipient-scoped catch-up bundles (missed grants and entry top-ups)";
335
+ };
336
+ readonly tombstones: {
337
+ readonly type: "array";
338
+ readonly items: {
339
+ readonly type: "object";
340
+ readonly properties: {
341
+ readonly keyID: {
342
+ readonly type: "string";
343
+ };
344
+ readonly authorDID: {
345
+ readonly type: "string";
346
+ };
347
+ readonly hlc: {
348
+ readonly type: "string";
349
+ };
350
+ readonly opJWT: {
351
+ readonly type: "string";
352
+ };
353
+ readonly opHash: {
354
+ readonly type: "string";
355
+ };
356
+ readonly subjectID: {
357
+ readonly type: "string";
358
+ };
359
+ };
360
+ readonly required: readonly ["keyID", "authorDID", "hlc", "opJWT", "opHash", "subjectID"];
361
+ readonly additionalProperties: false;
362
+ };
363
+ readonly description: "Tombstones for advertised held IDs that are now revoked (GC)";
364
+ };
365
+ };
366
+ readonly required: readonly ["bundles", "tombstones"];
367
+ readonly additionalProperties: false;
368
+ };
369
+ };
206
370
  };
207
371
  export type SyncProtocol = typeof syncProtocol;
208
372
  /**
@@ -406,6 +570,113 @@ export declare const peerProtocol: {
406
570
  readonly additionalProperties: false;
407
571
  };
408
572
  };
573
+ readonly 'blob/query-haves': {
574
+ readonly type: "request";
575
+ readonly param: {
576
+ readonly type: "object";
577
+ readonly properties: {
578
+ readonly attachmentIDs: {
579
+ readonly type: "array";
580
+ readonly items: {
581
+ readonly type: "string";
582
+ };
583
+ readonly description: "Candidate AttachmentIDs the caller wants to locate";
584
+ };
585
+ };
586
+ readonly required: readonly ["attachmentIDs"];
587
+ readonly additionalProperties: false;
588
+ };
589
+ readonly result: {
590
+ readonly type: "object";
591
+ readonly properties: {
592
+ readonly have: {
593
+ readonly type: "array";
594
+ readonly items: {
595
+ readonly type: "string";
596
+ };
597
+ readonly description: "The subset this node holds with all bytes local";
598
+ };
599
+ };
600
+ readonly required: readonly ["have"];
601
+ readonly additionalProperties: false;
602
+ };
603
+ };
604
+ readonly 'blob/manifest': {
605
+ readonly type: "request";
606
+ readonly param: {
607
+ readonly type: "object";
608
+ readonly properties: {
609
+ readonly attachmentID: {
610
+ readonly type: "string";
611
+ };
612
+ readonly delegationTokens: {
613
+ readonly type: "array";
614
+ readonly items: {
615
+ readonly type: "string";
616
+ };
617
+ readonly description: "The caller's read-delegation tokens, for scope authorization";
618
+ };
619
+ };
620
+ readonly required: readonly ["attachmentID", "delegationTokens"];
621
+ readonly additionalProperties: false;
622
+ };
623
+ readonly result: {
624
+ readonly type: "object";
625
+ readonly properties: {
626
+ readonly chunkSize: {
627
+ readonly type: "number";
628
+ };
629
+ readonly chunkCount: {
630
+ readonly type: "number";
631
+ };
632
+ readonly contentLength: {
633
+ readonly type: "number";
634
+ };
635
+ readonly chunkDigests: {
636
+ readonly type: "array";
637
+ readonly items: {
638
+ readonly type: "string";
639
+ };
640
+ readonly description: "Per-chunk blake3 digests, base64, ordered by index";
641
+ };
642
+ readonly capability: {
643
+ readonly type: "string";
644
+ readonly description: "Short-TTL signed fetch capability for the data-plane GET";
645
+ };
646
+ };
647
+ readonly required: readonly ["chunkSize", "chunkCount", "contentLength", "chunkDigests", "capability"];
648
+ readonly additionalProperties: false;
649
+ };
650
+ };
651
+ readonly 'controller/get-log': {
652
+ readonly type: "request";
653
+ readonly param: {
654
+ readonly type: "object";
655
+ readonly properties: {
656
+ readonly did: {
657
+ readonly type: "string";
658
+ readonly description: "The did:kokuin: controller whose log is requested";
659
+ };
660
+ };
661
+ readonly required: readonly ["did"];
662
+ readonly additionalProperties: false;
663
+ };
664
+ readonly result: {
665
+ readonly type: "object";
666
+ readonly properties: {
667
+ readonly events: {
668
+ readonly type: "array";
669
+ readonly items: {
670
+ readonly type: "object";
671
+ readonly additionalProperties: true;
672
+ };
673
+ readonly description: "The controller's signed key-event log";
674
+ };
675
+ };
676
+ readonly required: readonly ["events"];
677
+ readonly additionalProperties: false;
678
+ };
679
+ };
409
680
  };
410
681
  export type PeerProtocol = typeof peerProtocol;
411
682
  export type PeerGroupsResult = FromSchema<PeerProtocol['peer/groups']['result']>;
@@ -416,12 +687,20 @@ export type GroupInviteParam = FromSchema<PeerProtocol['group/invite']['param']>
416
687
  export type GroupInviteResult = FromSchema<PeerProtocol['group/invite']['result']>;
417
688
  export type PushControlParam = FromSchema<PeerProtocol['group/push-control']['param']>;
418
689
  export type PushControlResult = FromSchema<PeerProtocol['group/push-control']['result']>;
690
+ export type BlobQueryHavesParam = FromSchema<PeerProtocol['blob/query-haves']['param']>;
691
+ export type BlobQueryHavesResult = FromSchema<PeerProtocol['blob/query-haves']['result']>;
692
+ export type BlobManifestParam = FromSchema<PeerProtocol['blob/manifest']['param']>;
693
+ export type BlobManifestResult = FromSchema<PeerProtocol['blob/manifest']['result']>;
694
+ export type ControllerGetLogParam = FromSchema<PeerProtocol['controller/get-log']['param']>;
695
+ export type ControllerGetLogResult = FromSchema<PeerProtocol['controller/get-log']['result']>;
419
696
  export type SyncNegotiateParams = FromSchema<SyncProtocol['sync/negotiate']['param']>;
420
697
  export type SyncNegotiateResult = FromSchema<SyncProtocol['sync/negotiate']['result']>;
421
698
  export type SyncMerkleSyncParams = FromSchema<SyncProtocol['sync/merkle-sync']['param']>;
422
699
  export type SyncMerkleSyncSend = FromSchema<SyncProtocol['sync/merkle-sync']['send']>;
423
700
  export type SyncMerkleSyncReceive = FromSchema<SyncProtocol['sync/merkle-sync']['receive']>;
424
701
  export type SyncMerkleSyncResult = FromSchema<SyncProtocol['sync/merkle-sync']['result']>;
702
+ export type SyncReconcileCredentialsParam = FromSchema<SyncProtocol['sync/reconcile-credentials']['param']>;
703
+ export type SyncReconcileCredentialsResult = FromSchema<SyncProtocol['sync/reconcile-credentials']['result']>;
425
704
  export type SyncDirection = 'push' | 'pull' | 'both';
426
705
  export type SyncClientMessage = AnyClientMessageOf<SyncProtocol>;
427
706
  export type SyncServerMessage = AnyServerMessageOf<SyncProtocol>;
package/lib/protocol.js CHANGED
@@ -247,6 +247,224 @@ export const syncProtocol = {
247
247
  ],
248
248
  additionalProperties: false
249
249
  }
250
+ },
251
+ // Credential catch-up + revocation GC in one round, served over the same
252
+ // doc-sync session. The caller advertises the signed subject states it holds so
253
+ // the server can send missing or updated rows and name tombstones for held rows
254
+ // that are now revoked — a wrapping tombstone addresses no recipient once its
255
+ // row is gone, so it can only travel when the caller names the id. `bundles`
256
+ // carries the row BYTES of the keys the caller is a recipient of and was
257
+ // missing, shaped like a `credential:key-grant` minus its `auth` envelope: each
258
+ // row self-authenticates through its own `op`, and recipient scoping is
259
+ // enforced server-side.
260
+ 'sync/reconcile-credentials': {
261
+ type: 'request',
262
+ param: {
263
+ type: 'object',
264
+ properties: {
265
+ held: {
266
+ type: 'array',
267
+ items: {
268
+ type: 'object',
269
+ properties: {
270
+ subjectKind: {
271
+ type: 'string',
272
+ enum: [
273
+ 'key',
274
+ 'wrapping',
275
+ 'entry'
276
+ ]
277
+ },
278
+ subjectID: {
279
+ type: 'string'
280
+ },
281
+ opHash: {
282
+ type: 'string'
283
+ }
284
+ },
285
+ required: [
286
+ 'subjectKind',
287
+ 'subjectID',
288
+ 'opHash'
289
+ ],
290
+ additionalProperties: false
291
+ },
292
+ description: 'Signed subject states the caller holds, for updates and revocation GC'
293
+ }
294
+ },
295
+ required: [
296
+ 'held'
297
+ ],
298
+ additionalProperties: false
299
+ },
300
+ result: {
301
+ type: 'object',
302
+ properties: {
303
+ bundles: {
304
+ type: 'array',
305
+ items: {
306
+ type: 'object',
307
+ properties: {
308
+ keyID: {
309
+ type: 'string'
310
+ },
311
+ keyVersion: {
312
+ type: 'number'
313
+ },
314
+ suite: {
315
+ type: 'number'
316
+ },
317
+ ownerDID: {
318
+ type: 'string'
319
+ },
320
+ keyOp: {
321
+ type: 'string'
322
+ },
323
+ keyBranches: {
324
+ type: 'array',
325
+ items: {
326
+ type: 'string'
327
+ },
328
+ description: "The proven key-op JWTs that introduced this key version's branches."
329
+ },
330
+ wrapping: {
331
+ type: 'object',
332
+ properties: {
333
+ wrappingID: {
334
+ type: 'string'
335
+ },
336
+ factors: {
337
+ type: 'array',
338
+ items: {
339
+ type: 'object',
340
+ properties: {
341
+ kind: {
342
+ type: 'string'
343
+ },
344
+ params: {
345
+ type: 'object',
346
+ additionalProperties: true
347
+ }
348
+ },
349
+ required: [
350
+ 'kind',
351
+ 'params'
352
+ ],
353
+ additionalProperties: false
354
+ }
355
+ },
356
+ iv: {
357
+ type: 'string'
358
+ },
359
+ wrappedKey: {
360
+ type: 'string'
361
+ },
362
+ recipientDID: {
363
+ type: 'string'
364
+ },
365
+ op: {
366
+ type: 'string'
367
+ }
368
+ },
369
+ required: [
370
+ 'wrappingID',
371
+ 'factors',
372
+ 'iv',
373
+ 'wrappedKey',
374
+ 'recipientDID',
375
+ 'op'
376
+ ],
377
+ additionalProperties: false
378
+ },
379
+ entries: {
380
+ type: 'array',
381
+ items: {
382
+ type: 'object',
383
+ properties: {
384
+ entryID: {
385
+ type: 'string'
386
+ },
387
+ iv: {
388
+ type: 'string'
389
+ },
390
+ ciphertext: {
391
+ type: 'string'
392
+ },
393
+ hlc: {
394
+ type: 'string'
395
+ },
396
+ op: {
397
+ type: 'string'
398
+ }
399
+ },
400
+ required: [
401
+ 'entryID',
402
+ 'iv',
403
+ 'ciphertext',
404
+ 'hlc',
405
+ 'op'
406
+ ],
407
+ additionalProperties: false
408
+ }
409
+ }
410
+ },
411
+ required: [
412
+ 'keyID',
413
+ 'keyVersion',
414
+ 'suite',
415
+ 'ownerDID',
416
+ 'keyOp',
417
+ 'keyBranches',
418
+ 'wrapping',
419
+ 'entries'
420
+ ],
421
+ additionalProperties: false
422
+ },
423
+ description: "The caller's recipient-scoped catch-up bundles (missed grants and entry top-ups)"
424
+ },
425
+ tombstones: {
426
+ type: 'array',
427
+ items: {
428
+ type: 'object',
429
+ properties: {
430
+ keyID: {
431
+ type: 'string'
432
+ },
433
+ authorDID: {
434
+ type: 'string'
435
+ },
436
+ hlc: {
437
+ type: 'string'
438
+ },
439
+ opJWT: {
440
+ type: 'string'
441
+ },
442
+ opHash: {
443
+ type: 'string'
444
+ },
445
+ subjectID: {
446
+ type: 'string'
447
+ }
448
+ },
449
+ required: [
450
+ 'keyID',
451
+ 'authorDID',
452
+ 'hlc',
453
+ 'opJWT',
454
+ 'opHash',
455
+ 'subjectID'
456
+ ],
457
+ additionalProperties: false
458
+ },
459
+ description: 'Tombstones for advertised held IDs that are now revoked (GC)'
460
+ }
461
+ },
462
+ required: [
463
+ 'bundles',
464
+ 'tombstones'
465
+ ],
466
+ additionalProperties: false
467
+ }
250
468
  }
251
469
  };
252
470
  /**
@@ -515,5 +733,145 @@ export const syncProtocol = {
515
733
  ],
516
734
  additionalProperties: false
517
735
  }
736
+ },
737
+ // Blob transfer lane — control plane. Bytes never ride these; they carry
738
+ // discovery + a signed fetch capability. The data plane is raw HTTP Range.
739
+ // Gated coarsely (checkPeerAccess): just reports which bytes this node holds.
740
+ 'blob/query-haves': {
741
+ type: 'request',
742
+ param: {
743
+ type: 'object',
744
+ properties: {
745
+ attachmentIDs: {
746
+ type: 'array',
747
+ items: {
748
+ type: 'string'
749
+ },
750
+ description: 'Candidate AttachmentIDs the caller wants to locate'
751
+ }
752
+ },
753
+ required: [
754
+ 'attachmentIDs'
755
+ ],
756
+ additionalProperties: false
757
+ },
758
+ result: {
759
+ type: 'object',
760
+ properties: {
761
+ have: {
762
+ type: 'array',
763
+ items: {
764
+ type: 'string'
765
+ },
766
+ description: 'The subset this node holds with all bytes local'
767
+ }
768
+ },
769
+ required: [
770
+ 'have'
771
+ ],
772
+ additionalProperties: false
773
+ }
774
+ },
775
+ // Returns the chunk manifest for one blob and mints a short-TTL fetch
776
+ // capability the caller presents to the data-plane HTTP route. Scope-gated:
777
+ // the caller must have a document in scope referencing the blob (D19), and
778
+ // presents its own read-delegation tokens to prove it.
779
+ 'blob/manifest': {
780
+ type: 'request',
781
+ param: {
782
+ type: 'object',
783
+ properties: {
784
+ attachmentID: {
785
+ type: 'string'
786
+ },
787
+ delegationTokens: {
788
+ type: 'array',
789
+ items: {
790
+ type: 'string'
791
+ },
792
+ description: "The caller's read-delegation tokens, for scope authorization"
793
+ }
794
+ },
795
+ required: [
796
+ 'attachmentID',
797
+ 'delegationTokens'
798
+ ],
799
+ additionalProperties: false
800
+ },
801
+ result: {
802
+ type: 'object',
803
+ properties: {
804
+ chunkSize: {
805
+ type: 'number'
806
+ },
807
+ chunkCount: {
808
+ type: 'number'
809
+ },
810
+ contentLength: {
811
+ type: 'number'
812
+ },
813
+ chunkDigests: {
814
+ type: 'array',
815
+ items: {
816
+ type: 'string'
817
+ },
818
+ description: 'Per-chunk blake3 digests, base64, ordered by index'
819
+ },
820
+ capability: {
821
+ type: 'string',
822
+ description: 'Short-TTL signed fetch capability for the data-plane GET'
823
+ }
824
+ },
825
+ required: [
826
+ 'chunkSize',
827
+ 'chunkCount',
828
+ 'contentLength',
829
+ 'chunkDigests',
830
+ 'capability'
831
+ ],
832
+ additionalProperties: false
833
+ }
834
+ },
835
+ // Controller log sharing. Serves a `did:kokuin:` controller's stored key-event
836
+ // log inline (logs are small — no blob-style data plane). Gated coarsely by
837
+ // `checkPeerAccess`: the log you need is that of a DID whose documents you
838
+ // already sync, and those are group/catalog scoped. The events are
839
+ // self-authenticating (inception digest == DID, every event signed), so the
840
+ // recipient folds + verifies them independently — the wire schema stays
841
+ // permissive and the fold on receipt is the real check.
842
+ 'controller/get-log': {
843
+ type: 'request',
844
+ param: {
845
+ type: 'object',
846
+ properties: {
847
+ did: {
848
+ type: 'string',
849
+ description: 'The did:kokuin: controller whose log is requested'
850
+ }
851
+ },
852
+ required: [
853
+ 'did'
854
+ ],
855
+ additionalProperties: false
856
+ },
857
+ result: {
858
+ type: 'object',
859
+ properties: {
860
+ events: {
861
+ type: 'array',
862
+ // A SignedEvent is a nested object re-verified on receipt; the wire
863
+ // carries it opaquely rather than reproducing its structure.
864
+ items: {
865
+ type: 'object',
866
+ additionalProperties: true
867
+ },
868
+ description: "The controller's signed key-event log"
869
+ }
870
+ },
871
+ required: [
872
+ 'events'
873
+ ],
874
+ additionalProperties: false
875
+ }
518
876
  }
519
877
  };
@@ -2,7 +2,7 @@ import type { OwnIdentity } from '@kokuin/token';
2
2
  import type { KubunDB } from '@kubun/db';
3
3
  import type { EngineEventBus, EngineEvents } from '@kubun/engine';
4
4
  import type { Logger } from '@kubun/logger';
5
- import type { GroupBroadcastMessage } from '../groups/broadcast.js';
5
+ import type { GroupBroadcastMessage } from '../groups/broadcast-message.js';
6
6
  export type AccessDefaultSenderParams = {
7
7
  db: KubunDB;
8
8
  eventBus: EngineEventBus<EngineEvents>;