@serfab/cadre-core 1.15.0 → 1.17.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 (199) hide show
  1. package/README.md +1 -1
  2. package/dist/bootstrap-peer-store-file.js +1 -1
  3. package/dist/bootstrap-peer-store.d.ts +1 -1
  4. package/dist/bootstrap-peer-store.js +4 -4
  5. package/dist/cadre-invite-protocol.d.ts +55 -138
  6. package/dist/cadre-invite-protocol.js +94 -449
  7. package/dist/cadre-invite-protocol.js.map +1 -1
  8. package/dist/cadre-join-request.d.ts +15 -2
  9. package/dist/cadre-join-request.js +22 -3
  10. package/dist/cadre-join-request.js.map +1 -1
  11. package/dist/cadre-node.d.ts +530 -247
  12. package/dist/cadre-node.js +1046 -525
  13. package/dist/cadre-node.js.map +1 -1
  14. package/dist/control-authorization.d.ts +36 -14
  15. package/dist/control-authorization.js +20 -3
  16. package/dist/control-authorization.js.map +1 -1
  17. package/dist/control-cohort.d.ts +22 -23
  18. package/dist/control-cohort.js +24 -24
  19. package/dist/control-cohort.js.map +1 -1
  20. package/dist/control-database.d.ts +416 -136
  21. package/dist/control-database.js +757 -378
  22. package/dist/control-database.js.map +1 -1
  23. package/dist/control-protocol-guard.d.ts +5 -4
  24. package/dist/control-protocol-guard.js +6 -3
  25. package/dist/control-protocol-guard.js.map +1 -1
  26. package/dist/control-schema-version.d.ts +80 -0
  27. package/dist/control-schema-version.js +203 -0
  28. package/dist/control-schema-version.js.map +1 -0
  29. package/dist/control-schema.d.ts +45 -5
  30. package/dist/control-schema.js +254 -70
  31. package/dist/control-schema.js.map +1 -1
  32. package/dist/control-write-retry.d.ts +5 -5
  33. package/dist/control-write-retry.js +10 -8
  34. package/dist/control-write-retry.js.map +1 -1
  35. package/dist/delegate-admission.d.ts +13 -0
  36. package/dist/delegate-admission.js +27 -0
  37. package/dist/delegate-admission.js.map +1 -1
  38. package/dist/ed25519-key.d.ts +10 -7
  39. package/dist/ed25519-key.js +23 -20
  40. package/dist/ed25519-key.js.map +1 -1
  41. package/dist/edge-node/config.d.ts +122 -0
  42. package/dist/edge-node/config.js +199 -0
  43. package/dist/edge-node/config.js.map +1 -0
  44. package/dist/edge-node/dissolve.d.ts +95 -0
  45. package/dist/edge-node/dissolve.js +184 -0
  46. package/dist/edge-node/dissolve.js.map +1 -0
  47. package/dist/edge-node/edge-join.d.ts +44 -0
  48. package/dist/edge-node/edge-join.js +227 -0
  49. package/dist/edge-node/edge-join.js.map +1 -0
  50. package/dist/edge-node/edge-node.d.ts +295 -0
  51. package/dist/edge-node/edge-node.js +704 -0
  52. package/dist/edge-node/edge-node.js.map +1 -0
  53. package/dist/edge-node/index.d.ts +18 -0
  54. package/dist/edge-node/index.js +18 -0
  55. package/dist/edge-node/index.js.map +1 -0
  56. package/dist/edge-node/join-credential.d.ts +11 -0
  57. package/dist/edge-node/join-credential.js +11 -0
  58. package/dist/edge-node/join-credential.js.map +1 -0
  59. package/dist/edge-node/lazy-raw-storage.d.ts +40 -0
  60. package/dist/edge-node/lazy-raw-storage.js +134 -0
  61. package/dist/edge-node/lazy-raw-storage.js.map +1 -0
  62. package/dist/edge-node/node-local.d.ts +60 -0
  63. package/dist/edge-node/node-local.js +58 -0
  64. package/dist/edge-node/node-local.js.map +1 -0
  65. package/dist/edge-node/options.d.ts +83 -0
  66. package/dist/edge-node/options.js +110 -0
  67. package/dist/edge-node/options.js.map +1 -0
  68. package/dist/edge-node/owner-grant.d.ts +41 -0
  69. package/dist/edge-node/owner-grant.js +38 -0
  70. package/dist/edge-node/owner-grant.js.map +1 -0
  71. package/dist/edge-node/platform.d.ts +140 -0
  72. package/dist/edge-node/platform.js +12 -0
  73. package/dist/edge-node/platform.js.map +1 -0
  74. package/dist/edge-node/strand-move.d.ts +115 -0
  75. package/dist/edge-node/strand-move.js +223 -0
  76. package/dist/edge-node/strand-move.js.map +1 -0
  77. package/dist/edge-node/strands.d.ts +28 -0
  78. package/dist/edge-node/strands.js +60 -0
  79. package/dist/edge-node/strands.js.map +1 -0
  80. package/dist/index.d.ts +16 -7
  81. package/dist/index.js +26 -7
  82. package/dist/index.js.map +1 -1
  83. package/dist/joined-strand-store.d.ts +3 -3
  84. package/dist/joined-strand-store.js +3 -3
  85. package/dist/joined-strand-store.js.map +1 -1
  86. package/dist/key-store.d.ts +9 -4
  87. package/dist/key-store.js +9 -4
  88. package/dist/key-store.js.map +1 -1
  89. package/dist/machine-removal.d.ts +19 -39
  90. package/dist/machine-removal.js +24 -98
  91. package/dist/machine-removal.js.map +1 -1
  92. package/dist/member-redemption.d.ts +250 -0
  93. package/dist/member-redemption.js +485 -0
  94. package/dist/member-redemption.js.map +1 -0
  95. package/dist/owner-anchor-sync.d.ts +4 -4
  96. package/dist/owner-anchor-sync.js +16 -15
  97. package/dist/owner-anchor-sync.js.map +1 -1
  98. package/dist/owner-grant-protocol.d.ts +247 -0
  99. package/dist/owner-grant-protocol.js +330 -0
  100. package/dist/owner-grant-protocol.js.map +1 -0
  101. package/dist/owner-key-export.d.ts +70 -0
  102. package/dist/owner-key-export.js +279 -0
  103. package/dist/owner-key-export.js.map +1 -0
  104. package/dist/owner-key-flows.d.ts +55 -0
  105. package/dist/owner-key-flows.js +60 -0
  106. package/dist/owner-key-flows.js.map +1 -0
  107. package/dist/owner-key-store.d.ts +31 -0
  108. package/dist/owner-key-store.js +81 -0
  109. package/dist/owner-key-store.js.map +1 -0
  110. package/dist/owner-keys.d.ts +78 -0
  111. package/dist/owner-keys.js +133 -0
  112. package/dist/owner-keys.js.map +1 -0
  113. package/dist/owner-signer.d.ts +54 -0
  114. package/dist/owner-signer.js +51 -0
  115. package/dist/owner-signer.js.map +1 -0
  116. package/dist/peer-authorization.d.ts +83 -18
  117. package/dist/peer-authorization.js +123 -53
  118. package/dist/peer-authorization.js.map +1 -1
  119. package/dist/provider/rent-node.js +1 -1
  120. package/dist/provider/rent-node.js.map +1 -1
  121. package/dist/seed-bootstrap.d.ts +131 -109
  122. package/dist/seed-bootstrap.js +260 -248
  123. package/dist/seed-bootstrap.js.map +1 -1
  124. package/dist/seed-trust-policy.js +4 -4
  125. package/dist/strand-addr-protocol.d.ts +4 -1
  126. package/dist/strand-addr-protocol.js +8 -2
  127. package/dist/strand-addr-protocol.js.map +1 -1
  128. package/dist/strand-cohort.d.ts +3 -0
  129. package/dist/strand-cohort.js.map +1 -1
  130. package/dist/strand-database.d.ts +1 -0
  131. package/dist/strand-database.js +3 -0
  132. package/dist/strand-database.js.map +1 -1
  133. package/dist/strand-first-sync-gate.d.ts +4 -3
  134. package/dist/strand-first-sync-gate.js +4 -3
  135. package/dist/strand-first-sync-gate.js.map +1 -1
  136. package/dist/strand-instance-manager.d.ts +1 -1
  137. package/dist/strand-membership-writer.d.ts +13 -2
  138. package/dist/strand-membership-writer.js +52 -16
  139. package/dist/strand-membership-writer.js.map +1 -1
  140. package/dist/strand-move.d.ts +6 -5
  141. package/dist/strand-move.js +31 -30
  142. package/dist/strand-move.js.map +1 -1
  143. package/dist/strand-peer-redial.js +2 -3
  144. package/dist/strand-peer-redial.js.map +1 -1
  145. package/dist/types.d.ts +286 -103
  146. package/dist/types.js.map +1 -1
  147. package/package.json +16 -7
  148. package/src/bootstrap-peer-store-file.ts +44 -44
  149. package/src/bootstrap-peer-store.ts +214 -214
  150. package/src/cadre-invite-protocol.ts +131 -531
  151. package/src/cadre-join-request.ts +188 -167
  152. package/src/cadre-node.ts +1166 -541
  153. package/src/control-authorization.ts +47 -14
  154. package/src/control-cohort.ts +127 -128
  155. package/src/control-database.ts +940 -456
  156. package/src/control-protocol-guard.ts +7 -4
  157. package/src/control-schema-version.ts +251 -0
  158. package/src/control-schema.ts +265 -70
  159. package/src/control-write-retry.ts +569 -567
  160. package/src/delegate-admission.ts +37 -0
  161. package/src/ed25519-key.ts +174 -171
  162. package/src/edge-node/config.ts +277 -0
  163. package/src/edge-node/dissolve.ts +251 -0
  164. package/src/edge-node/edge-join.ts +319 -0
  165. package/src/edge-node/edge-node.ts +1045 -0
  166. package/src/edge-node/index.ts +59 -0
  167. package/src/edge-node/join-credential.ts +16 -0
  168. package/src/edge-node/lazy-raw-storage.ts +178 -0
  169. package/src/edge-node/node-local.ts +84 -0
  170. package/src/edge-node/options.ts +179 -0
  171. package/src/edge-node/owner-grant.ts +63 -0
  172. package/src/edge-node/platform.ts +151 -0
  173. package/src/edge-node/strand-move.ts +270 -0
  174. package/src/edge-node/strands.ts +72 -0
  175. package/src/index.ts +102 -5
  176. package/src/joined-strand-store.ts +4 -4
  177. package/src/key-store.ts +10 -4
  178. package/src/machine-removal.ts +26 -111
  179. package/src/member-redemption.ts +642 -0
  180. package/src/owner-anchor-sync.ts +19 -18
  181. package/src/owner-grant-protocol.ts +532 -0
  182. package/src/owner-key-export.ts +348 -0
  183. package/src/owner-key-flows.ts +109 -0
  184. package/src/owner-key-store.ts +85 -0
  185. package/src/owner-keys.ts +178 -0
  186. package/src/owner-signer.ts +94 -0
  187. package/src/peer-authorization.ts +558 -488
  188. package/src/provider/rent-node.ts +1 -1
  189. package/src/seed-bootstrap.ts +301 -312
  190. package/src/seed-trust-policy.ts +4 -4
  191. package/src/strand-addr-protocol.ts +547 -538
  192. package/src/strand-cohort.ts +4 -0
  193. package/src/strand-database.ts +3 -0
  194. package/src/strand-first-sync-gate.ts +4 -3
  195. package/src/strand-instance-manager.ts +1 -1
  196. package/src/strand-membership-writer.ts +61 -16
  197. package/src/strand-move.ts +45 -36
  198. package/src/strand-peer-redial.ts +2 -3
  199. package/src/types.ts +304 -103
@@ -0,0 +1,247 @@
1
+ /**
2
+ * Owner grant redemption transport: `/sereus/owner-grant/1.0.0`.
3
+ *
4
+ * A holder of an owner grant (an owner-signed `OwnerGrant` row plus the private half of the
5
+ * grant keypair, see {@link OwnerGrantBundle}) dials ANY member machine the grant names and
6
+ * proves possession of the grant and of the key it wants seated; the member seats the row if
7
+ * it does not hold it yet and writes the holder's `OwnerKey` row through
8
+ * `ControlDatabase.redeemOwnerGrant`. No machine is admitted and no peer id is named: the
9
+ * holder's network identity has nothing to do with the key it seats, so unlike the invitation
10
+ * protocol there is no connecting-identity check — both signatures already bind the grant, the
11
+ * nonce and the key. The owner that minted the grant need not be online.
12
+ *
13
+ * The exchange shape — one frame each way, the member's hardening and admission of the
14
+ * holder, the holder's address-by-address dialing in passes — is `member-redemption.ts`'s,
15
+ * shared with the invitation protocol; this module supplies the grant's bundle, request,
16
+ * checks, writes and refusal codes. Stranger-facing by design, classed `stranger-open` in
17
+ * `control-protocol-guard.ts`; the handler's own trust decision is the two signatures.
18
+ */
19
+ import type { Libp2p } from '@libp2p/interface';
20
+ import { type ControlDatabase } from './control-database.js';
21
+ import { MemberRedemptionHandler, type MemberRedemption, type MemberRedemptionHandlerOptions, type RedemptionAddressOutcome, type RedemptionRejection } from './member-redemption.js';
22
+ import type { OwnerSign } from './owner-signer.js';
23
+ import type { CadreJoinProgress, OwnerGrantRow } from './types.js';
24
+ /** Protocol id for owner grant redemption (parallel to `/sereus/cadre-invite/1.0.0`). */
25
+ export declare const OWNER_GRANT_PROTOCOL = "/sereus/owner-grant/1.0.0";
26
+ /**
27
+ * What an owner hands out (QR, paste, file) and a holder redeems. A grant is an ed25519
28
+ * keypair: the row holds the public half, `grantPrivateKey` is the proof of possession, and
29
+ * whoever holds this bundle can become an owner of the party — a bearer credential for admin
30
+ * rights for the row's lifetime (15 minutes by default; a backup grant has no expiry and is
31
+ * kept as carefully as an owner key).
32
+ *
33
+ * Carrying the signed row is what makes redemption work at a member that has not received
34
+ * the row by replication: the member seats it from the bundle under its stored issuer
35
+ * signature. The row's own signature covers every column, so a bundle whose row was altered
36
+ * cannot be seated anywhere. `members` are the party's addresses at mint time, so a backup
37
+ * grant can go stale if every member's address changes.
38
+ */
39
+ export interface OwnerGrantBundle {
40
+ v: 1;
41
+ /** The cadre the grant makes an owner of; a holder refuses one for another party. */
42
+ partyId: string;
43
+ /** The grant's ed25519 seed, base64url: the proof of possession. */
44
+ grantPrivateKey: string;
45
+ /** The owner-signed row exactly as issued (`ControlDatabase.insertOwnerGrant`). */
46
+ grant: OwnerGrantRow;
47
+ /**
48
+ * The issuer's anchored owner keys. The holder pins them before it dials
49
+ * (`CadreNode.trustOwnerKeys`) and checks the member's reply against them. Sourced from the
50
+ * issuer's node-local anchor only, never the replicated `OwnerKey` table, for the reason the
51
+ * invitation gives: the holder anchors whatever arrives here.
52
+ */
53
+ ownerKeys: string[];
54
+ /** As `CadreInvitation.members`: multiaddrs ending in `/p2p/<peerId>`, the issuer's first, at most six in all. */
55
+ members: string[];
56
+ }
57
+ /**
58
+ * Encode a bundle for out-of-band delivery: {@link OWNER_GRANT_PREFIX}, then base64url over
59
+ * JSON. The prefix lets an app tell a grant from an invitation, a join request or an owner key
60
+ * and name the mistake when one is pasted for the other.
61
+ */
62
+ export declare function encodeOwnerGrant(bundle: OwnerGrantBundle): string;
63
+ /**
64
+ * Decode a bundle, refusing anything that is not a well-formed version-1
65
+ * {@link OwnerGrantBundle} behind {@link OWNER_GRANT_PREFIX}. Standalone, like
66
+ * `decodeCadreInvitation`, so a client without a node can decode one.
67
+ *
68
+ * @throws on an owner key, a cadre invitation or a join request, a string without the prefix
69
+ * or that is not base64url JSON after it, or one that decodes to another shape or version.
70
+ */
71
+ export declare function decodeOwnerGrant(encoded: string): OwnerGrantBundle;
72
+ /** Is `value` an {@link OwnerGrantRow} with every column in its stored form and bounded? */
73
+ export declare function isWellFormedOwnerGrantRow(value: unknown): value is OwnerGrantRow;
74
+ /** Holder → member: one frame, the whole redemption. */
75
+ export interface OwnerGrantRedeemRequest {
76
+ v: 1;
77
+ /** The cadre the holder believes it is becoming an owner of; a machine serving another party refuses by name. */
78
+ partyId: string;
79
+ /** The owner-signed row from the bundle. */
80
+ grant: OwnerGrantRow;
81
+ /** The ed25519 public key to seat as an owner, base64url: the holder's, fresh or already held. */
82
+ ownerKey: string;
83
+ /** Single-use nonce the holder minted (`generateStampId`); both signatures cover it. */
84
+ usageStampId: string;
85
+ /** By `grantPrivateKey` over the `'redeem'` digest. */
86
+ grantSig: string;
87
+ /** By `ownerKey` over the `'consent'` digest. */
88
+ ownerSig: string;
89
+ }
90
+ /**
91
+ * Why a member refused a redemption: the invitation's codes with grant wording. Retryability
92
+ * is {@link OWNER_GRANT_REJECTION_RETRYABLE}'s; a retryable code moves the holder to the next
93
+ * address the bundle names.
94
+ */
95
+ export type OwnerGrantRejectionCode =
96
+ /** The issuer's `OwnerKey` row is not on this member (not replicated yet), or the issuer was removed; the member cannot tell which. */
97
+ 'issuer-unknown'
98
+ /** A signature does not verify, or the request or the row is malformed. */
99
+ | 'grant-invalid'
100
+ /** Expired, withdrawn, exhausted, or issued by a key that is no longer an owner here. */
101
+ | 'grant-spent'
102
+ /** This machine serves another cadre than the one the grant names. */
103
+ | 'party-mismatch'
104
+ /** The member is at its cap on concurrent redemptions. */
105
+ | 'busy'
106
+ /** The write failed transiently (the write retry gave up), or the member has not synced the grant row the cadre holds; nothing was recorded. */
107
+ | 'conflict'
108
+ /** An unexpected member-side failure, or a request frame the member could not read: nothing was proved either way. */
109
+ | 'internal';
110
+ /** Which refusals are worth repeating at the next address — the one place that says so. */
111
+ export declare const OWNER_GRANT_REJECTION_RETRYABLE: Readonly<Record<OwnerGrantRejectionCode, boolean>>;
112
+ /** Is `value` a code this build knows? Own keys only, so a peer's `'constructor'` does not pass. */
113
+ export declare function isOwnerGrantRejectionCode(value: unknown): value is OwnerGrantRejectionCode;
114
+ /** Member → holder. No dial hints: the holder is not joining the cadre's network, only seating a key. */
115
+ export interface OwnerGrantRedeemReply {
116
+ accepted: boolean;
117
+ /** Present iff `!accepted`. */
118
+ code?: OwnerGrantRejectionCode;
119
+ /** Human-facing text; present iff `!accepted`. */
120
+ reason?: string;
121
+ /** The member's party id; present iff `accepted`. */
122
+ partyId?: string;
123
+ /** The grant row as this member holds it; present iff `accepted`. */
124
+ grant?: OwnerGrantRow;
125
+ /** The key was already a live owner here, so nothing was written and no use was spent; present iff `accepted`. */
126
+ alreadyOwner?: boolean;
127
+ }
128
+ /** An accepting reply, every optional field present. */
129
+ export interface OwnerGrantAccepted extends OwnerGrantRedeemReply {
130
+ accepted: true;
131
+ partyId: string;
132
+ grant: OwnerGrantRow;
133
+ alreadyOwner: boolean;
134
+ }
135
+ type OwnerGrantRejection = RedemptionRejection<OwnerGrantRejectionCode>;
136
+ /**
137
+ * A member answered and refused (on `CadreNode.redeemOwnerGrant`'s local path, the member is
138
+ * this node). `code` is `'unrecognized'` when the frame carried none this build knows, and such
139
+ * a refusal counts as retryable, as the invitation's does.
140
+ */
141
+ export declare class OwnerGrantRejectedError extends Error {
142
+ readonly code: OwnerGrantRejectionCode | 'unrecognized';
143
+ readonly reason: string;
144
+ readonly retryable: boolean;
145
+ /** Both arguments come straight off the wire, so neither is trusted to have its declared type. */
146
+ constructor(code: unknown, reason: unknown);
147
+ }
148
+ /** Every address the bundle names was tried and none accepted. Always retryable; `outcomes` says what each address did. */
149
+ export declare class OwnerGrantUnreachableError extends Error {
150
+ readonly outcomes: readonly RedemptionAddressOutcome[];
151
+ readonly retryable = true;
152
+ constructor(outcomes: readonly RedemptionAddressOutcome[]);
153
+ }
154
+ /**
155
+ * A member accepted but its reply does not check out: another party id, another grant key, or
156
+ * a row not signed by one of the pinned owner keys. Final, for the invitation's reason: such a
157
+ * machine is not a member of the cadre the grant names.
158
+ */
159
+ export declare class OwnerGrantReplyInvalidError extends Error {
160
+ readonly retryable = false;
161
+ constructor(message: string);
162
+ }
163
+ /**
164
+ * Build and sign the request for `bundle`: the holder's `'redeem'` signature with the grant's
165
+ * private key (held in memory for the length of this call) and the seated key's `'consent'`
166
+ * signature through `signConsent`, the `sign` of an open owner approval on the signer that
167
+ * holds `ownerKey`; both over (grant key, `usageStampId`, `ownerKey`) for the grant's party. The
168
+ * same bytes the schema verifies at the member (`ownerGrantRedeemMessage` /
169
+ * `ownerGrantConsentMessage`), and the same request goes to every member and every pass.
170
+ */
171
+ export declare function signOwnerGrantRequest(bundle: OwnerGrantBundle, ownerKey: string, signConsent: OwnerSign, usageStampId: string): Promise<OwnerGrantRedeemRequest>;
172
+ /**
173
+ * The holder's check on an acceptance: the same party, the same grant key, and a row signed by
174
+ * an issuer the holder pinned from the bundle. Throws {@link OwnerGrantReplyInvalidError} naming
175
+ * the first failure. Bounded as `verifyRedeemReply` is: it catches a wrong-party or wrong-row
176
+ * answer, not a forged member, which the holder's anchor settles once its store syncs.
177
+ */
178
+ export declare function verifyOwnerGrantReply(reply: OwnerGrantAccepted, bundle: OwnerGrantBundle, isTrustedIssuer: (ownerKey: string) => boolean): void;
179
+ /** The control-database surface a redemption needs; a `ControlDatabase` satisfies it. */
180
+ export type OwnerGrantStore = Pick<ControlDatabase, 'seatOwnerGrant' | 'isOwnerGrantLive' | 'redeemOwnerGrant'>;
181
+ export interface OwnerGrantHandlerOptions extends MemberRedemptionHandlerOptions {
182
+ store: OwnerGrantStore;
183
+ }
184
+ /**
185
+ * Member side of the grant protocol (`MemberRedemptionHandler` has the shape): after the
186
+ * request's shape, it checks the party and both signatures — nothing about the connecting
187
+ * peer, whose identity is unrelated to the key it seats — then seats the row from the bundle
188
+ * and redeems. An issuer this member does not know as an owner is the one retryable refusal
189
+ * left: the holder tries the next address, which may hold the issuer's row.
190
+ */
191
+ export declare class OwnerGrantHandler extends MemberRedemptionHandler<OwnerGrantRedeemRequest, OwnerGrantRedeemReply> {
192
+ private readonly store;
193
+ protected readonly busyRefusal: RedemptionRejection<"busy">;
194
+ protected readonly internalRefusal: RedemptionRejection<"internal">;
195
+ protected readonly malformedRefusal: RedemptionRejection<"grant-invalid">;
196
+ constructor(options: OwnerGrantHandlerOptions);
197
+ protected isWellFormedRequest(value: unknown): value is OwnerGrantRedeemRequest;
198
+ protected checkRequest(request: OwnerGrantRedeemRequest): OwnerGrantRejection | null;
199
+ protected isLive(request: OwnerGrantRedeemRequest): Promise<boolean>;
200
+ /** The two writes — the seat (its own transaction; a no-op when held) and the redemption — each answered by name when it fails. */
201
+ protected redeemAdmitted(request: OwnerGrantRedeemRequest, remotePeerId: string): Promise<OwnerGrantRedeemReply>;
202
+ }
203
+ export interface RedeemOwnerGrantAtMembersOptions {
204
+ /** The bundle: its `members` are dialed in order. */
205
+ bundle: OwnerGrantBundle;
206
+ /** The signed request ({@link signOwnerGrantRequest}); the same one goes to every address. */
207
+ request: OwnerGrantRedeemRequest;
208
+ /** Is this owner key one the holder pinned from the bundle? The reply check's input. */
209
+ isTrustedIssuer: (ownerKey: string) => boolean;
210
+ /** See `MemberRedemptionOptions.linkRoundTripMs`. */
211
+ linkRoundTripMs?: number;
212
+ /** Per-address deadline override; default derived from `linkRoundTripMs`. */
213
+ addressBudgetMs?: number;
214
+ protocolId?: string;
215
+ /** Cancels the dial or stream in flight and ends the pass; the call throws the signal's reason. */
216
+ signal?: AbortSignal;
217
+ }
218
+ /** What a successful redemption yields the holder. */
219
+ export type OwnerGrantRedemption = MemberRedemption<OwnerGrantAccepted>;
220
+ /**
221
+ * Holder side: try the bundle's addresses one at a time and stop at the first acceptance or
222
+ * the first final refusal (`dialRedemption` in `member-redemption.ts`). Every address gets the
223
+ * SAME request, with one `usageStampId`: `OwnerGrantUsage` is keyed by it, so a member the
224
+ * holder gave up on that was still committing cannot spend a second use, and a retry after a
225
+ * dropped reply is answered `alreadyOwner`.
226
+ *
227
+ * @throws {OwnerGrantRejectedError} on a final refusal (its `retryable` is false).
228
+ * @throws {OwnerGrantReplyInvalidError} on an acceptance that fails {@link verifyOwnerGrantReply}.
229
+ * @throws {OwnerGrantUnreachableError} when every address was tried and none accepted.
230
+ * @throws the reason of `options.signal` once it aborts.
231
+ */
232
+ export declare function redeemOwnerGrantAtMembers(node: Libp2p, options: RedeemOwnerGrantAtMembersOptions): Promise<OwnerGrantRedemption>;
233
+ export interface RedeemOwnerGrantInPassesOptions extends RedeemOwnerGrantAtMembersOptions {
234
+ /** Keep making passes while every answer is retryable; false makes exactly one. */
235
+ waitForMember: boolean;
236
+ /** Called at each pass and each pause; an exception it throws is logged and ignored. */
237
+ onProgress?: (progress: CadreJoinProgress) => void;
238
+ }
239
+ /**
240
+ * Holder side, in passes (`dialRedemptionInPasses` in `member-redemption.ts`): one
241
+ * {@link redeemOwnerGrantAtMembers} pass, or, with `waitForMember`, as many as it takes,
242
+ * pausing between them and never past the grant's expiry, which by this holder's clock is
243
+ * thrown as the `grant-spent` refusal a member would give. A backup grant has no expiry, so a
244
+ * wait on one ends only by acceptance, a final refusal, the signal or the node stopping.
245
+ */
246
+ export declare function redeemOwnerGrantInPasses(node: Libp2p, options: RedeemOwnerGrantInPassesOptions): Promise<OwnerGrantRedemption>;
247
+ export {};
@@ -0,0 +1,330 @@
1
+ /**
2
+ * Owner grant redemption transport: `/sereus/owner-grant/1.0.0`.
3
+ *
4
+ * A holder of an owner grant (an owner-signed `OwnerGrant` row plus the private half of the
5
+ * grant keypair, see {@link OwnerGrantBundle}) dials ANY member machine the grant names and
6
+ * proves possession of the grant and of the key it wants seated; the member seats the row if
7
+ * it does not hold it yet and writes the holder's `OwnerKey` row through
8
+ * `ControlDatabase.redeemOwnerGrant`. No machine is admitted and no peer id is named: the
9
+ * holder's network identity has nothing to do with the key it seats, so unlike the invitation
10
+ * protocol there is no connecting-identity check — both signatures already bind the grant, the
11
+ * nonce and the key. The owner that minted the grant need not be online.
12
+ *
13
+ * The exchange shape — one frame each way, the member's hardening and admission of the
14
+ * holder, the holder's address-by-address dialing in passes — is `member-redemption.ts`'s,
15
+ * shared with the invitation protocol; this module supplies the grant's bundle, request,
16
+ * checks, writes and refusal codes. Stranger-facing by design, classed `stranger-open` in
17
+ * `control-protocol-guard.ts`; the handler's own trust decision is the two signatures.
18
+ */
19
+ import debug from 'debug';
20
+ import { toString as uint8ArrayToString, fromString as uint8ArrayFromString } from 'uint8arrays';
21
+ import { sign } from '@optimystic/quereus-plugin-crypto';
22
+ import { ownerGrantRedeemMessage, ownerGrantConsentMessage, OwnerGrantIssuerUnknownError, InvitationExhaustedError } from './control-database.js';
23
+ import { verifyOwnerGrantRow, verifyOwnerGrantRedemption } from './peer-authorization.js';
24
+ import { OWNER_KEY_MAX_LABEL } from './owner-key-export.js';
25
+ import { CADRE_INVITATION_PREFIX, CADRE_JOIN_REQUEST_PREFIX, OWNER_GRANT_PREFIX, OWNER_KEY_EXPORT_STEM } from './cadre-join-request.js';
26
+ import { MemberRedemptionHandler, constraintRefusal, dialRedemption, dialRedemptionInPasses, isBoundedString, isEd25519KeyB64, isNullableBoundedString, isNullableUseCap, rejection, writeFailureRefusal } from './member-redemption.js';
27
+ const log = debug('sereus:cadre:owner-grant-proto');
28
+ /** Protocol id for owner grant redemption (parallel to `/sereus/cadre-invite/1.0.0`). */
29
+ export const OWNER_GRANT_PROTOCOL = '/sereus/owner-grant/1.0.0';
30
+ /** What the dialer calls the credential in log lines, deadline labels and error text. */
31
+ const LABEL = 'Owner grant';
32
+ /** Most machines a grant bundle may name; the issuer caps its own list far below this. */
33
+ const MAX_BUNDLE_MEMBERS = 64;
34
+ /**
35
+ * Encode a bundle for out-of-band delivery: {@link OWNER_GRANT_PREFIX}, then base64url over
36
+ * JSON. The prefix lets an app tell a grant from an invitation, a join request or an owner key
37
+ * and name the mistake when one is pasted for the other.
38
+ */
39
+ export function encodeOwnerGrant(bundle) {
40
+ return `${OWNER_GRANT_PREFIX}${uint8ArrayToString(new TextEncoder().encode(JSON.stringify(bundle)), 'base64url')}`;
41
+ }
42
+ /**
43
+ * Decode a bundle, refusing anything that is not a well-formed version-1
44
+ * {@link OwnerGrantBundle} behind {@link OWNER_GRANT_PREFIX}. Standalone, like
45
+ * `decodeCadreInvitation`, so a client without a node can decode one.
46
+ *
47
+ * @throws on an owner key, a cadre invitation or a join request, a string without the prefix
48
+ * or that is not base64url JSON after it, or one that decodes to another shape or version.
49
+ */
50
+ export function decodeOwnerGrant(encoded) {
51
+ const trimmed = encoded.trim();
52
+ if (trimmed.startsWith(OWNER_KEY_EXPORT_STEM)) {
53
+ throw new Error('This is an owner key, not an owner grant; it is private, so import it only where the app asks for an owner key');
54
+ }
55
+ if (trimmed.startsWith(CADRE_INVITATION_PREFIX)) {
56
+ throw new Error('This is a cadre invitation, not an owner grant; paste it where the app asks for an invitation');
57
+ }
58
+ if (trimmed.startsWith(CADRE_JOIN_REQUEST_PREFIX)) {
59
+ throw new Error('This is a join request, not an owner grant; paste it into the app that manages your cadre');
60
+ }
61
+ if (!trimmed.startsWith(OWNER_GRANT_PREFIX)) {
62
+ throw new Error(`Owner grant must start with "${OWNER_GRANT_PREFIX}" (this one starts with "${trimmed.slice(0, OWNER_GRANT_PREFIX.length)}")`);
63
+ }
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(new TextDecoder().decode(uint8ArrayFromString(trimmed.slice(OWNER_GRANT_PREFIX.length), 'base64url')));
67
+ }
68
+ catch (error) {
69
+ throw new Error('Owner grant does not decode as base64url JSON', { cause: error });
70
+ }
71
+ if (!isWellFormedOwnerGrantBundle(parsed)) {
72
+ throw new Error('Owner grant is malformed or of an unsupported version');
73
+ }
74
+ return parsed;
75
+ }
76
+ function isWellFormedOwnerGrantBundle(value) {
77
+ if (typeof value !== 'object' || value === null)
78
+ return false;
79
+ const { v, partyId, grantPrivateKey, grant, ownerKeys, members } = value;
80
+ return v === 1
81
+ && isBoundedString(partyId)
82
+ && isEd25519KeyB64(grantPrivateKey)
83
+ && isWellFormedOwnerGrantRow(grant)
84
+ && Array.isArray(ownerKeys) && ownerKeys.length > 0 && ownerKeys.every((key) => isEd25519KeyB64(key))
85
+ && Array.isArray(members) && members.length <= MAX_BUNDLE_MEMBERS && members.every((addr) => isBoundedString(addr));
86
+ }
87
+ /** Is `value` an {@link OwnerGrantRow} with every column in its stored form and bounded? */
88
+ export function isWellFormedOwnerGrantRow(value) {
89
+ if (typeof value !== 'object' || value === null)
90
+ return false;
91
+ const row = value;
92
+ return isEd25519KeyB64(row.key)
93
+ && isNullableBoundedString(row.label, OWNER_KEY_MAX_LABEL)
94
+ && isNullableBoundedString(row.expiresAt)
95
+ && isNullableUseCap(row.totalUses)
96
+ && isBoundedString(row.stampId)
97
+ && isEd25519KeyB64(row.issuerKey)
98
+ && isBoundedString(row.issuerSig);
99
+ }
100
+ /** Which refusals are worth repeating at the next address — the one place that says so. */
101
+ export const OWNER_GRANT_REJECTION_RETRYABLE = {
102
+ 'issuer-unknown': true,
103
+ 'grant-invalid': false,
104
+ 'grant-spent': false,
105
+ 'party-mismatch': false,
106
+ 'busy': true,
107
+ 'conflict': true,
108
+ 'internal': true
109
+ };
110
+ /** Is `value` a code this build knows? Own keys only, so a peer's `'constructor'` does not pass. */
111
+ export function isOwnerGrantRejectionCode(value) {
112
+ return typeof value === 'string' && Object.prototype.hasOwnProperty.call(OWNER_GRANT_REJECTION_RETRYABLE, value);
113
+ }
114
+ // ── Errors the holder sees ───────────────────────────────────────────────────
115
+ /**
116
+ * A member answered and refused (on `CadreNode.redeemOwnerGrant`'s local path, the member is
117
+ * this node). `code` is `'unrecognized'` when the frame carried none this build knows, and such
118
+ * a refusal counts as retryable, as the invitation's does.
119
+ */
120
+ export class OwnerGrantRejectedError extends Error {
121
+ /** Both arguments come straight off the wire, so neither is trusted to have its declared type. */
122
+ constructor(code, reason) {
123
+ const text = typeof reason === 'string' ? reason : 'no reason provided';
124
+ super(`Owner grant refused: ${text}`);
125
+ this.name = 'OwnerGrantRejectedError';
126
+ this.code = isOwnerGrantRejectionCode(code) ? code : 'unrecognized';
127
+ this.reason = text;
128
+ this.retryable = this.code === 'unrecognized' || OWNER_GRANT_REJECTION_RETRYABLE[this.code];
129
+ }
130
+ }
131
+ /** Every address the bundle names was tried and none accepted. Always retryable; `outcomes` says what each address did. */
132
+ export class OwnerGrantUnreachableError extends Error {
133
+ constructor(outcomes) {
134
+ super(outcomes.length === 0
135
+ ? 'Owner grant names no dialable member'
136
+ : `Owner grant could not be redeemed at any of its ${outcomes.length} address(es): `
137
+ + outcomes.map((outcome) => `${outcome.addr}: ${outcome.error.message}`).join('; '));
138
+ this.outcomes = outcomes;
139
+ this.retryable = true;
140
+ this.name = 'OwnerGrantUnreachableError';
141
+ }
142
+ }
143
+ /**
144
+ * A member accepted but its reply does not check out: another party id, another grant key, or
145
+ * a row not signed by one of the pinned owner keys. Final, for the invitation's reason: such a
146
+ * machine is not a member of the cadre the grant names.
147
+ */
148
+ export class OwnerGrantReplyInvalidError extends Error {
149
+ constructor(message) {
150
+ super(`Owner grant reply refused: ${message}`);
151
+ this.retryable = false;
152
+ this.name = 'OwnerGrantReplyInvalidError';
153
+ }
154
+ }
155
+ // ── Shape checks ─────────────────────────────────────────────────────────────
156
+ function isWellFormedRedeemRequest(value) {
157
+ if (typeof value !== 'object' || value === null)
158
+ return false;
159
+ const { v, partyId, grant, ownerKey, usageStampId, grantSig, ownerSig } = value;
160
+ return v === 1
161
+ && isBoundedString(partyId)
162
+ && isWellFormedOwnerGrantRow(grant)
163
+ && isEd25519KeyB64(ownerKey)
164
+ && isBoundedString(usageStampId)
165
+ && isBoundedString(grantSig)
166
+ && isBoundedString(ownerSig);
167
+ }
168
+ /** An acceptance frame's fields. Throws on a malformed one. */
169
+ function decodeAccepted(reply) {
170
+ if (!isBoundedString(reply.partyId) || !isWellFormedOwnerGrantRow(reply.grant)) {
171
+ throw new Error('Owner grant acceptance is missing its party id or a well-formed row');
172
+ }
173
+ return { accepted: true, partyId: reply.partyId, grant: reply.grant, alreadyOwner: reply.alreadyOwner === true };
174
+ }
175
+ // ── Request construction (holder side) ───────────────────────────────────────
176
+ /**
177
+ * Build and sign the request for `bundle`: the holder's `'redeem'` signature with the grant's
178
+ * private key (held in memory for the length of this call) and the seated key's `'consent'`
179
+ * signature through `signConsent`, the `sign` of an open owner approval on the signer that
180
+ * holds `ownerKey`; both over (grant key, `usageStampId`, `ownerKey`) for the grant's party. The
181
+ * same bytes the schema verifies at the member (`ownerGrantRedeemMessage` /
182
+ * `ownerGrantConsentMessage`), and the same request goes to every member and every pass.
183
+ */
184
+ export async function signOwnerGrantRequest(bundle, ownerKey, signConsent, usageStampId) {
185
+ const fields = { grantKey: bundle.grant.key, usageStampId, seatedKey: ownerKey };
186
+ const grantSig = sign(ownerGrantRedeemMessage(bundle.partyId, fields), bundle.grantPrivateKey, 'ed25519', 'bytes', 'base64url', 'base64url');
187
+ const ownerSig = await signConsent(ownerGrantConsentMessage(bundle.partyId, fields));
188
+ return { v: 1, partyId: bundle.partyId, grant: bundle.grant, ownerKey, usageStampId, grantSig, ownerSig };
189
+ }
190
+ /**
191
+ * The holder's check on an acceptance: the same party, the same grant key, and a row signed by
192
+ * an issuer the holder pinned from the bundle. Throws {@link OwnerGrantReplyInvalidError} naming
193
+ * the first failure. Bounded as `verifyRedeemReply` is: it catches a wrong-party or wrong-row
194
+ * answer, not a forged member, which the holder's anchor settles once its store syncs.
195
+ */
196
+ export function verifyOwnerGrantReply(reply, bundle, isTrustedIssuer) {
197
+ if (reply.partyId !== bundle.partyId) {
198
+ throw new OwnerGrantReplyInvalidError(`the member serves party ${reply.partyId}, the grant names ${bundle.partyId}`);
199
+ }
200
+ if (reply.grant.key !== bundle.grant.key) {
201
+ throw new OwnerGrantReplyInvalidError('the member answered for a different grant');
202
+ }
203
+ if (!isTrustedIssuer(reply.grant.issuerKey)) {
204
+ throw new OwnerGrantReplyInvalidError('the row the member holds is not issued by one of the grant\'s owner keys');
205
+ }
206
+ if (!verifyOwnerGrantRow(bundle.partyId, reply.grant)) {
207
+ throw new OwnerGrantReplyInvalidError('the row the member holds is not signed by its issuer');
208
+ }
209
+ }
210
+ /** Constraint names the schema refuses a redemption with, and the code each maps to. */
211
+ const REDEEM_CONSTRAINT_CODES = [
212
+ [/CHECK constraint failed: Authorized\b/, 'grant-spent', 'The grant is expired, withdrawn, exhausted, or its issuer is no longer an owner'],
213
+ [/CHECK constraint failed: (GrantPossessed|OwnerConsented|SeatedExists)\b/, 'grant-invalid', 'The redemption does not satisfy the grant'],
214
+ [/CHECK constraint failed: NotRevoked\b/, 'grant-spent', 'The grant was withdrawn'],
215
+ ];
216
+ /**
217
+ * Member side of the grant protocol (`MemberRedemptionHandler` has the shape): after the
218
+ * request's shape, it checks the party and both signatures — nothing about the connecting
219
+ * peer, whose identity is unrelated to the key it seats — then seats the row from the bundle
220
+ * and redeems. An issuer this member does not know as an owner is the one retryable refusal
221
+ * left: the holder tries the next address, which may hold the issuer's row.
222
+ */
223
+ export class OwnerGrantHandler extends MemberRedemptionHandler {
224
+ constructor(options) {
225
+ super('Owner grant', OWNER_GRANT_PROTOCOL, options);
226
+ this.busyRefusal = rejection('busy', 'Too many concurrent redemptions');
227
+ this.internalRefusal = rejection('internal', 'Internal redemption error');
228
+ this.malformedRefusal = rejection('grant-invalid', 'Malformed redemption request');
229
+ this.store = options.store;
230
+ }
231
+ isWellFormedRequest(value) {
232
+ return isWellFormedRedeemRequest(value);
233
+ }
234
+ checkRequest(request) {
235
+ if (request.partyId !== this.partyId) {
236
+ return rejection('party-mismatch', 'This machine serves another cadre');
237
+ }
238
+ const fields = { grantKey: request.grant.key, usageStampId: request.usageStampId, seatedKey: request.ownerKey };
239
+ if (!verifyOwnerGrantRedemption(this.partyId, fields, request.grantSig, request.ownerSig)) {
240
+ return rejection('grant-invalid', 'The redemption signatures do not verify');
241
+ }
242
+ return null;
243
+ }
244
+ isLive(request) {
245
+ return this.store.isOwnerGrantLive(request.grant);
246
+ }
247
+ /** The two writes — the seat (its own transaction; a no-op when held) and the redemption — each answered by name when it fails. */
248
+ async redeemAdmitted(request, remotePeerId) {
249
+ try {
250
+ await this.store.seatOwnerGrant(request.grant);
251
+ }
252
+ catch (error) {
253
+ if (error instanceof OwnerGrantIssuerUnknownError) {
254
+ return rejection('issuer-unknown', 'The grant\'s issuer is not known as an owner here');
255
+ }
256
+ log('seating grant %s from %s failed: %o', request.grant.key, remotePeerId, error);
257
+ return constraintRefusal(error, REDEEM_CONSTRAINT_CODES) ?? writeFailureRefusal(error);
258
+ }
259
+ let alreadyOwner;
260
+ try {
261
+ const result = await this.store.redeemOwnerGrant({
262
+ grantKey: request.grant.key,
263
+ seatedKey: request.ownerKey,
264
+ usageStampId: request.usageStampId,
265
+ grantSig: request.grantSig,
266
+ ownerSig: request.ownerSig
267
+ });
268
+ alreadyOwner = result.alreadyOwner;
269
+ log('grant %s redeemed for %s by %s (alreadyOwner=%s)', request.grant.key, request.ownerKey, remotePeerId, alreadyOwner);
270
+ }
271
+ catch (error) {
272
+ if (error instanceof InvitationExhaustedError) {
273
+ return rejection('grant-spent', 'The grant has no uses left');
274
+ }
275
+ log('redeeming grant %s for %s failed: %o', request.grant.key, request.ownerKey, error);
276
+ return constraintRefusal(error, REDEEM_CONSTRAINT_CODES) ?? writeFailureRefusal(error);
277
+ }
278
+ // The row as held: the seat inserted this copy verbatim, or found the same row.
279
+ return { accepted: true, partyId: this.partyId, grant: request.grant, alreadyOwner };
280
+ }
281
+ }
282
+ /** The grant's half of the shared dial loop: its label, protocol, bundle, codec, checks and errors. */
283
+ function grantRedemption(options) {
284
+ return {
285
+ label: LABEL,
286
+ protocolId: options.protocolId ?? OWNER_GRANT_PROTOCOL,
287
+ members: options.bundle.members,
288
+ request: options.request,
289
+ decodeAccepted,
290
+ refusal: (code, reason) => new OwnerGrantRejectedError(code, reason),
291
+ verifyAccepted: (reply) => verifyOwnerGrantReply(reply, options.bundle, options.isTrustedIssuer),
292
+ unreachable: (outcomes) => new OwnerGrantUnreachableError(outcomes),
293
+ ...(options.linkRoundTripMs !== undefined ? { linkRoundTripMs: options.linkRoundTripMs } : {}),
294
+ ...(options.addressBudgetMs !== undefined ? { addressBudgetMs: options.addressBudgetMs } : {}),
295
+ ...(options.signal ? { signal: options.signal } : {}),
296
+ };
297
+ }
298
+ /**
299
+ * Holder side: try the bundle's addresses one at a time and stop at the first acceptance or
300
+ * the first final refusal (`dialRedemption` in `member-redemption.ts`). Every address gets the
301
+ * SAME request, with one `usageStampId`: `OwnerGrantUsage` is keyed by it, so a member the
302
+ * holder gave up on that was still committing cannot spend a second use, and a retry after a
303
+ * dropped reply is answered `alreadyOwner`.
304
+ *
305
+ * @throws {OwnerGrantRejectedError} on a final refusal (its `retryable` is false).
306
+ * @throws {OwnerGrantReplyInvalidError} on an acceptance that fails {@link verifyOwnerGrantReply}.
307
+ * @throws {OwnerGrantUnreachableError} when every address was tried and none accepted.
308
+ * @throws the reason of `options.signal` once it aborts.
309
+ */
310
+ export function redeemOwnerGrantAtMembers(node, options) {
311
+ return dialRedemption(node, grantRedemption(options));
312
+ }
313
+ /**
314
+ * Holder side, in passes (`dialRedemptionInPasses` in `member-redemption.ts`): one
315
+ * {@link redeemOwnerGrantAtMembers} pass, or, with `waitForMember`, as many as it takes,
316
+ * pausing between them and never past the grant's expiry, which by this holder's clock is
317
+ * thrown as the `grant-spent` refusal a member would give. A backup grant has no expiry, so a
318
+ * wait on one ends only by acceptance, a final refusal, the signal or the node stopping.
319
+ */
320
+ export function redeemOwnerGrantInPasses(node, options) {
321
+ const passes = {
322
+ ...grantRedemption(options),
323
+ waitForMember: options.waitForMember,
324
+ expiresAt: options.bundle.grant.expiresAt,
325
+ expired: () => new OwnerGrantRejectedError('grant-spent', 'the grant expired before a member accepted it'),
326
+ ...(options.onProgress ? { onProgress: options.onProgress } : {}),
327
+ };
328
+ return dialRedemptionInPasses(node, passes);
329
+ }
330
+ //# sourceMappingURL=owner-grant-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-grant-protocol.js","sourceRoot":"","sources":["../src/owner-grant-protocol.ts"],"names":[],"mappings":"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"}