@kubun/store-credential 0.17.3 → 0.18.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/lib/advisory-locks.d.ts +5 -0
- package/lib/advisory-locks.js +12 -0
- package/lib/api-aliases.d.ts +3 -0
- package/lib/api-aliases.js +58 -0
- package/lib/api-entries.d.ts +3 -0
- package/lib/api-entries.js +157 -0
- package/lib/api-keys.d.ts +3 -0
- package/lib/api-keys.js +249 -0
- package/lib/api-provisioning.d.ts +3 -0
- package/lib/api-provisioning.js +227 -0
- package/lib/api-records.d.ts +3 -0
- package/lib/api-records.js +74 -0
- package/lib/api-types.d.ts +412 -0
- package/lib/api-types.js +14 -0
- package/lib/api.d.ts +5 -429
- package/lib/api.js +24 -968
- package/lib/definition.js +3 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.js +1 -0
- package/lib/migrations.js +62 -36
- package/lib/records.d.ts +206 -0
- package/lib/records.js +905 -0
- package/lib/store-context.d.ts +37 -0
- package/lib/store-context.js +139 -0
- package/lib/tables.d.ts +88 -64
- package/package.json +11 -8
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import type { MethodRegistry } from '@kokuin/token';
|
|
2
|
+
import type { RecordKey, SignedRecord } from '@kubun/records';
|
|
3
|
+
import type { CredentialEntry, CredentialEntryWithProvenance, CredentialFactorDescriptor, CredentialKey, CredentialKeyBranch, CredentialKeyState, CredentialManifestKey, CredentialRecordRow, CredentialRevocation, CredentialWrapping, CredentialWrappingWithBranch } from './tables.js';
|
|
4
|
+
/**
|
|
5
|
+
* The persisted half of a credential manifest — a structural subset of the
|
|
6
|
+
* plugin's signed `CredentialManifestClaim`, so a verified claim can pass
|
|
7
|
+
* straight to {@link CredentialStoreAPI.putManifest} without mapping. This
|
|
8
|
+
* package neither signs nor verifies; the raw token rides alongside as `token`.
|
|
9
|
+
*/
|
|
10
|
+
export type CredentialManifestRecord = {
|
|
11
|
+
ownerDID: string;
|
|
12
|
+
recipientDID: string;
|
|
13
|
+
grantorDID: string;
|
|
14
|
+
epoch: number;
|
|
15
|
+
sequence: number;
|
|
16
|
+
keys: Array<CredentialManifestKey>;
|
|
17
|
+
};
|
|
18
|
+
export type ListManifestsParams = {
|
|
19
|
+
ownerDID: string;
|
|
20
|
+
recipientDID: string;
|
|
21
|
+
};
|
|
22
|
+
/** One stored manifest: its persisted record, the signed token that authored it, and delegation tokens. */
|
|
23
|
+
export type StoredCredentialManifest = {
|
|
24
|
+
record: CredentialManifestRecord;
|
|
25
|
+
token: string;
|
|
26
|
+
delegationTokens: Array<string>;
|
|
27
|
+
};
|
|
28
|
+
export type PutWrappingAuthorityParams = {
|
|
29
|
+
wrappingID: string;
|
|
30
|
+
ownerDID?: string;
|
|
31
|
+
envelope: string;
|
|
32
|
+
refreshSeq: number;
|
|
33
|
+
};
|
|
34
|
+
export type WrappingAuthority = {
|
|
35
|
+
envelope: string;
|
|
36
|
+
refreshSeq: number;
|
|
37
|
+
};
|
|
38
|
+
export type NextGrantorSequenceParams = {
|
|
39
|
+
ownerDID: string;
|
|
40
|
+
recipientDID: string;
|
|
41
|
+
grantorDID: string;
|
|
42
|
+
};
|
|
43
|
+
export type NextProvisioningEpochParams = {
|
|
44
|
+
ownerDID: string;
|
|
45
|
+
recipientDID: string;
|
|
46
|
+
grantorDID: string;
|
|
47
|
+
minEpoch: number;
|
|
48
|
+
};
|
|
49
|
+
export type ListDistributableKeysParams = {
|
|
50
|
+
ownerDID: string;
|
|
51
|
+
grantorDID: string;
|
|
52
|
+
};
|
|
53
|
+
export type PutCredentialKeyParams = {
|
|
54
|
+
keyID: string;
|
|
55
|
+
ownerDID: string;
|
|
56
|
+
suite: number;
|
|
57
|
+
version: number;
|
|
58
|
+
state: CredentialKeyState;
|
|
59
|
+
};
|
|
60
|
+
export type PutCredentialWrappingParams = {
|
|
61
|
+
wrappingID: string;
|
|
62
|
+
keyID: string;
|
|
63
|
+
ownerDID?: string;
|
|
64
|
+
keyVersion: number;
|
|
65
|
+
factors: Array<CredentialFactorDescriptor>;
|
|
66
|
+
iv: Uint8Array;
|
|
67
|
+
wrappedKey: Uint8Array;
|
|
68
|
+
recipientDID?: string | null;
|
|
69
|
+
authority?: WrappingAuthority;
|
|
70
|
+
};
|
|
71
|
+
export type PutCredentialManifestParams = {
|
|
72
|
+
record: CredentialManifestRecord;
|
|
73
|
+
token: string;
|
|
74
|
+
delegationTokens?: Array<string>;
|
|
75
|
+
};
|
|
76
|
+
export type PutCredentialEntryParams = {
|
|
77
|
+
entryID: string;
|
|
78
|
+
keyID: string;
|
|
79
|
+
ownerDID?: string;
|
|
80
|
+
keyVersion: number;
|
|
81
|
+
iv: Uint8Array;
|
|
82
|
+
ciphertext: Uint8Array;
|
|
83
|
+
hlc: string;
|
|
84
|
+
};
|
|
85
|
+
export type UpdateStoredEntryIfUnchangedParams = PutCredentialEntryParams & {
|
|
86
|
+
expectedHLC: string;
|
|
87
|
+
};
|
|
88
|
+
/** The address of a device's own grant: which provider, for which owner, on which device. */
|
|
89
|
+
export type CredentialAliasKey = {
|
|
90
|
+
providerName: string;
|
|
91
|
+
ownerDID: string;
|
|
92
|
+
deviceDID: string;
|
|
93
|
+
};
|
|
94
|
+
export type SetDeviceAliasParams = CredentialAliasKey & {
|
|
95
|
+
entryID: string;
|
|
96
|
+
/** Owner of the entry; defaults to `ownerDID`. */
|
|
97
|
+
entryOwnerDID?: string;
|
|
98
|
+
};
|
|
99
|
+
/** Deletes only when the stored `entryID` matches. */
|
|
100
|
+
export type DeleteDeviceAliasIfEntryParams = CredentialAliasKey & {
|
|
101
|
+
entryID: string;
|
|
102
|
+
};
|
|
103
|
+
export type ListDeviceAliasOwnersParams = {
|
|
104
|
+
providerName: string;
|
|
105
|
+
deviceDID: string;
|
|
106
|
+
};
|
|
107
|
+
/**
|
|
108
|
+
* Per-device grant pointers. Local, like the two-key aliases: each device points at the entry
|
|
109
|
+
* holding its own grant. Values are stored and compared verbatim, so a caller normalizes.
|
|
110
|
+
*/
|
|
111
|
+
export type CredentialDeviceAliasAPI = {
|
|
112
|
+
getDeviceAliasEntry(key: CredentialAliasKey): Promise<{
|
|
113
|
+
entryID: string;
|
|
114
|
+
entryOwnerDID: string;
|
|
115
|
+
} | null>;
|
|
116
|
+
getDeviceAliasEntryID(key: CredentialAliasKey): Promise<string | null>;
|
|
117
|
+
/** Point `(provider, owner, device)` at `entryID`, replacing any prior target. */
|
|
118
|
+
setDeviceAliasEntryID(params: SetDeviceAliasParams): Promise<void>;
|
|
119
|
+
deleteDeviceAliasEntryID(key: CredentialAliasKey): Promise<void>;
|
|
120
|
+
deleteDeviceAliasIfEntry(params: DeleteDeviceAliasIfEntryParams): Promise<void>;
|
|
121
|
+
listDeviceAliasOwnersForProvider(params: ListDeviceAliasOwnersParams): Promise<Array<string>>;
|
|
122
|
+
/** Every device alias of one owner, ordered by provider then device. */
|
|
123
|
+
listDeviceAliasesForOwner(ownerDID: string): Promise<Array<CredentialAliasKey & {
|
|
124
|
+
entryID: string;
|
|
125
|
+
}>>;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Persistence for credential keys, wrappings and entries.
|
|
129
|
+
*
|
|
130
|
+
* Storage only: nothing here wraps, unwraps, encrypts or decrypts, and nothing
|
|
131
|
+
* here interprets a ciphertext. `ciphertext` and `wrapped_key` are opaque byte
|
|
132
|
+
* strings that come back exactly as they went in — not parsed as JSON, not
|
|
133
|
+
* decoded as UTF-8, not validated in any way. A caller owning the crypto is what
|
|
134
|
+
* lets the suite change without a migration.
|
|
135
|
+
*
|
|
136
|
+
* Replicated writes use signed records; local GraphQL writes use these row verbs.
|
|
137
|
+
* Owner-qualified arguments address one projection. An omitted owner is accepted
|
|
138
|
+
* only when the stored ID has one owner; ambiguous IDs fail closed. Legacy local
|
|
139
|
+
* writes without a key row use the empty owner namespace.
|
|
140
|
+
*/
|
|
141
|
+
export type CredentialStoreAPI = CredentialDeviceAliasAPI & {
|
|
142
|
+
/** Whether this store is bound to a caller-owned database transaction. */
|
|
143
|
+
readonly isTransaction?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Run `fn` against a `CredentialStoreAPI` scoped to one atomic transaction.
|
|
146
|
+
* Nesting-safe: if `this` is already bound to an open Kysely transaction,
|
|
147
|
+
* `fn` runs inline against `this` instead of opening a second one (Kysely
|
|
148
|
+
* has no nested transactions), so callers can invoke this unconditionally.
|
|
149
|
+
*/
|
|
150
|
+
transaction<R>(fn: (store: CredentialStoreAPI) => Promise<R>): Promise<R>;
|
|
151
|
+
/**
|
|
152
|
+
* Serialize writers of one key's version, wrappings and entries.
|
|
153
|
+
* Call first inside a transaction, before reading those rows. The lock lasts
|
|
154
|
+
* until that transaction commits or rolls back, even if the key row is absent.
|
|
155
|
+
* Call `lockKeyRows` instead when a transaction can touch more than one key.
|
|
156
|
+
*/
|
|
157
|
+
lockKeyRow(keyID: string): Promise<void>;
|
|
158
|
+
/** Acquire a complete key set before authoritative reads; Postgres orders by advisory ID. */
|
|
159
|
+
lockKeyRows(keyIDs: ReadonlyArray<string>): Promise<void>;
|
|
160
|
+
putKey(params: PutCredentialKeyParams): Promise<void>;
|
|
161
|
+
getKey(keyID: string, ownerDID?: string): Promise<CredentialKey | undefined>;
|
|
162
|
+
listKeys(ownerDID: string): Promise<Array<CredentialKey>>;
|
|
163
|
+
setKeyState(keyID: string, state: CredentialKeyState, ownerDID?: string): Promise<void>;
|
|
164
|
+
/** Bump a key to a new version. Wrappings and entries at earlier versions stay. */
|
|
165
|
+
setKeyVersion(keyID: string, version: number, ownerDID?: string): Promise<void>;
|
|
166
|
+
deleteKey(keyID: string, ownerDID?: string): Promise<void>;
|
|
167
|
+
listKeyBranches(keyID: string, keyVersion: number, ownerDID?: string): Promise<Array<CredentialKeyBranch>>;
|
|
168
|
+
/**
|
|
169
|
+
* `authority`, when present, upserts the wrapping's grantor-authority envelope
|
|
170
|
+
* in the SAME transaction as the wrapping row, so a crash can't
|
|
171
|
+
* leave a held wrapping this device can't later prove was authorized. Omitted
|
|
172
|
+
* for an owner-signed wrapping. Gated strictly-greater on `refreshSeq`, same
|
|
173
|
+
* as {@link CredentialStoreAPI.putWrappingAuthority}.
|
|
174
|
+
*/
|
|
175
|
+
putWrapping(params: PutCredentialWrappingParams): Promise<void>;
|
|
176
|
+
getWrapping(wrappingID: string, ownerDID?: string): Promise<CredentialWrapping | undefined>;
|
|
177
|
+
/** Every wrapping for a key, or only those at one version. */
|
|
178
|
+
listWrappings(keyID: string, keyVersion?: number, ownerDID?: string): Promise<Array<CredentialWrapping>>;
|
|
179
|
+
/**
|
|
180
|
+
* As {@link listWrappings}, each row carrying the branch of its replicated record.
|
|
181
|
+
* The fork-aware read path
|
|
182
|
+
* needs the label to resolve which content-key branch a device opens.
|
|
183
|
+
*/
|
|
184
|
+
listWrappingsWithBranch(keyID: string, keyVersion?: number, ownerDID?: string): Promise<Array<CredentialWrappingWithBranch>>;
|
|
185
|
+
deleteWrapping(wrappingID: string, ownerDID?: string): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* Drop every wrapping for a key below `keyVersion` — what a rotation leaves
|
|
188
|
+
* behind. Replicated deletion uses record tombstones through the record adapter.
|
|
189
|
+
*/
|
|
190
|
+
deleteWrappingsBelowVersion(keyID: string, keyVersion: number, ownerDID?: string): Promise<void>;
|
|
191
|
+
putEntry(params: PutCredentialEntryParams): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Explicitly change an entry's key association. Callers must authorize both
|
|
194
|
+
* source and target keys before invoking this capability.
|
|
195
|
+
*/
|
|
196
|
+
moveEntry(params: PutCredentialEntryParams): Promise<void>;
|
|
197
|
+
/**
|
|
198
|
+
* Write over an entry's ciphertext ONLY if the row already exists under the
|
|
199
|
+
* same key — never inserts, never moves it. Returns 'absent' when nothing was updated.
|
|
200
|
+
*/
|
|
201
|
+
updateEntryIfPresent(params: PutCredentialEntryParams): Promise<'updated' | 'absent'>;
|
|
202
|
+
/**
|
|
203
|
+
* As {@link updateEntryIfPresent}, and also conditional on the entry row still
|
|
204
|
+
* carrying `expectedHLC`, the stamp its writer read it at. The check and the
|
|
205
|
+
* write are one atomic section, so a write that landed since that read (a new
|
|
206
|
+
* consent, say) is never overwritten: it reports `'superseded'` and touches
|
|
207
|
+
* nothing.
|
|
208
|
+
*/
|
|
209
|
+
updateEntryIfUnchanged(params: UpdateStoredEntryIfUnchangedParams): Promise<'updated' | 'absent' | 'superseded'>;
|
|
210
|
+
getEntry(entryID: string, ownerDID?: string): Promise<CredentialEntry | undefined>;
|
|
211
|
+
listEntryOwners(entryID: string): Promise<Array<string>>;
|
|
212
|
+
getEntryWithProvenance(entryID: string, ownerDID?: string): Promise<CredentialEntryWithProvenance | undefined>;
|
|
213
|
+
listEntries(keyID: string, ownerDID?: string): Promise<Array<CredentialEntry>>;
|
|
214
|
+
/**
|
|
215
|
+
* Greatest stored entry HLC, or `null` when there are none. Credential writes
|
|
216
|
+
* advance the device clock but leave no row in the graph mutation log, so this
|
|
217
|
+
* is the only trace they leave for a restart floor to read.
|
|
218
|
+
*/
|
|
219
|
+
getMaxEntryHLC(): Promise<string | null>;
|
|
220
|
+
deleteEntry(entryID: string, ownerDID?: string): Promise<void>;
|
|
221
|
+
/** Store a wrapping's grantor-authority envelope; gated strictly-greater on `refreshSeq` (stale/replayed is a silent no-op). */
|
|
222
|
+
putWrappingAuthority(params: PutWrappingAuthorityParams): Promise<void>;
|
|
223
|
+
/** The stored envelope and its `refreshSeq`, or `undefined` when unset. */
|
|
224
|
+
getWrappingAuthority(wrappingID: string, ownerDID?: string): Promise<WrappingAuthority | undefined>;
|
|
225
|
+
/**
|
|
226
|
+
* Mint the next `refreshSeq` for one `(ownerDID, recipientDID, grantorDID)`
|
|
227
|
+
* triple: 1 on the first call, strictly increasing thereafter. Persisted, so
|
|
228
|
+
* a restart never reissues a number already handed out.
|
|
229
|
+
*/
|
|
230
|
+
nextGrantorSequence(params: NextGrantorSequenceParams): Promise<number>;
|
|
231
|
+
/**
|
|
232
|
+
* Allocate the next `epoch` for one `(ownerDID, recipientDID, grantorDID)`
|
|
233
|
+
* triple: returns `max(stored, minEpoch) + 1` on each call, so the value is
|
|
234
|
+
* strictly increasing but a floor can jump it forward. Persisted; never
|
|
235
|
+
* reissues an epoch already handed out. Triple is keyed on normalized DIDs,
|
|
236
|
+
* so a `did:peer:4` short/long form converge on one row.
|
|
237
|
+
*/
|
|
238
|
+
nextProvisioningEpoch(params: NextProvisioningEpochParams): Promise<number>;
|
|
239
|
+
/**
|
|
240
|
+
* Store a grantor's manifest, gated lexicographically on `(epoch, sequence)`
|
|
241
|
+
* per `(ownerDID, recipientDID, grantorDID)` triple — higher epoch always
|
|
242
|
+
* wins, sequence breaks ties within an epoch; a stale/replayed value is a
|
|
243
|
+
* silent no-op. Triple keyed on normalized DIDs. `token` is the raw signed
|
|
244
|
+
* manifest; `delegationTokens` are optional wrappings that authorized it.
|
|
245
|
+
*/
|
|
246
|
+
putManifest(params: PutCredentialManifestParams): Promise<void>;
|
|
247
|
+
/**
|
|
248
|
+
* Every grantor's manifest for one `(ownerDID, recipientDID)`, one row per
|
|
249
|
+
* grantor. Arguments are normalized before query, matching
|
|
250
|
+
* {@link CredentialStoreAPI.putManifest}'s normalize-on-write.
|
|
251
|
+
*/
|
|
252
|
+
listManifests(params: ListManifestsParams): Promise<Array<StoredCredentialManifest>>;
|
|
253
|
+
/**
|
|
254
|
+
* Take the write lock on the manifest row so a held-epoch read later in the
|
|
255
|
+
* SAME transaction can't race a concurrent {@link CredentialStoreAPI.putManifest}.
|
|
256
|
+
* A value-preserving UPDATE, not `FOR UPDATE` (SQLite rejects that syntax) —
|
|
257
|
+
* it blocks a concurrent Postgres writer the same way; SQLite is already
|
|
258
|
+
* single-writer-serialized. No-op if the row doesn't exist yet; that
|
|
259
|
+
* first-write race is benign (held epoch 0).
|
|
260
|
+
*/
|
|
261
|
+
lockManifestRow(params: {
|
|
262
|
+
ownerDID: string;
|
|
263
|
+
recipientDID: string;
|
|
264
|
+
grantorDID: string;
|
|
265
|
+
}): Promise<void>;
|
|
266
|
+
/**
|
|
267
|
+
* Every active owner key for which a wrapping exists at the key's current
|
|
268
|
+
* version addressed (after normalization) to the grantor. One snapshot read;
|
|
269
|
+
* in-memory DID normalization. Deduped by keyID.
|
|
270
|
+
*/
|
|
271
|
+
listDistributableKeys(params: ListDistributableKeysParams): Promise<Array<{
|
|
272
|
+
keyID: string;
|
|
273
|
+
version: number;
|
|
274
|
+
}>>;
|
|
275
|
+
/**
|
|
276
|
+
* Begin tracking a provisioning attempt, idempotent on the id. Ensures an
|
|
277
|
+
* expectation floor row exists (at 0) if none yet. The attempt counts toward
|
|
278
|
+
* outstanding and blocks readiness until cleared.
|
|
279
|
+
*/
|
|
280
|
+
beginProvisioningAttempt(params: {
|
|
281
|
+
ownerDID: string;
|
|
282
|
+
grantorDID: string;
|
|
283
|
+
attemptID: string;
|
|
284
|
+
}): Promise<void>;
|
|
285
|
+
/**
|
|
286
|
+
* Record a provisioning attempt's outcome, atomically. If `epoch > heldEpoch`,
|
|
287
|
+
* clears the attempt row and raises the expectation floor to
|
|
288
|
+
* `max(stored, epoch)`; otherwise leaves the attempt row and returns retry.
|
|
289
|
+
*/
|
|
290
|
+
recordProvisioningAttempt(params: {
|
|
291
|
+
ownerDID: string;
|
|
292
|
+
grantorDID: string;
|
|
293
|
+
attemptID: string;
|
|
294
|
+
epoch: number;
|
|
295
|
+
heldEpoch: number;
|
|
296
|
+
}): Promise<{
|
|
297
|
+
status: 'recorded';
|
|
298
|
+
} | {
|
|
299
|
+
status: 'retry';
|
|
300
|
+
minEpoch: number;
|
|
301
|
+
}>;
|
|
302
|
+
/**
|
|
303
|
+
* Abandon a provisioning attempt. Deletes ONLY the attempt row, never touches
|
|
304
|
+
* the expectation floor.
|
|
305
|
+
*/
|
|
306
|
+
abandonProvisioningAttempt(params: {
|
|
307
|
+
ownerDID: string;
|
|
308
|
+
grantorDID: string;
|
|
309
|
+
attemptID: string;
|
|
310
|
+
}): Promise<void>;
|
|
311
|
+
/**
|
|
312
|
+
* Abandon ALL outstanding provisioning attempts for one (owner, grantor)
|
|
313
|
+
* scope. Deletes every attempt row for the pair, never touches the
|
|
314
|
+
* expectation floor. The recovery escape hatch when the attempt id is lost.
|
|
315
|
+
*
|
|
316
|
+
* Exclusive-recovery contract: this also clears any OTHER live coordinator's
|
|
317
|
+
* attempt on the same scope (whose later `recordProvisioningAttempt` would
|
|
318
|
+
* then hit the phantom-attempt guard and not raise the floor). Callers must
|
|
319
|
+
* ensure no other live attempt exists for the scope before calling. When the
|
|
320
|
+
* id is known, prefer `abandonProvisioningAttempt`, which is safe under
|
|
321
|
+
* concurrency.
|
|
322
|
+
*/
|
|
323
|
+
abandonProvisioningAttempts(params: {
|
|
324
|
+
ownerDID: string;
|
|
325
|
+
grantorDID: string;
|
|
326
|
+
}): Promise<void>;
|
|
327
|
+
/**
|
|
328
|
+
* List provisioning expectations for one owner: one row per (owner, grantor)
|
|
329
|
+
* pair currently held. Returns the expectation floor and count of outstanding
|
|
330
|
+
* attempts. Normalizes ownerDID on read.
|
|
331
|
+
*/
|
|
332
|
+
listProvisioningExpectations(params: {
|
|
333
|
+
ownerDID: string;
|
|
334
|
+
}): Promise<Array<{
|
|
335
|
+
grantorDID: string;
|
|
336
|
+
epochFloor: number;
|
|
337
|
+
outstanding: number;
|
|
338
|
+
}>>;
|
|
339
|
+
/**
|
|
340
|
+
* Every distinct owner DID with a provisioning expectation row, normalized
|
|
341
|
+
* and de-duped — the catalog-independent enumeration
|
|
342
|
+
* `listProvisioningExpectations` can't give on its own (it's per-owner).
|
|
343
|
+
*/
|
|
344
|
+
listProvisioningExpectationOwners(): Promise<Array<string>>;
|
|
345
|
+
/**
|
|
346
|
+
* Refresh a controller-owned key's `credential/administer` delegation chain,
|
|
347
|
+
* gated strictly-greater on `refreshSeq` (stale/replayed is a silent no-op,
|
|
348
|
+
* same shape as {@link CredentialStoreAPI.putWrappingAuthority}). Handles
|
|
349
|
+
* both the absent-row insert and the monotone race. Returns whether a row
|
|
350
|
+
* was inserted or updated.
|
|
351
|
+
*/
|
|
352
|
+
refreshKeyOwnerDelegation(params: {
|
|
353
|
+
keyID: string;
|
|
354
|
+
ownerDID?: string;
|
|
355
|
+
delegationTokens: Array<string>;
|
|
356
|
+
refreshSeq: number;
|
|
357
|
+
}): Promise<boolean>;
|
|
358
|
+
/**
|
|
359
|
+
* Compare-and-swap a key-owner delegation chain, guarded on the `revision`
|
|
360
|
+
* the caller read. Replaces the row only when its CURRENT `revision` still
|
|
361
|
+
* equals `expectedRevision`, so a writer that read an invalid-present chain
|
|
362
|
+
* and revalidated it can install a replacement without racing another such
|
|
363
|
+
* writer or a concurrent refresh. The guard is `revision`, NOT `refreshSeq`:
|
|
364
|
+
* two distinct valid chains can share a `refreshSeq` (min-exp ms), so guarding
|
|
365
|
+
* on the seq has an ABA hole. Unlike {@link refreshKeyOwnerDelegation} this
|
|
366
|
+
* never inserts and is not monotone — it is the escape hatch for the
|
|
367
|
+
* invalid-present case, where the incoming chain's `refreshSeq` may be lower.
|
|
368
|
+
* Absent row is a no-op false, same as a revision mismatch. A successful
|
|
369
|
+
* write bumps `revision`.
|
|
370
|
+
*/
|
|
371
|
+
replaceKeyOwnerDelegationIfUnchanged(params: {
|
|
372
|
+
keyID: string;
|
|
373
|
+
ownerDID?: string;
|
|
374
|
+
expectedRevision: number;
|
|
375
|
+
delegationTokens: Array<string>;
|
|
376
|
+
refreshSeq: number;
|
|
377
|
+
}): Promise<boolean>;
|
|
378
|
+
/** The stored delegation chain, its `refreshSeq`, and its `revision`, or `undefined` when unset. */
|
|
379
|
+
getKeyOwnerDelegation(keyID: string, ownerDID?: string): Promise<{
|
|
380
|
+
delegationTokens: Array<string>;
|
|
381
|
+
refreshSeq: number;
|
|
382
|
+
revision: number;
|
|
383
|
+
} | undefined>;
|
|
384
|
+
/**
|
|
385
|
+
* The stored row of one replicated record, tombstone included, as the table holds it.
|
|
386
|
+
* `credentialRecordAdapter` reads records through this; nothing here decodes the row.
|
|
387
|
+
*/
|
|
388
|
+
getRecordRow(type: string, id: string): Promise<CredentialRecordRow | undefined>;
|
|
389
|
+
getRecordRows(key: RecordKey): Promise<Array<CredentialRecordRow>>;
|
|
390
|
+
/** `getRecordRows` of each key, keyed by `recordKeyText`; a key without rows is absent. */
|
|
391
|
+
getRecordRowsForKeys(keys: ReadonlyArray<RecordKey>): Promise<Map<string, Array<CredentialRecordRow>>>;
|
|
392
|
+
deleteRecordCopy(key: RecordKey, opHash: string): Promise<void>;
|
|
393
|
+
/**
|
|
394
|
+
* The stored rows of every record of the given types. Their order is the adapter's
|
|
395
|
+
* collation, which differs between SQLite and Postgres, so a caller that needs an order
|
|
396
|
+
* sorts them itself.
|
|
397
|
+
*/
|
|
398
|
+
listRecordRows(types: ReadonlyArray<string>): Promise<Array<CredentialRecordRow>>;
|
|
399
|
+
/**
|
|
400
|
+
* Store a signed record as the current op of its `(type, id)` with its indexed row, in
|
|
401
|
+
* one transaction. See `putCredentialRecord` for what it checks and throws.
|
|
402
|
+
*/
|
|
403
|
+
putRecord(record: SignedRecord, methods?: MethodRegistry): Promise<void>;
|
|
404
|
+
/** All authenticated entry candidates, including losing branch operations. */
|
|
405
|
+
listEntryCandidates(keyID: string, keyVersion: number, ownerDID?: string): Promise<Array<SignedRecord>>;
|
|
406
|
+
/** Earlier signed tombstones that must participate in fork repair entry ordering. */
|
|
407
|
+
listPriorEntryTombstones(keyID: string, beforeVersion: number, ownerDID?: string): Promise<Array<SignedRecord>>;
|
|
408
|
+
/** Called after record authorization, including when the candidate loses the merge. */
|
|
409
|
+
retainEntryCandidate(record: SignedRecord, methods?: MethodRegistry): Promise<void>;
|
|
410
|
+
/** The recipients revoked from a key, ordered by recipient. */
|
|
411
|
+
listRevocations(keyID: string, ownerDID?: string): Promise<Array<CredentialRevocation>>;
|
|
412
|
+
};
|
package/lib/api-types.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistence for credential keys, wrappings and entries.
|
|
3
|
+
*
|
|
4
|
+
* Storage only: nothing here wraps, unwraps, encrypts or decrypts, and nothing
|
|
5
|
+
* here interprets a ciphertext. `ciphertext` and `wrapped_key` are opaque byte
|
|
6
|
+
* strings that come back exactly as they went in — not parsed as JSON, not
|
|
7
|
+
* decoded as UTF-8, not validated in any way. A caller owning the crypto is what
|
|
8
|
+
* lets the suite change without a migration.
|
|
9
|
+
*
|
|
10
|
+
* Replicated writes use signed records; local GraphQL writes use these row verbs.
|
|
11
|
+
* Owner-qualified arguments address one projection. An omitted owner is accepted
|
|
12
|
+
* only when the stored ID has one owner; ambiguous IDs fail closed. Legacy local
|
|
13
|
+
* writes without a key row use the empty owner namespace.
|
|
14
|
+
*/ export { };
|