@openlfcp/client 0.2.2 → 0.3.1

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 (43) hide show
  1. package/dist/data-unit.d.ts +11 -0
  2. package/dist/data-unit.js +9 -0
  3. package/dist/identity/accept.d.ts +115 -0
  4. package/dist/identity/accept.js +335 -0
  5. package/dist/identity/context.d.ts +214 -0
  6. package/dist/identity/context.js +495 -0
  7. package/dist/identity/devices.d.ts +127 -0
  8. package/dist/identity/devices.js +221 -0
  9. package/dist/identity/document.d.ts +112 -0
  10. package/dist/identity/document.js +54 -0
  11. package/dist/identity/index.d.ts +17 -0
  12. package/dist/identity/index.js +17 -0
  13. package/dist/identity/journal.d.ts +139 -0
  14. package/dist/identity/journal.js +202 -0
  15. package/dist/identity/network.d.ts +88 -0
  16. package/dist/identity/network.js +243 -0
  17. package/dist/identity/pairing-request.d.ts +147 -0
  18. package/dist/identity/pairing-request.js +422 -0
  19. package/dist/identity/pairing.d.ts +225 -0
  20. package/dist/identity/pairing.js +624 -0
  21. package/dist/identity/phases.d.ts +75 -0
  22. package/dist/identity/phases.js +104 -0
  23. package/dist/identity/proof.d.ts +45 -0
  24. package/dist/identity/proof.js +71 -0
  25. package/dist/identity/reconcile.d.ts +73 -0
  26. package/dist/identity/reconcile.js +273 -0
  27. package/dist/identity/resource.d.ts +74 -0
  28. package/dist/identity/resource.js +201 -0
  29. package/dist/identity/revocation.d.ts +106 -0
  30. package/dist/identity/revocation.js +403 -0
  31. package/dist/identity/roster.d.ts +89 -0
  32. package/dist/identity/roster.js +130 -0
  33. package/dist/identity/rotation.d.ts +131 -0
  34. package/dist/identity/rotation.js +363 -0
  35. package/dist/index.d.ts +2 -1
  36. package/dist/index.js +2 -1
  37. package/dist/revoke.d.ts +8 -0
  38. package/dist/revoke.js +12 -8
  39. package/dist/storage.d.ts +18 -0
  40. package/dist/storage.js +26 -0
  41. package/dist/sync-client.d.ts +2 -0
  42. package/dist/sync-client.js +1 -0
  43. package/package.json +5 -5
@@ -0,0 +1,214 @@
1
+ import { type ControlRecordId, type DataEpoch, type DataUnitId, type PrincipalId, type ResourceId } from "@openlfcp/core";
2
+ import { type AgreementKeyPair, type ResourceDEK } from "@openlfcp/crypto";
3
+ import { type LfcpStorage, type SecretStore } from "@openlfcp/storage";
4
+ import { type DataUnitPayload, type Parsed, type PrincipalDescriptor, type Signer } from "@openlfcp/wire";
5
+ import { type IdentityDocumentPort, type IdentityIntent } from "./document.js";
6
+ import { type JournalPhase, type OperationJournal, type PackageLedger } from "./journal.js";
7
+ import type { IdentityChannel } from "./network.js";
8
+ import type { LinearChain, PhaseState } from "./phases.js";
9
+ /** The storage the identity flows use. */
10
+ export type IdentityStorage = Pick<LfcpStorage, "control" | "commit" | "localMarks" | "actorSequences">;
11
+ /** This installation, as the identity flows act for it. */
12
+ export interface Installation {
13
+ /** Its Principal's signer: a device's, or the root's when it has no devices yet. */
14
+ readonly signer: Signer;
15
+ /** Its X25519 key, to open Key Packages. */
16
+ readonly agreement: AgreementKeyPair;
17
+ }
18
+ /** The Resource or the Identity Resource is forked (§9.7): approval, reconciliation and rotation are suspended. */
19
+ export declare class IdentityConflict extends Error {
20
+ readonly resource: ResourceId;
21
+ constructor(resource: ResourceId, message: string);
22
+ }
23
+ /**
24
+ * Synchronises the Control Chain of `resource` from the coordinator and
25
+ * stores it: the local chain extended with the coordinator's later
26
+ * records, or the coordinator's whole chain when the local one does not
27
+ * extend. A fork is stored as a conflict and thrown (§9.7).
28
+ */
29
+ export declare function syncChain(storage: IdentityStorage, channel: IdentityChannel, resource: ResourceId): Promise<LinearChain>;
30
+ /** Validates `chain` extended with `record` (e.g. after an ACK) and stores it. */
31
+ export declare function extendChain(storage: IdentityStorage, chain: LinearChain, record: Uint8Array): Promise<LinearChain>;
32
+ export interface ControlPhaseSpec {
33
+ readonly id: string;
34
+ readonly kind: JournalPhase["kind"];
35
+ readonly resource: ResourceId;
36
+ readonly facts?: Readonly<Record<string, string>>;
37
+ /** §9.2 classification on the synchronised chain; `isOwn` tells this installation's record IDs. */
38
+ classify(chain: LinearChain, isOwn: (recordIdHex: string) => boolean): PhaseState;
39
+ /** The signed record on the chain's head (§9.3: rebuilt on a new head, never re-sent as it was). */
40
+ build(chain: LinearChain): Promise<Uint8Array> | Uint8Array;
41
+ /**
42
+ * False for a phase whose record depends on more than the head, such as a
43
+ * KEY_EPOCH and its frontier (§9.3): a pending record is rebuilt on every
44
+ * attempt, even on the head it was built on. An accepted one is still
45
+ * recognised by its journaled record ID.
46
+ */
47
+ readonly resend?: boolean;
48
+ }
49
+ export interface PhaseOutcome {
50
+ readonly state: PhaseState | "refused";
51
+ readonly chain: LinearChain;
52
+ /** The NACK code of a refused phase. */
53
+ readonly code?: string;
54
+ readonly recordId?: ControlRecordId;
55
+ }
56
+ /**
57
+ * Runs one Control Plane phase durably (§9.1–§9.3). The phase is
58
+ * classified on the synchronised chain first; while it is `pending`, the
59
+ * exact bytes are persisted before they are sent: the same bytes again
60
+ * while the head is the one they were built on (a lost ACK is answered
61
+ * with the same ACK, W §47), a record rebuilt on a new head otherwise.
62
+ */
63
+ export declare function runControlPhase(storage: IdentityStorage, channel: IdentityChannel, journal: OperationJournal, operation: string, spec: ControlPhaseSpec): Promise<PhaseOutcome>;
64
+ /** The DEKs this client holds for `chain`'s epochs, each checked against its commitment. */
65
+ export declare function heldDeks(secrets: SecretStore, chain: LinearChain): Promise<Map<string, ResourceDEK>>;
66
+ /** Stores the DEK of `epoch` (secret first) and links the epoch rows to it (LFCP-034). */
67
+ export declare function storeDek(storage: IdentityStorage, secrets: SecretStore, chain: LinearChain, epoch: DataEpoch, dek: ResourceDEK): Promise<void>;
68
+ /**
69
+ * KEY_PACKAGE_GET for `recipient` over every epoch of `chain` (§52: at most
70
+ * 256 per request, the channel splits), opening and storing each DEK.
71
+ */
72
+ export declare function fetchDeks(storage: IdentityStorage, secrets: SecretStore, channel: IdentityChannel, chain: LinearChain, recipient: Installation): Promise<Map<string, ResourceDEK>>;
73
+ /** Every Principal with `holds(P, 1)` at the head (W §19, §25.2): the reader set, by ID. */
74
+ export declare function readersAt(state: LinearChain["state"]): readonly PrincipalDescriptor[];
75
+ export interface KeyDelivery {
76
+ /** Packages sealed and acknowledged now, as (epoch, recipient hex). */
77
+ readonly sent: readonly {
78
+ readonly epoch: DataEpoch;
79
+ readonly recipient: string;
80
+ }[];
81
+ /** Already in the ledger (§9.2 Package: complete). */
82
+ readonly complete: number;
83
+ /** Recipients that are not readers at the head, or packages the coordinator refused. */
84
+ readonly skipped: readonly {
85
+ readonly recipient: string;
86
+ readonly reason: string;
87
+ }[];
88
+ }
89
+ /**
90
+ * Seals every DEK of `deks` to each recipient at the chain's head and
91
+ * records each acknowledged package (§9.5). A package the ledger records is
92
+ * `complete` unless `resend` lists its epoch for that recipient (a
93
+ * `missing_keys` hint, §7.1 step 3); a recipient that is no longer a
94
+ * reader, or a package that would not be authorized, is skipped (§9.2).
95
+ */
96
+ export declare function deliverKeys(options: {
97
+ readonly channel: IdentityChannel;
98
+ readonly ledger: PackageLedger;
99
+ readonly chain: LinearChain;
100
+ readonly sender: Signer;
101
+ readonly recipients: readonly PrincipalDescriptor[];
102
+ readonly deks: ReadonlyMap<string, ResourceDEK>;
103
+ readonly resend?: ReadonlyMap<string, ReadonlySet<string>>;
104
+ }): Promise<KeyDelivery>;
105
+ /**
106
+ * Fetches every Data Unit of the Identity Resource that the coordinator
107
+ * advertises and applies the readable ones to `doc` in actor-sequence
108
+ * order, each with its writer class at its control_ref (§2.3). Returns the
109
+ * highest accepted sequence per actor (hex).
110
+ */
111
+ export declare function loadIdentityDocument(options: {
112
+ readonly channel: IdentityChannel;
113
+ readonly chain: LinearChain;
114
+ readonly deks: ReadonlyMap<string, ResourceDEK>;
115
+ readonly doc: IdentityDocumentPort;
116
+ }): Promise<IdentityDocumentLoad>;
117
+ /** What loadIdentityDocument learned besides the document. */
118
+ export interface IdentityDocumentLoad {
119
+ /** Each actor's latest accepted unit (by Principal hex): the next unit's previous (W §26.2). */
120
+ readonly latest: ReadonlyMap<string, {
121
+ readonly seq: bigint;
122
+ readonly unitId: DataUnitId;
123
+ }>;
124
+ /**
125
+ * The units the wire accepted whose change the document did not take,
126
+ * after every change it could: refused by its admission (IDENTITY-PROFILE-01
127
+ * §3), or held for a change it never got (SOP §14.1). The port does not
128
+ * tell the two apart. In delivery order; empty when the document holds
129
+ * every unit.
130
+ */
131
+ readonly unapplied: readonly {
132
+ readonly actor: PrincipalId;
133
+ readonly seq: bigint;
134
+ readonly unitId: DataUnitId;
135
+ }[];
136
+ }
137
+ /** The Genesis owner of a chain: the root of an Identity Resource (§2.3). */
138
+ export declare function genesisOwner(chain: LinearChain): PrincipalId;
139
+ /**
140
+ * A new unit of `signer` in the Identity Resource carrying `intents` as
141
+ * one change: the next actor sequence from the storage's reservation
142
+ * (durable, never reused), the current epoch's DEK, the signer's latest
143
+ * accepted unit as previous. The change is applied to `doc`.
144
+ */
145
+ export declare function sealIdentityUnit(options: {
146
+ readonly storage: IdentityStorage;
147
+ readonly chain: LinearChain;
148
+ readonly deks: ReadonlyMap<string, ResourceDEK>;
149
+ readonly signer: Signer;
150
+ readonly doc: IdentityDocumentPort;
151
+ readonly latest: IdentityDocumentLoad["latest"];
152
+ readonly intents: readonly IdentityIntent[];
153
+ /** The sequence to use instead of a reservation (a pairing device shared by installations, §5.3). */
154
+ readonly seq?: bigint;
155
+ }): Promise<Uint8Array>;
156
+ /**
157
+ * W §26.2: two different units at one (resource, actor, sequence), each
158
+ * with a valid signature by its actor, are equivocation, and both are
159
+ * excluded (their dependants then wait for a dependency that never comes:
160
+ * the actor's later units for its hash chain, other changes for the
161
+ * document's). Only units of `chain`'s Resource whose signature verifies
162
+ * take part: an unsigned or forged copy proves nothing and is dropped
163
+ * without excluding the signed unit. Authorization and decryption are not
164
+ * conditions here. Deciding before anything is applied keeps the result
165
+ * independent of the delivery order.
166
+ */
167
+ export declare function withoutEquivocations<T extends {
168
+ readonly bytes: Uint8Array;
169
+ readonly parsed: Parsed<DataUnitPayload>;
170
+ }>(chain: LinearChain, units: readonly T[]): T[];
171
+ /**
172
+ * What became of a flow's unit of display data in the Identity Resource:
173
+ * none needed, written (`committed-own`), found already written by another
174
+ * writer when the unit was built (`complete`, nothing sent), refused by the
175
+ * coordinator with `code`, or not sent because the coordinator was
176
+ * unreachable. `refused` and `unreachable` leave the flow's operation open.
177
+ */
178
+ export interface DocumentWrite {
179
+ readonly state: "none" | "committed-own" | "complete" | "refused" | "unreachable";
180
+ readonly code?: string;
181
+ }
182
+ /**
183
+ * Sends one Data Unit durably (§9.1): its exact bytes are persisted before
184
+ * they are sent and re-sent as they are after a restart, so an actor
185
+ * sequence is never used twice (W §26.2). A coordinator answers a unit it
186
+ * already holds with the same ACK.
187
+ */
188
+ export declare function runUnitPhase(channel: IdentityChannel, journal: OperationJournal, operation: string, spec: {
189
+ readonly id: string;
190
+ readonly resource: ResourceId;
191
+ /**
192
+ * The unit to send, built on the current state; null when that state
193
+ * already holds the phase's effect, written by another hand: the phase is
194
+ * then `complete` and nothing is sent.
195
+ */
196
+ readonly build: () => Promise<Uint8Array | null>;
197
+ /**
198
+ * Refusals after which the phase's intent is written again as a new unit
199
+ * on the current state, e.g. STALE_DATA_EPOCH after a rotation (W §19.1);
200
+ * the refused bytes are kept in the phase as stale, never sent again.
201
+ */
202
+ readonly rebuildOn?: readonly string[];
203
+ /**
204
+ * A phase an earlier run left refused, whatever the code, is written
205
+ * again once as a new unit on the current state: how a flow that
206
+ * reported the refusal resumes the write (the refused bytes are kept as
207
+ * stale, never sent again).
208
+ */
209
+ readonly rebuildRefused?: boolean;
210
+ }): Promise<{
211
+ readonly state: "committed-own" | "complete" | "refused";
212
+ readonly code?: string;
213
+ }>;
214
+ //# sourceMappingURL=context.d.ts.map