@cef-ai/vault-sdk 3.3.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +26 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +40 -3
- package/dist/client.js.map +1 -1
- package/dist/core/canonical.d.ts +17 -1
- package/dist/core/canonical.d.ts.map +1 -1
- package/dist/core/canonical.js +26 -1
- package/dist/core/canonical.js.map +1 -1
- package/dist/core/endpoints.d.ts +5 -4
- package/dist/core/endpoints.d.ts.map +1 -1
- package/dist/core/endpoints.js +13 -4
- package/dist/core/endpoints.js.map +1 -1
- package/dist/core/grant-doc.d.ts +345 -0
- package/dist/core/grant-doc.d.ts.map +1 -0
- package/dist/core/grant-doc.js +603 -0
- package/dist/core/grant-doc.js.map +1 -0
- package/dist/core/types.d.ts +181 -49
- package/dist/core/types.d.ts.map +1 -1
- package/dist/fluent/vault.d.ts +6 -0
- package/dist/fluent/vault.d.ts.map +1 -1
- package/dist/fluent/vault.js +7 -0
- package/dist/fluent/vault.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/memberships.d.ts +360 -0
- package/dist/internal/memberships.d.ts.map +1 -0
- package/dist/internal/memberships.js +403 -0
- package/dist/internal/memberships.js.map +1 -0
- package/dist/internal/vaults.d.ts +22 -0
- package/dist/internal/vaults.d.ts.map +1 -1
- package/dist/internal/vaults.js +11 -0
- package/dist/internal/vaults.js.map +1 -1
- package/dist/internal-exports.d.ts +2 -1
- package/dist/internal-exports.d.ts.map +1 -1
- package/dist/internal-exports.js +1 -1
- package/dist/internal-exports.js.map +1 -1
- package/package.json +3 -3
- package/dist/internal/orgs.d.ts +0 -59
- package/dist/internal/orgs.d.ts.map +0 -1
- package/dist/internal/orgs.js +0 -80
- package/dist/internal/orgs.js.map +0 -1
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import type { Signer } from "@cef-ai/signer";
|
|
2
|
+
import type { VaultHttpClient } from "../core/http.js";
|
|
3
|
+
import type { Member, MemberRole, MembershipSummary, ScopeGrants, SignedRoster } from "../core/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* What the caller already knows about the membership's OTHER half, so the
|
|
6
|
+
* grant document can be built without reading it back.
|
|
7
|
+
*
|
|
8
|
+
* The document always describes the membership as it will read AFTER the
|
|
9
|
+
* write, and each write route sets only one of its two components (see
|
|
10
|
+
* `Memberships`' doc comment). Absent, the SDK reads the other half from the
|
|
11
|
+
* server; supplied, it is signed as given — which saves the round trip for a
|
|
12
|
+
* console that already holds the roster, and is refused with a 400 naming the
|
|
13
|
+
* document the server derived if it is wrong.
|
|
14
|
+
*/
|
|
15
|
+
export interface PutMemberOptions {
|
|
16
|
+
/** The scope grants this member ALREADY holds. Default: read back. */
|
|
17
|
+
scopes?: ScopeGrants;
|
|
18
|
+
}
|
|
19
|
+
/** @see PutMemberOptions */
|
|
20
|
+
export interface PutScopesOptions {
|
|
21
|
+
/**
|
|
22
|
+
* The standing this member ALREADY has — BOTH halves this route does not
|
|
23
|
+
* set. Default: read both back off the roster in one GET.
|
|
24
|
+
*
|
|
25
|
+
* ONE OPTION CARRYING TWO FIELDS, replacing the former `role?`. The grant
|
|
26
|
+
* document covers the role AND the expiry, and this route changes neither,
|
|
27
|
+
* so a caller who knew only the role would have had the SDK sign
|
|
28
|
+
* "never expires" for a membership that does expire — a document vault-api
|
|
29
|
+
* refuses, and would have honoured as a widening if it did not. Knowing
|
|
30
|
+
* half the standing is not knowing the standing.
|
|
31
|
+
*
|
|
32
|
+
* `expiresAt` absent inside this object means the membership has no expiry.
|
|
33
|
+
* Pass the spelling you read off `list()`; any spelling of the right
|
|
34
|
+
* instant is accepted, because the server compares instants (it cannot
|
|
35
|
+
* render the signer's original string back out of a timestamp column).
|
|
36
|
+
*/
|
|
37
|
+
standing?: {
|
|
38
|
+
role: MemberRole;
|
|
39
|
+
expiresAt?: string;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Who belongs to a vault, in what role, holding which scope grants — and,
|
|
44
|
+
* from the other direction, which vaults the caller belongs to.
|
|
45
|
+
*
|
|
46
|
+
* ## THERE IS NO ORG ENTITY (D1)
|
|
47
|
+
*
|
|
48
|
+
* This class replaces `sdk.orgs`, which addressed an `orgId`. The `orgs`
|
|
49
|
+
* table and every `/api/v1/orgs…` route were removed, not aliased: a vault
|
|
50
|
+
* IS the organization, and **a vault BECOMES one by acquiring a second
|
|
51
|
+
* member**, which is `put()` below. There is deliberately no `create` — the
|
|
52
|
+
* removed `POST /api/v1/orgs` needed only half a replacement, the naming
|
|
53
|
+
* half, and that is `sdk.vault.rename()` (`PATCH /api/v1/vaults/:vaultId`),
|
|
54
|
+
* because a name is a property of the vault and a single-member vault must
|
|
55
|
+
* be nameable too.
|
|
56
|
+
*
|
|
57
|
+
* ## The one thing a consumer porting from `sdk.orgs` gets wrong
|
|
58
|
+
*
|
|
59
|
+
* `mine()` does NOT include the caller's own vault. `sdk.orgs.list()` folded
|
|
60
|
+
* the two together by synthesising an owner entry; the owner is never a
|
|
61
|
+
* membership row under D1, and `sdk.vault.current()` already answers "my own
|
|
62
|
+
* vault" keyed by wallet. **A switcher shows both by calling both** — and
|
|
63
|
+
* folding them here would double-count for anyone who did:
|
|
64
|
+
*
|
|
65
|
+
* ```ts
|
|
66
|
+
* const [own, joined] = await Promise.all([
|
|
67
|
+
* sdk.vault.current(), // the vault this wallet owns
|
|
68
|
+
* sdk.memberships.mine(), // the vaults this wallet was invited into
|
|
69
|
+
* ]);
|
|
70
|
+
* ```
|
|
71
|
+
*
|
|
72
|
+
* ## THE TWO WRITES CARRY A SECOND SIGNATURE, AND IT IS THE OWNER'S
|
|
73
|
+
*
|
|
74
|
+
* `put()` and `putScopes()` send `X-Grant-Signature`: the VAULT OWNER's
|
|
75
|
+
* ed25519 signature over the grant's canonical document
|
|
76
|
+
* (`canonicalGrantBytes`). ddc-node #1136 made it mandatory on both, so
|
|
77
|
+
* without it neither method can succeed at all — a 400 `grant sig: missing
|
|
78
|
+
* X-Grant-Signature`. They send `X-Grant-Issued-At` alongside it, carrying the
|
|
79
|
+
* moment the document was minted: it is inside the signed bytes, and the
|
|
80
|
+
* server rebuilds those bytes rather than receiving them, so it has no way to
|
|
81
|
+
* supply that field itself. It is a header of its own rather than the wallet auth's
|
|
82
|
+
* `X-Signature` because the two cover different bytes: `X-Signature` covers
|
|
83
|
+
* the request BODY and authenticates the caller, while this covers a document
|
|
84
|
+
* that names the vault, the member, the role and the scopes, so one signature
|
|
85
|
+
* cannot be replayed onto another member or another vault.
|
|
86
|
+
*
|
|
87
|
+
* `remove()` sends NO grant signature, and that is not an omission —
|
|
88
|
+
* `DeleteMember` has no such check. Read the handler before assuming
|
|
89
|
+
* symmetry: revocation deletes the row (and, by FK, its grants), so there is
|
|
90
|
+
* no post-write standing left for a document to describe.
|
|
91
|
+
*
|
|
92
|
+
* ### The document describes the membership AFTER the write, and each route
|
|
93
|
+
* ### knows only half of it
|
|
94
|
+
*
|
|
95
|
+
* `PutMember` builds its document from the role in the body and the scopes
|
|
96
|
+
* ALREADY IN THE STORE; `PutScopes` builds its own from the scopes in the
|
|
97
|
+
* body and the role already in the store. So each method reads the other half
|
|
98
|
+
* back before signing — one extra GET — unless the caller supplies it
|
|
99
|
+
* (`PutMemberOptions.scopes` / `PutScopesOptions.role`). Signing the same
|
|
100
|
+
* bytes for both calls is refused by the second.
|
|
101
|
+
*
|
|
102
|
+
* ### AN ADMIN WHO IS NOT THE OWNER CANNOT SIGN
|
|
103
|
+
*
|
|
104
|
+
* The route's gate admits the vault owner OR a live `role: "admin"` member,
|
|
105
|
+
* but `verifyGrantDocument` checks the signature against the VAULT's wallet
|
|
106
|
+
* key and nothing else. So an admin can be authorised to make this request
|
|
107
|
+
* and unable to produce the document it must carry. The SDK signs with the
|
|
108
|
+
* configured `signer`, which is the owner in the ordinary case of an owner
|
|
109
|
+
* administering their own vault; a non-owner admin gets a 400 naming the
|
|
110
|
+
* document, and needs one their owner signed out of band — pass it by calling
|
|
111
|
+
* the route through `VaultHttpClient` directly with the header set. There is
|
|
112
|
+
* no in-band way to obtain it today.
|
|
113
|
+
*
|
|
114
|
+
* ## Every mutation body carries a `timestamp`
|
|
115
|
+
*
|
|
116
|
+
* The wallet-signature middleware (`pkg/shared/auth/signature.go`) rejects
|
|
117
|
+
* ANY mutation body with no top-level RFC3339 `timestamp` as 401
|
|
118
|
+
* `INVALID_SIGNATURE "body missing timestamp"`, before the request reaches
|
|
119
|
+
* a handler. `WalletAuthProvider` supplies one during canonicalisation;
|
|
120
|
+
* `DelegationAuthProvider` (which never passes through that middleware)
|
|
121
|
+
* supplies nothing — so each method below sends its own, keeping the body
|
|
122
|
+
* correct on both paths. It is NOT a replay guard: ddc-node parses the field
|
|
123
|
+
* and no membership handler reads it.
|
|
124
|
+
*/
|
|
125
|
+
export declare class Memberships {
|
|
126
|
+
private readonly http;
|
|
127
|
+
private readonly signer?;
|
|
128
|
+
/**
|
|
129
|
+
* `signer` is the VAULT OWNER's key, and it is required by `put` and
|
|
130
|
+
* `putScopes` only — every read here, and `remove`, work without one.
|
|
131
|
+
* Optional so that constructing this class from
|
|
132
|
+
* `@cef-ai/vault-sdk/internal` for reads alone keeps working unchanged;
|
|
133
|
+
* a write without it throws `VaultSignerRequiredError` rather than
|
|
134
|
+
* sending a request the server will refuse.
|
|
135
|
+
*/
|
|
136
|
+
constructor(http: VaultHttpClient, signer?: Signer | undefined);
|
|
137
|
+
/**
|
|
138
|
+
* The vaults the caller is a MEMBER of, with their own grants on each —
|
|
139
|
+
* the employee's vault switcher. `GET /api/v1/memberships`.
|
|
140
|
+
*
|
|
141
|
+
* Excludes the caller's own vault; see this class's doc comment, which is
|
|
142
|
+
* the single most likely thing to get wrong when porting from
|
|
143
|
+
* `sdk.orgs.list()`.
|
|
144
|
+
*
|
|
145
|
+
* LIVE memberships only: a membership that is suspended or past its
|
|
146
|
+
* `expiresAt` is absent, not present-with-a-state. `scopes` is always
|
|
147
|
+
* present on every entry (these are the caller's OWN grants, so there is
|
|
148
|
+
* no disclosure question) and is `{}` — never `null` — when they hold
|
|
149
|
+
* none.
|
|
150
|
+
*/
|
|
151
|
+
mine(): Promise<MembershipSummary[]>;
|
|
152
|
+
/**
|
|
153
|
+
* The vault's roster. `GET /api/v1/vaults/:vaultId/members`.
|
|
154
|
+
*
|
|
155
|
+
* Readable by the vault owner or any of its own LIVE members, whatever
|
|
156
|
+
* their role; 403 (uniformly, so an outsider cannot enumerate) otherwise,
|
|
157
|
+
* and 404 if the vault was never claimed.
|
|
158
|
+
*
|
|
159
|
+
* THE OWNER ROW IS FIRST, is synthesised (`isOwner: true`, `role:
|
|
160
|
+
* "admin"`, `state: "active"`), and carries NO `scopes` — see `Member`.
|
|
161
|
+
* Every other row's `scopes` is present only when disclosed to the caller.
|
|
162
|
+
* `Member.scopes` being absent is NOT the same as `{}`; do not default it.
|
|
163
|
+
*/
|
|
164
|
+
list(vaultId: string): Promise<Member[]>;
|
|
165
|
+
/**
|
|
166
|
+
* The same roster as SIGNED EVIDENCE.
|
|
167
|
+
* `GET /api/v1/vaults/:vaultId/roster/signed`.
|
|
168
|
+
*
|
|
169
|
+
* Each entry carries the canonical grant document the vault owner signed
|
|
170
|
+
* and that signature, so a party that does NOT trust this vault-api can
|
|
171
|
+
* decide what a member may do. That is the entire point of the route, and
|
|
172
|
+
* it only holds if the consumer checks the documents AGAINST SOMETHING
|
|
173
|
+
* THIS RESPONSE DID NOT SUPPLY:
|
|
174
|
+
*
|
|
175
|
+
* ```ts
|
|
176
|
+
* import { verifySignedRoster } from "@cef-ai/vault-sdk";
|
|
177
|
+
*
|
|
178
|
+
* const roster = await sdk.memberships.signedRoster(vaultId);
|
|
179
|
+
* const grants = await verifySignedRoster(roster, vaultId); // throws on any entry
|
|
180
|
+
* // act on `grants` — never on roster.grants[i].role / .scopes
|
|
181
|
+
* ```
|
|
182
|
+
*
|
|
183
|
+
* **Pass the SAME `vaultId` you asked for.** `verifySignedRoster` requires
|
|
184
|
+
* it and will not verify without it, because the alternative is not a
|
|
185
|
+
* weaker check but a meaningless one: `orgWalletPubkey` arrives inside the
|
|
186
|
+
* response, so a roster checked only against itself proves that whoever
|
|
187
|
+
* answered can sign — never that they are the vault's owner. The id is the
|
|
188
|
+
* one value the responder does not get to choose; `vaultIdFor` makes the
|
|
189
|
+
* owner key answer to it. A caller holding the owner key instead of the id
|
|
190
|
+
* gets the id from `vaultIdFor(ownerKey)`.
|
|
191
|
+
*
|
|
192
|
+
* What this does NOT establish: that the vault id is the one you meant. It
|
|
193
|
+
* anchors the roster to a vault, so anchor the vault to something you knew
|
|
194
|
+
* beforehand rather than to a value the same untrusted party handed you.
|
|
195
|
+
*
|
|
196
|
+
* The raw shape is returned rather than the verified one so evidence can be
|
|
197
|
+
* forwarded to a third party intact; `verifySignedRoster` is the step that
|
|
198
|
+
* turns it into values worth acting on. `SignedGrant.role` and
|
|
199
|
+
* `.scopes` are vault-api's own decoding of `doc`, provided for display —
|
|
200
|
+
* enforcing on them verifies one thing and enforces another.
|
|
201
|
+
*
|
|
202
|
+
* Same gate and same disclosure rule as `list()`: readable by the owner or
|
|
203
|
+
* any LIVE member (404 for an unclaimed vault, a uniform 403 otherwise),
|
|
204
|
+
* owner and live admin see every grant, a plain member only their own. Two
|
|
205
|
+
* differences from `list()`, both deliberate: the owner is NOT an entry
|
|
206
|
+
* here (they hold no signed document — `orgWalletPubkey` is where they
|
|
207
|
+
* appear), and only LIVE memberships are served, so there is no `state`
|
|
208
|
+
* field to check.
|
|
209
|
+
*/
|
|
210
|
+
signedRoster(vaultId: string): Promise<SignedRoster>;
|
|
211
|
+
/**
|
|
212
|
+
* Adds or updates a member. `PUT /api/v1/vaults/:vaultId/members/:memberPubkey`.
|
|
213
|
+
*
|
|
214
|
+
* **This is how a vault becomes an organization** — there is no
|
|
215
|
+
* registration step; the first successful call is the whole ceremony.
|
|
216
|
+
*
|
|
217
|
+
* Requires the vault owner or a live `role: "admin"` member. 400 if
|
|
218
|
+
* `memberPubkey` is the vault's own owner — the owner is never a
|
|
219
|
+
* membership row (D1) — and 404 if the vault is unclaimed.
|
|
220
|
+
*
|
|
221
|
+
* `memberPubkey` should already be in the server's canonical
|
|
222
|
+
* 0x-lowercase-hex spelling (`auth.CanonicalPubKeyHex`), which is the one
|
|
223
|
+
* spelling every authorization read looks members up by.
|
|
224
|
+
*
|
|
225
|
+
* `expiresAt` MUST BE RFC 3339 — vault-api parses it for the timestamptz
|
|
226
|
+
* column and 400s anything else, naming the field. It is also INSIDE THE
|
|
227
|
+
* SIGNED DOCUMENT now, and the server rebuilds the document from the string
|
|
228
|
+
* this method sends: the exact spelling passed here is what is signed and
|
|
229
|
+
* what is sent, never re-derived from a `Date` on either side. Formatting it
|
|
230
|
+
* twice is how the two copies drift by a trimmed fractional zero and the
|
|
231
|
+
* signature fails as though the key were wrong.
|
|
232
|
+
*
|
|
233
|
+
* The returned `Member` carries neither `scopes` nor `isOwner`: it is the
|
|
234
|
+
* row just written, and grants are a separate call (`putScopes`).
|
|
235
|
+
*
|
|
236
|
+
* CARRIES THE OWNER'S `X-Grant-Signature` over
|
|
237
|
+
* `{vaultId, memberPubkey, role, scopes, issuedAt, expiresAt}` — see the
|
|
238
|
+
* class doc comment. The scopes in that document are the ones the member
|
|
239
|
+
* ALREADY HOLDS, because this route sets the role only, so re-roling a
|
|
240
|
+
* member with grants signs those grants too. They are read back with `scopes()` (a 404 — the new
|
|
241
|
+
* member case — is `{}`); pass `{ scopes }` to skip that GET when they are
|
|
242
|
+
* already in hand.
|
|
243
|
+
*/
|
|
244
|
+
put(vaultId: string, memberPubkey: string, role: MemberRole, expiresAt?: string, opts?: PutMemberOptions): Promise<Member>;
|
|
245
|
+
/**
|
|
246
|
+
* Removes a member row. `DELETE /api/v1/vaults/:vaultId/members/:memberPubkey`.
|
|
247
|
+
*
|
|
248
|
+
* 409 — not 404 — for the vault's own owner: they cannot be removed at
|
|
249
|
+
* all, and 404 would read as "already gone, nothing left to do" to an
|
|
250
|
+
* admin who believed they had locked the founder out.
|
|
251
|
+
*
|
|
252
|
+
* ddc-node's handler never reads the body, but the wallet-signature
|
|
253
|
+
* middleware still requires a top-level `timestamp` on every mutation
|
|
254
|
+
* regardless of what the handler does with it — so this body is
|
|
255
|
+
* `{timestamp}` and nothing else.
|
|
256
|
+
*
|
|
257
|
+
* NO `X-Grant-Signature`, deliberately and after reading `DeleteMember`:
|
|
258
|
+
* the grant check lives in `verifyGrantDocument`, which only `PutMember`
|
|
259
|
+
* and `PutScopes` call. Adding one here on the assumption that the three
|
|
260
|
+
* writes are symmetrical would send a header the server ignores and would
|
|
261
|
+
* make this method need a signer it has no use for.
|
|
262
|
+
*/
|
|
263
|
+
remove(vaultId: string, memberPubkey: string): Promise<void>;
|
|
264
|
+
/**
|
|
265
|
+
* A member's scope grants.
|
|
266
|
+
* `GET /api/v1/vaults/:vaultId/members/:memberPubkey/scopes`.
|
|
267
|
+
*
|
|
268
|
+
* Readable by the vault owner, a live admin, or the member themselves.
|
|
269
|
+
* 404 when the membership does not exist — INCLUDING when the vault OWNER
|
|
270
|
+
* asks for their own grants, which is the read-side face of "the owner is
|
|
271
|
+
* never a row": their authority is key math and there is no grant row.
|
|
272
|
+
*
|
|
273
|
+
* `list()` already carries `scopes` inline on every disclosed row, so a
|
|
274
|
+
* console rendering a roster should NOT call this per member — that is an
|
|
275
|
+
* N+1. This is for reading one membership's grants directly.
|
|
276
|
+
*/
|
|
277
|
+
scopes(vaultId: string, memberPubkey: string): Promise<{
|
|
278
|
+
scopes: ScopeGrants;
|
|
279
|
+
}>;
|
|
280
|
+
/**
|
|
281
|
+
* Replaces a member's FULL scope-grant set.
|
|
282
|
+
* `PUT /api/v1/vaults/:vaultId/members/:memberPubkey/scopes`.
|
|
283
|
+
*
|
|
284
|
+
* The server deletes then reinserts, so this is never a merge or a diff
|
|
285
|
+
* against the existing grants — send the complete intended set. 404 if the
|
|
286
|
+
* membership row does not exist, INCLUDING for an empty `scopes` map: the
|
|
287
|
+
* check is EXISTENCE, not liveness, so an admin may prepare the grants of
|
|
288
|
+
* a currently-suspended membership.
|
|
289
|
+
*
|
|
290
|
+
* CARRIES THE OWNER'S `X-Grant-Signature` over
|
|
291
|
+
* `{vaultId, memberPubkey, role, scopes, issuedAt, expiresAt}` — see the
|
|
292
|
+
* class doc comment. The role AND the expiry in that document are the ones
|
|
293
|
+
* the member ALREADY HOLDS, because this route sets the scopes only; both
|
|
294
|
+
* are read off the roster (`list()`) in one GET, which is why a
|
|
295
|
+
* `memberPubkey` with no row fails here rather than as the server's 404.
|
|
296
|
+
* Pass `{ standing: { role, expiresAt } }` to skip it.
|
|
297
|
+
*
|
|
298
|
+
* THE EXPIRY IS ALSO SENT IN THE BODY, and that is the one place this route
|
|
299
|
+
* differs from `put`. vault-api holds the expiry as a timestamp and the
|
|
300
|
+
* document carries the signer's STRING, which a timestamp cannot be
|
|
301
|
+
* rendered back into — so the server cannot supply this field the way it
|
|
302
|
+
* supplies the role. It checks what is sent against the stored instant, so
|
|
303
|
+
* stating it cannot widen the membership: a different moment is a 400.
|
|
304
|
+
*/
|
|
305
|
+
putScopes(vaultId: string, memberPubkey: string, scopes: ScopeGrants, opts?: PutScopesOptions): Promise<void>;
|
|
306
|
+
/**
|
|
307
|
+
* The vault owner's signature over this grant's canonical document, as the
|
|
308
|
+
* `X-Grant-Signature` header — see the class doc comment for why a write
|
|
309
|
+
* cannot land without it.
|
|
310
|
+
*
|
|
311
|
+
* `memberPubkey` is canonicalised FIRST. The server canonicalises the URL
|
|
312
|
+
* parameter before it derives the bytes (`memberPubkeyParam`), so signing
|
|
313
|
+
* the caller's own spelling of a bare or upper-case key produces a valid
|
|
314
|
+
* signature over a document the server never builds — a 400 that reads as
|
|
315
|
+
* a key problem. `vaultId` is NOT canonicalised, because the server does
|
|
316
|
+
* not touch it either.
|
|
317
|
+
*
|
|
318
|
+
* ED25519 ONLY, and checked here. `authz.VerifyGrantSig` hard-codes
|
|
319
|
+
* `SchemeEd25519` (unlike the request-auth middleware, which also takes
|
|
320
|
+
* sr25519), so an sr25519 owner can authenticate the request and still
|
|
321
|
+
* never produce a document the server will accept. Named up front rather
|
|
322
|
+
* than left to surface as an opaque signature refusal.
|
|
323
|
+
*/
|
|
324
|
+
private grantHeader;
|
|
325
|
+
/**
|
|
326
|
+
* The scope grants this member holds RIGHT NOW — the half of `put`'s
|
|
327
|
+
* document that route reads from the store rather than from its body.
|
|
328
|
+
*
|
|
329
|
+
* A 404 is `{}`, not a failure: it is what `GET .../scopes` answers for a
|
|
330
|
+
* membership row that does not exist yet, which is the ordinary case of
|
|
331
|
+
* adding a NEW member, and it is exactly what the server's own
|
|
332
|
+
* `ListScopeGrantsForMember` yields there (it tolerates `ErrNotFound`).
|
|
333
|
+
* Every other error propagates — a 403 means this caller may not administer
|
|
334
|
+
* the vault at all, and guessing `{}` would turn it into a puzzling 400
|
|
335
|
+
* from the write instead.
|
|
336
|
+
*/
|
|
337
|
+
private heldScopes;
|
|
338
|
+
/**
|
|
339
|
+
* The role AND expiry this member holds RIGHT NOW — the two halves of
|
|
340
|
+
* `putScopes`'s document that route reads from the store rather than from
|
|
341
|
+
* its body.
|
|
342
|
+
*
|
|
343
|
+
* BOTH OUT OF ONE ROW, deliberately. They used to be one value read here
|
|
344
|
+
* and one value the document did not carry at all; now that the expiry is
|
|
345
|
+
* signed, fetching them separately would be two chances for them to
|
|
346
|
+
* describe different moments of the same membership.
|
|
347
|
+
*
|
|
348
|
+
* From the roster rather than from a route of its own, because there is no
|
|
349
|
+
* single-membership read that carries a role: `GET .../scopes` returns only
|
|
350
|
+
* grants. The synthesised OWNER row is skipped explicitly — the owner is
|
|
351
|
+
* never a membership row (D1), so a `memberPubkey` matching it is the
|
|
352
|
+
* server's 400, not a standing to sign.
|
|
353
|
+
*
|
|
354
|
+
* `expiresAt` absent on the row means the membership does not expire; the
|
|
355
|
+
* roster omits the key rather than sending null (Go `omitempty`), which is
|
|
356
|
+
* the same three-state distinction `Member.scopes` documents.
|
|
357
|
+
*/
|
|
358
|
+
private heldStanding;
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=memberships.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memberships.d.ts","sourceRoot":"","sources":["../../src/internal/memberships.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAavD,OAAO,KAAK,EACV,MAAM,EACN,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,YAAY,EACb,MAAM,kBAAkB,CAAC;AAE1B;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,4BAA4B;AAC5B,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkFG;AACH,qBAAa,WAAW;IAUpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IAV1B;;;;;;;OAOG;gBAEgB,IAAI,EAAE,eAAe,EACrB,MAAM,CAAC,EAAE,MAAM,YAAA;IAGlC;;;;;;;;;;;;;OAaG;IACH,IAAI,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAIpC;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAIxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4CG;IACH,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAIpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,GAAG,CACP,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,UAAU,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,CAAC;IAalB;;;;;;;;;;;;;;;;;OAiBG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5D;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,CAAA;KAAE,CAAC;IAI/E;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACG,SAAS,CACb,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,IAAI,CAAC;IAUhB;;;;;;;;;;;;;;;;;OAiBG;YACW,WAAW;IAiDzB;;;;;;;;;;;OAWG;YACW,UAAU;IASxB;;;;;;;;;;;;;;;;;;;OAmBG;YACW,YAAY;CAkB3B"}
|