@kubun/plugin-p2p 0.10.0 → 0.11.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 (136) hide show
  1. package/lib/context/delegation.js +130 -1
  2. package/lib/context/group.js +1319 -1
  3. package/lib/context/hub.js +150 -1
  4. package/lib/context/join.js +80 -1
  5. package/lib/context/sync.js +19 -1
  6. package/lib/context/types.d.ts +12 -3
  7. package/lib/context/types.js +28 -1
  8. package/lib/groups/admin-roster.d.ts +130 -0
  9. package/lib/groups/admin-roster.js +184 -0
  10. package/lib/groups/broadcast-codec.js +6 -1
  11. package/lib/groups/broadcast.d.ts +122 -38
  12. package/lib/groups/broadcast.js +627 -1
  13. package/lib/groups/circle-projection.d.ts +122 -0
  14. package/lib/groups/circle-projection.js +288 -0
  15. package/lib/groups/circle-reducers.d.ts +178 -0
  16. package/lib/groups/circle-reducers.js +198 -0
  17. package/lib/groups/events.d.ts +7 -2
  18. package/lib/groups/events.js +10 -1
  19. package/lib/groups/group-anchor.d.ts +63 -0
  20. package/lib/groups/group-anchor.js +107 -0
  21. package/lib/groups/group-crypto.d.ts +19 -0
  22. package/lib/groups/group-crypto.js +85 -0
  23. package/lib/groups/group-handle-registry.d.ts +69 -2
  24. package/lib/groups/group-handle-registry.js +243 -1
  25. package/lib/groups/group-handlers.d.ts +29 -0
  26. package/lib/groups/group-handlers.js +92 -0
  27. package/lib/groups/group-health-monitor.d.ts +56 -0
  28. package/lib/groups/group-health-monitor.js +139 -0
  29. package/lib/groups/group-mls.d.ts +35 -0
  30. package/lib/groups/group-mls.js +164 -0
  31. package/lib/groups/group-peer-manager.d.ts +108 -0
  32. package/lib/groups/group-peer-manager.js +344 -0
  33. package/lib/groups/group-protocols.d.ts +297 -0
  34. package/lib/groups/group-protocols.js +174 -0
  35. package/lib/groups/invite-payload.d.ts +1 -1
  36. package/lib/groups/invite-payload.js +26 -1
  37. package/lib/groups/join-utils.d.ts +1 -0
  38. package/lib/groups/join-utils.js +104 -1
  39. package/lib/groups/ledger-affected-events.d.ts +15 -0
  40. package/lib/groups/ledger-affected-events.js +96 -0
  41. package/lib/groups/ledger-entry.d.ts +37 -0
  42. package/lib/groups/ledger-entry.js +56 -0
  43. package/lib/groups/ledger-fold.d.ts +56 -0
  44. package/lib/groups/ledger-fold.js +53 -0
  45. package/lib/groups/manager.d.ts +29 -71
  46. package/lib/groups/manager.js +281 -1
  47. package/lib/groups/mls-codec.d.ts +1 -1
  48. package/lib/groups/mls-codec.js +18 -1
  49. package/lib/groups/mls-encryptor.d.ts +2 -2
  50. package/lib/groups/mls-encryptor.js +30 -1
  51. package/lib/groups/mls-group-handle.d.ts +1 -1
  52. package/lib/groups/mls-group-handle.js +10 -1
  53. package/lib/groups/mls-json.js +17 -1
  54. package/lib/groups/mls-receive-errors.d.ts +29 -0
  55. package/lib/groups/mls-receive-errors.js +42 -0
  56. package/lib/groups/mls-state.d.ts +1 -1
  57. package/lib/groups/mls-state.js +56 -1
  58. package/lib/groups/store-received-grant.d.ts +4 -1
  59. package/lib/groups/store-received-grant.js +116 -1
  60. package/lib/groups/store-received-revocation.d.ts +3 -3
  61. package/lib/groups/store-received-revocation.js +82 -1
  62. package/lib/hub/ack-backoff.d.ts +22 -0
  63. package/lib/hub/ack-backoff.js +88 -0
  64. package/lib/hub/did-observing-transport.d.ts +13 -2
  65. package/lib/hub/did-observing-transport.js +126 -1
  66. package/lib/hub/errors.d.ts +4 -8
  67. package/lib/hub/errors.js +33 -1
  68. package/lib/hub/http-client.d.ts +28 -3
  69. package/lib/hub/http-client.js +32 -1
  70. package/lib/hub/hub-like.d.ts +24 -0
  71. package/lib/hub/hub-like.js +535 -0
  72. package/lib/hub/manager.d.ts +5 -4
  73. package/lib/hub/manager.js +198 -1
  74. package/lib/hub/wiring.d.ts +28 -41
  75. package/lib/hub/wiring.js +132 -1
  76. package/lib/index.d.ts +29 -13
  77. package/lib/index.js +392 -1
  78. package/lib/protocol.d.ts +8 -1
  79. package/lib/protocol.js +251 -1
  80. package/lib/schema.d.ts +2 -1
  81. package/lib/schema.js +471 -2
  82. package/lib/sync/authorize.d.ts +25 -0
  83. package/lib/sync/authorize.js +73 -0
  84. package/lib/sync/broadcast-queue.js +183 -1
  85. package/lib/sync/broadcast-sender.js +179 -1
  86. package/lib/sync/catalog-scope.js +68 -1
  87. package/lib/sync/errors.d.ts +12 -0
  88. package/lib/sync/errors.js +19 -0
  89. package/lib/sync/forwarder.js +277 -1
  90. package/lib/sync/handlers.d.ts +3 -22
  91. package/lib/sync/handlers.js +160 -1
  92. package/lib/sync/hub-tunnel-sync-listener.d.ts +9 -3
  93. package/lib/sync/hub-tunnel-sync-listener.js +172 -1
  94. package/lib/sync/hub-tunnel-sync-provider.d.ts +14 -14
  95. package/lib/sync/hub-tunnel-sync-provider.js +64 -1
  96. package/lib/sync/merkle-apply.d.ts +5 -0
  97. package/lib/sync/merkle-apply.js +194 -1
  98. package/lib/sync/merkle-channel.d.ts +19 -0
  99. package/lib/sync/merkle-channel.js +182 -1
  100. package/lib/sync/merkle-tree.js +120 -1
  101. package/lib/sync/peer-registry.d.ts +8 -1
  102. package/lib/sync/peer-registry.js +107 -1
  103. package/lib/sync/receive-access-gate.js +24 -1
  104. package/lib/sync/scope-resolver.js +41 -1
  105. package/lib/sync/sync-client.d.ts +5 -3
  106. package/lib/sync/sync-client.js +192 -1
  107. package/lib/sync/sync-manager.d.ts +2 -2
  108. package/lib/sync/sync-manager.js +272 -1
  109. package/lib/types.d.ts +41 -0
  110. package/lib/types.js +2 -1
  111. package/lib/util/mutex.js +10 -1
  112. package/lib/utils.d.ts +5 -0
  113. package/lib/utils.js +21 -0
  114. package/package.json +48 -41
  115. package/lib/groups/broadcast-service.d.ts +0 -189
  116. package/lib/groups/broadcast-service.js +0 -1
  117. package/lib/groups/wire-frame.d.ts +0 -32
  118. package/lib/groups/wire-frame.js +0 -1
  119. package/lib/hub/connection-pool.d.ts +0 -43
  120. package/lib/hub/connection-pool.js +0 -1
  121. package/lib/hub/forward-remote-broadcast.d.ts +0 -15
  122. package/lib/hub/forward-remote-broadcast.js +0 -1
  123. package/lib/hub/group-channel.d.ts +0 -67
  124. package/lib/hub/group-channel.js +0 -1
  125. package/lib/hub/hub-connection.d.ts +0 -96
  126. package/lib/hub/hub-connection.js +0 -1
  127. package/lib/hub/receive-handler.d.ts +0 -33
  128. package/lib/hub/receive-handler.js +0 -1
  129. package/lib/hub/relay-manager.d.ts +0 -127
  130. package/lib/hub/relay-manager.js +0 -1
  131. package/lib/hub/send-handler.d.ts +0 -40
  132. package/lib/hub/send-handler.js +0 -1
  133. package/lib/hub/tunnel-inbox.d.ts +0 -20
  134. package/lib/hub/tunnel-inbox.js +0 -1
  135. package/lib/hub/wait-for-gate.d.ts +0 -14
  136. package/lib/hub/wait-for-gate.js +0 -1
@@ -0,0 +1,96 @@
1
+ import { toISO } from '../context/types.js';
2
+ /**
3
+ * Emit the local `P2PEventEmitter` events for a remote-driven control-ledger
4
+ * entry that a receiving peer just applied, so GraphQL subscribers see
5
+ * remote circle/group changes live — the same events a local producer fires.
6
+ *
7
+ * Only `ledger:entry` projections surface as `affected`; every other applied
8
+ * message (delegation grant/revoke, advisory leave) already emits its own event
9
+ * from inside `processBroadcast`, so this covers exactly the circle/group
10
+ * projection rows the apply core returns rather than emits. The payloads are
11
+ * built from `affected.row`, which `processBroadcast` snapshots at the right
12
+ * moment (after-state for create/change, before-state for delete/remove).
13
+ */ export async function emitLedgerAffectedEvents(emitter, result) {
14
+ if (!result.applied || result.affected == null || result.affected.kind !== 'ledger') {
15
+ return;
16
+ }
17
+ const { ledger } = result.affected;
18
+ switch(ledger.entry){
19
+ case 'circle.def':
20
+ {
21
+ const { row } = ledger;
22
+ // No active pre-state means a create; otherwise a change. Match the
23
+ // producer: a catalogs-only change emits `circleCatalogsChanged`, any other
24
+ // change emits `circleDataChanged`. The `*Changed` payloads carry `circleID`.
25
+ if (!ledger.preExisted) {
26
+ await emitter.emit('circleCreated', {
27
+ id: row.id,
28
+ groupID: row.group_id,
29
+ name: row.name,
30
+ description: row.description,
31
+ createdAt: toISO(row.created_at)
32
+ });
33
+ return;
34
+ }
35
+ const eventName = ledger.catalogsChanged ? 'circleCatalogsChanged' : 'circleDataChanged';
36
+ await emitter.emit(eventName, {
37
+ id: row.id,
38
+ groupID: row.group_id,
39
+ name: row.name,
40
+ description: row.description,
41
+ createdAt: toISO(row.created_at),
42
+ circleID: row.id
43
+ });
44
+ return;
45
+ }
46
+ case 'circle.def.removed':
47
+ {
48
+ const { row } = ledger;
49
+ await emitter.emit('circleDeleted', {
50
+ id: row.id,
51
+ groupID: row.group_id,
52
+ name: row.name,
53
+ description: row.description,
54
+ createdAt: toISO(row.created_at)
55
+ });
56
+ return;
57
+ }
58
+ case 'circle.member':
59
+ {
60
+ const { row } = ledger;
61
+ // Both a new membership and a role change map here: there is no distinct
62
+ // "role changed" circle-member event, mirroring the producer.
63
+ await emitter.emit('circleMemberAdded', {
64
+ circleID: row.circle_id,
65
+ memberDID: row.member_did,
66
+ role: row.role,
67
+ createdAt: toISO(row.created_at)
68
+ });
69
+ return;
70
+ }
71
+ case 'circle.member.removed':
72
+ {
73
+ const { row } = ledger;
74
+ await emitter.emit('circleMemberRemoved', {
75
+ circleID: row.circle_id,
76
+ memberDID: row.member_did,
77
+ role: row.role,
78
+ createdAt: toISO(row.created_at)
79
+ });
80
+ return;
81
+ }
82
+ case 'group.settings':
83
+ {
84
+ const { row } = ledger;
85
+ await emitter.emit('groupDataChanged', {
86
+ id: row.id,
87
+ name: row.name,
88
+ description: row.description,
89
+ createdBy: row.created_by,
90
+ createdAt: toISO(row.created_at),
91
+ groupID: row.id
92
+ });
93
+ return;
94
+ }
95
+ }
96
+ }
@@ -0,0 +1,37 @@
1
+ import { type OwnIdentity } from '@kokuin/token';
2
+ /**
3
+ * A control-ledger claim. The payload of a signed ledger token: `type` selects
4
+ * the reducer, `subject` is the entity the claim is about, `value` carries the
5
+ * claim data, and `hlc` orders it. The authenticated author is never part of
6
+ * this shape — it comes from the verified token's `iss`.
7
+ */
8
+ export type LedgerEntry<TValue = unknown> = {
9
+ type: string;
10
+ subject: string;
11
+ value: TValue;
12
+ hlc: string;
13
+ };
14
+ /** A ledger entry whose token signature has been cryptographically verified. */
15
+ export type VerifiedLedgerEntry<TValue = unknown> = {
16
+ /** Authenticated author DID (the verified token issuer), normalized. */
17
+ issuer: string;
18
+ entry: LedgerEntry<TValue>;
19
+ };
20
+ /**
21
+ * Sign a ledger entry. The signer fills `iss` with its DID, so the signature
22
+ * covers every claim field and binds the author. Returns the stringified token.
23
+ */
24
+ export declare function signLedgerEntry(identity: OwnIdentity, entry: LedgerEntry): Promise<string>;
25
+ /**
26
+ * Verify a signed ledger token and extract its claim. Returns `null` (never
27
+ * throws) when the token is unparseable, unsigned (`alg: 'none'` — `verifyToken`
28
+ * returns those without checking a signature, so an attacker could forge an
29
+ * arbitrary `iss`), or structurally malformed. The claim fields come from the
30
+ * verified payload only; the issuer is the normalized verified `iss`.
31
+ */
32
+ export declare function verifyLedgerEntry<TValue = unknown>(token: string): Promise<VerifiedLedgerEntry<TValue> | null>;
33
+ /**
34
+ * Content-addressed digest of a signed ledger token, used as the append-only
35
+ * store's dedup key. Multibase-encoded SHA-256 multihash over the token bytes.
36
+ */
37
+ export declare function ledgerEntryDigest(signedToken: string): string;
@@ -0,0 +1,56 @@
1
+ import { encodeMultibase, isVerifiedToken, multihashSHA256, normalizeDID, stringifyToken, verifyToken } from '@kokuin/token';
2
+ const textEncoder = new TextEncoder();
3
+ /**
4
+ * Sign a ledger entry. The signer fills `iss` with its DID, so the signature
5
+ * covers every claim field and binds the author. Returns the stringified token.
6
+ */ export async function signLedgerEntry(identity, entry) {
7
+ const signed = await identity.signToken({
8
+ type: entry.type,
9
+ subject: entry.subject,
10
+ value: entry.value,
11
+ hlc: entry.hlc
12
+ }, // Embed the long-form DID so each entry is self-verifying offline: the
13
+ // ledger is the source of truth and receivers fold it long after first
14
+ // contact, when the author's DID document may no longer be cached. No-op
15
+ // for did:key (long form === id).
16
+ {
17
+ embedLongForm: true
18
+ });
19
+ return stringifyToken(signed);
20
+ }
21
+ /**
22
+ * Verify a signed ledger token and extract its claim. Returns `null` (never
23
+ * throws) when the token is unparseable, unsigned (`alg: 'none'` — `verifyToken`
24
+ * returns those without checking a signature, so an attacker could forge an
25
+ * arbitrary `iss`), or structurally malformed. The claim fields come from the
26
+ * verified payload only; the issuer is the normalized verified `iss`.
27
+ */ export async function verifyLedgerEntry(token) {
28
+ let verified;
29
+ try {
30
+ verified = await verifyToken(token);
31
+ } catch {
32
+ return null;
33
+ }
34
+ if (!isVerifiedToken(verified)) {
35
+ return null;
36
+ }
37
+ const { iss, type, subject, value, hlc } = verified.payload;
38
+ if (typeof type !== 'string' || typeof subject !== 'string' || typeof hlc !== 'string') {
39
+ return null;
40
+ }
41
+ return {
42
+ issuer: normalizeDID(iss),
43
+ entry: {
44
+ type,
45
+ subject,
46
+ value,
47
+ hlc
48
+ }
49
+ };
50
+ }
51
+ /**
52
+ * Content-addressed digest of a signed ledger token, used as the append-only
53
+ * store's dedup key. Multibase-encoded SHA-256 multihash over the token bytes.
54
+ */ export function ledgerEntryDigest(signedToken) {
55
+ return encodeMultibase(multihashSHA256(textEncoder.encode(signedToken)));
56
+ }
@@ -0,0 +1,56 @@
1
+ import type { GroupAnchor } from './group-anchor.js';
2
+ import type { VerifiedLedgerEntry } from './ledger-entry.js';
3
+ /**
4
+ * A per-type projection over the control ledger. The fold stays free of any
5
+ * admin/circle semantics: a reducer owns its own initial state (derived from
6
+ * the genesis anchor), its authority rule, and its fold step, so a new ledger
7
+ * type plugs in as a parameter with zero edits to {@link foldLedger}.
8
+ */
9
+ export type LedgerReducer<TValue, TState> = {
10
+ /** Ledger entry `type` this reducer projects; entries of any other type are dropped. */
11
+ type: string;
12
+ /**
13
+ * Initial fold state, derived from the genesis anchor. The anchor is the
14
+ * authenticated epoch-0 root (e.g. the creator DID is the first admin), so
15
+ * seeding from it is what makes the very first claims evaluable.
16
+ */
17
+ seed(anchor: GroupAnchor): TState;
18
+ /** Is the verified issuer allowed to make this claim, given the state so far? */
19
+ verifyAuthority(verified: VerifiedLedgerEntry<TValue>, stateSoFar: TState): boolean;
20
+ /** Fold step: return the next state after applying an authorized claim. */
21
+ apply(verified: VerifiedLedgerEntry<TValue>, stateSoFar: TState): TState;
22
+ };
23
+ /**
24
+ * A verified entry paired with its content-addressed id. The id is the
25
+ * total-order tie-breaker when two entries share an `hlc`, and identifies the
26
+ * entry in drop notices.
27
+ */
28
+ export type FoldInput<TValue = unknown> = {
29
+ verified: VerifiedLedgerEntry<TValue>;
30
+ entryID: string;
31
+ };
32
+ /** Why an entry was skipped during the fold, for an optional observer. */
33
+ export type FoldDrop = {
34
+ entryID: string;
35
+ type: string;
36
+ reason: string;
37
+ };
38
+ /**
39
+ * Replay the ledger into a single reducer's projection.
40
+ *
41
+ * Signatures are verified at ingest, not here — this fold evaluates AUTHORITY:
42
+ * whether each issuer was allowed to make its claim given the state accumulated
43
+ * from strictly-earlier entries. Evaluating against state-so-far (never the
44
+ * final state) is what makes rotation sound: a key authorized at HLC `t` can be
45
+ * revoked at `t+1` without retroactively invalidating its earlier claims.
46
+ *
47
+ * Deterministic on any arrival order: it seeds from the genesis anchor, sorts a
48
+ * copy of the entries by the total order `(hlc, entryID)`, then folds. Pure — no
49
+ * clock, no randomness, no I/O, and the input array is never mutated. A claim of
50
+ * an unrelated type or one whose authority fails is dropped (never thrown) so a
51
+ * single bad entry can never abort the projection. Drops are silent unless an
52
+ * `onDrop` observer is supplied — the fold runs on every authority check, where
53
+ * authority-failed drops are expected, so the caller decides whether to surface
54
+ * them rather than the fold emitting to the console.
55
+ */
56
+ export declare function foldLedger<TValue, TState>(entries: Array<FoldInput<TValue>>, anchor: GroupAnchor, reducer: LedgerReducer<TValue, TState>, onDrop?: (drop: FoldDrop) => void): TState;
@@ -0,0 +1,53 @@
1
+ /** Total order over the ledger: HLC first, then content-addressed id to break ties. */ function compareFoldInputs(a, b) {
2
+ if (a.verified.entry.hlc !== b.verified.entry.hlc) {
3
+ return a.verified.entry.hlc < b.verified.entry.hlc ? -1 : 1;
4
+ }
5
+ if (a.entryID === b.entryID) {
6
+ return 0;
7
+ }
8
+ return a.entryID < b.entryID ? -1 : 1;
9
+ }
10
+ /**
11
+ * Replay the ledger into a single reducer's projection.
12
+ *
13
+ * Signatures are verified at ingest, not here — this fold evaluates AUTHORITY:
14
+ * whether each issuer was allowed to make its claim given the state accumulated
15
+ * from strictly-earlier entries. Evaluating against state-so-far (never the
16
+ * final state) is what makes rotation sound: a key authorized at HLC `t` can be
17
+ * revoked at `t+1` without retroactively invalidating its earlier claims.
18
+ *
19
+ * Deterministic on any arrival order: it seeds from the genesis anchor, sorts a
20
+ * copy of the entries by the total order `(hlc, entryID)`, then folds. Pure — no
21
+ * clock, no randomness, no I/O, and the input array is never mutated. A claim of
22
+ * an unrelated type or one whose authority fails is dropped (never thrown) so a
23
+ * single bad entry can never abort the projection. Drops are silent unless an
24
+ * `onDrop` observer is supplied — the fold runs on every authority check, where
25
+ * authority-failed drops are expected, so the caller decides whether to surface
26
+ * them rather than the fold emitting to the console.
27
+ */ export function foldLedger(entries, anchor, reducer, onDrop) {
28
+ const ordered = [
29
+ ...entries
30
+ ].sort(compareFoldInputs);
31
+ let state = reducer.seed(anchor);
32
+ for (const { verified, entryID } of ordered){
33
+ const { entry } = verified;
34
+ if (entry.type !== reducer.type) {
35
+ onDrop?.({
36
+ entryID,
37
+ type: entry.type,
38
+ reason: `unknown type for reducer '${reducer.type}'`
39
+ });
40
+ continue;
41
+ }
42
+ if (!reducer.verifyAuthority(verified, state)) {
43
+ onDrop?.({
44
+ entryID,
45
+ type: entry.type,
46
+ reason: `issuer '${verified.issuer}' not authorized`
47
+ });
48
+ continue;
49
+ }
50
+ state = reducer.apply(verified, state);
51
+ }
52
+ return state;
53
+ }
@@ -1,7 +1,7 @@
1
- import { type GroupPermission, type Invite, type KeyPackageBundle } from '@enkaku/group';
2
- import type { Identity, OwnIdentity } from '@enkaku/token';
1
+ import { type Identity, type OwnIdentity } from '@kokuin/token';
3
2
  import type { StoreProvider } from '@kubun/db';
4
- import type { GroupBroadcastMessage } from './broadcast.js';
3
+ import { HLC } from '@kubun/hlc';
4
+ import { type GroupPermission, type Invite, type KeyPackageBundle } from '@kumiai/mls';
5
5
  import type { GroupHandleRegistry } from './group-handle-registry.js';
6
6
  import type { SuggestedHub } from './invite-payload.js';
7
7
  export type GroupManagerParams = {
@@ -13,6 +13,14 @@ export type GroupManagerParams = {
13
13
  * the registry's per-group mutex with write-through persist.
14
14
  */
15
15
  registry: GroupHandleRegistry;
16
+ /**
17
+ * Device-wide monotonic clock for stamping group/circle/member metadata.
18
+ * Required: production passes the engine's single instance so every write
19
+ * from this device — graph mutations and group metadata alike — advances one
20
+ * shared clock, preventing two same-millisecond writes from minting identical
21
+ * timestamps (the second would silently lose under last-writer-wins).
22
+ */
23
+ hlc: HLC;
16
24
  };
17
25
  export type CreateGroupParams = {
18
26
  stores: StoreProvider;
@@ -25,17 +33,6 @@ export type CreateGroupParams = {
25
33
  export type CreateGroupResult = {
26
34
  groupID: string;
27
35
  };
28
- export type UpdateGroupParams = {
29
- stores: StoreProvider;
30
- groupID: string;
31
- update: {
32
- name?: string;
33
- description?: string;
34
- };
35
- };
36
- export type UpdateGroupResult = {
37
- broadcast: GroupBroadcastMessage;
38
- };
39
36
  export type InviteToGroupParams = {
40
37
  stores: StoreProvider;
41
38
  groupID: string;
@@ -46,7 +43,7 @@ export type InviteToGroupParams = {
46
43
  };
47
44
  export type InviteToGroupResult = {
48
45
  invite: Invite;
49
- /** Framed MLSMessage(Welcome) bytes for the invitee (`@enkaku/group@0.16.1`). */
46
+ /** Framed MLSMessage(Welcome) bytes for the invitee (`@kumiai/mls`). */
50
47
  welcomeMessage: Uint8Array;
51
48
  /** Framed MLSMessage(Commit) bytes to fan out to existing members. */
52
49
  commitMessage: Uint8Array;
@@ -54,7 +51,7 @@ export type InviteToGroupResult = {
54
51
  * Ratchet tree from the post-commit handle. Required by `joinGroup`
55
52
  * callers that build an invite payload — they no longer hold a
56
53
  * `GroupHandle` reference, so the manager surfaces the tree directly.
57
- * Typed `unknown` to match `@enkaku/group`'s `ProcessWelcomeParams.ratchetTree`,
54
+ * Typed `unknown` to match `@kumiai/mls`'s `ProcessWelcomeParams.ratchetTree`,
58
55
  * which is opaque on that side too.
59
56
  */
60
57
  ratchetTree: unknown;
@@ -84,6 +81,14 @@ export type RemoveGroupMemberParams = {
84
81
  stores: StoreProvider;
85
82
  groupID: string;
86
83
  memberDID: string;
84
+ /**
85
+ * The HLC stamped by the caller for the roster tombstone. Lifted out of this
86
+ * method so the producer can stamp ONE HLC that orders both the MLS-roster
87
+ * tombstone here and the admin-role revocation it appends in the same
88
+ * transaction — the two must share a timestamp for the fold to drop exactly
89
+ * the ex-admin's later control entries.
90
+ */
91
+ hlc: string;
87
92
  };
88
93
  export type RemoveGroupMemberResult = {
89
94
  commitMessage: Uint8Array;
@@ -92,62 +97,20 @@ export type LeaveGroupParams = {
92
97
  stores: StoreProvider;
93
98
  groupID: string;
94
99
  identity: OwnIdentity;
100
+ /**
101
+ * The HLC stamped by the caller for the self-removal tombstone. Lifted out of
102
+ * this method so the `leave` producer can stamp ONE HLC that orders both this
103
+ * self-tombstone and the admin-role self-revocation it appends in the same
104
+ * transaction — the two must share a timestamp for a receiver's fold to drop
105
+ * exactly the leaver's control entries signed at or after the departure.
106
+ */
107
+ hlc: string;
95
108
  };
96
109
  export type LeaveGroupResult = undefined;
97
- export type CreateCircleParams = {
98
- stores: StoreProvider;
99
- groupID: string;
100
- name: string;
101
- description?: string;
102
- catalogIDs?: Array<string>;
103
- };
104
- export type CreateCircleResult = {
105
- circleID: string;
106
- broadcast: GroupBroadcastMessage;
107
- };
108
- export type UpdateCircleParams = {
109
- stores: StoreProvider;
110
- circleID: string;
111
- update: {
112
- name?: string;
113
- description?: string;
114
- catalogIDs?: Array<string>;
115
- };
116
- };
117
- export type UpdateCircleResult = {
118
- broadcast: GroupBroadcastMessage;
119
- broadcasts: Array<GroupBroadcastMessage>;
120
- };
121
- export type DeleteCircleParams = {
122
- stores: StoreProvider;
123
- circleID: string;
124
- };
125
- export type DeleteCircleResult = {
126
- broadcast: GroupBroadcastMessage;
127
- };
128
- export type AddCircleMemberParams = {
129
- stores: StoreProvider;
130
- groupID: string;
131
- circleID: string;
132
- memberDID: string;
133
- role: 'admin' | 'member';
134
- };
135
- export type AddCircleMemberResult = {
136
- broadcast: GroupBroadcastMessage;
137
- };
138
- export type RemoveCircleMemberParams = {
139
- stores: StoreProvider;
140
- circleID: string;
141
- memberDID: string;
142
- };
143
- export type RemoveCircleMemberResult = {
144
- broadcast: GroupBroadcastMessage;
145
- };
146
110
  export declare class GroupManager {
147
111
  #private;
148
112
  constructor(params: GroupManagerParams);
149
113
  createGroup(params: CreateGroupParams): Promise<CreateGroupResult>;
150
- updateGroup(params: UpdateGroupParams): Promise<UpdateGroupResult>;
151
114
  inviteToGroup(params: InviteToGroupParams): Promise<InviteToGroupResult>;
152
115
  joinGroup(params: JoinGroupParams): Promise<JoinGroupResult>;
153
116
  removeMember(params: RemoveMemberParams): Promise<RemoveMemberResult>;
@@ -157,9 +120,4 @@ export declare class GroupManager {
157
120
  epoch: number;
158
121
  credential: string;
159
122
  } | undefined>;
160
- createCircle(params: CreateCircleParams): Promise<CreateCircleResult>;
161
- updateCircle(params: UpdateCircleParams): Promise<UpdateCircleResult>;
162
- deleteCircle(params: DeleteCircleParams): Promise<DeleteCircleResult>;
163
- addCircleMember(params: AddCircleMemberParams): Promise<AddCircleMemberResult>;
164
- removeCircleMember(params: RemoveCircleMemberParams): Promise<RemoveCircleMemberResult>;
165
123
  }