@joe-broadhead/messaging 0.7.1 → 0.9.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 (94) hide show
  1. package/CHANGELOG.md +364 -2
  2. package/dist/bin/messaging-mcp.js +5498 -4338
  3. package/dist/bin/messaging-relay.js +8626 -5540
  4. package/dist/bin/messaging.js +4492 -3158
  5. package/dist/bin/messagingd.js +19672 -12412
  6. package/dist/lib/modules/core/agent/operations.js +19 -327
  7. package/dist/lib/modules/core/agent/present.js +20 -55
  8. package/dist/lib/modules/core/agent-tools.js +35 -139
  9. package/dist/lib/modules/core/consent.js +54 -14
  10. package/dist/lib/modules/core/contact-card.js +3 -3
  11. package/dist/lib/modules/core/conversation/event.js +29 -4
  12. package/dist/lib/modules/core/conversation/guest-invitation.js +42 -0
  13. package/dist/lib/modules/core/conversation/log.js +287 -65
  14. package/dist/lib/modules/core/conversation/request-log.js +158 -0
  15. package/dist/lib/modules/core/conversation/request-seal.js +41 -0
  16. package/dist/lib/modules/core/conversation/requests.js +87 -0
  17. package/dist/lib/modules/core/conversation/seal.js +90 -37
  18. package/dist/lib/modules/core/conversation-agent-tools.js +69 -0
  19. package/dist/lib/modules/core/federation/directory-proof.js +83 -0
  20. package/dist/lib/modules/core/federation/proof-state.js +167 -0
  21. package/dist/lib/modules/core/federation/roster-proof.js +74 -0
  22. package/dist/lib/modules/core/index.js +9 -4
  23. package/dist/lib/modules/core/jelly-host.js +8 -5
  24. package/dist/lib/modules/core/schema/common.js +33 -5
  25. package/dist/lib/modules/core/schema/consent.js +23 -5
  26. package/dist/lib/modules/core/schema/contact-request.js +22 -0
  27. package/dist/lib/modules/core/schema/conv-frames.js +101 -0
  28. package/dist/lib/modules/core/schema/conversation.js +67 -33
  29. package/dist/lib/modules/core/schema/directory-frames.js +8 -3
  30. package/dist/lib/modules/core/schema/envelope.js +8 -24
  31. package/dist/lib/modules/core/schema/errors.js +7 -5
  32. package/dist/lib/modules/core/schema/guest-invitation.js +13 -0
  33. package/dist/lib/modules/core/schema/index.js +5 -0
  34. package/dist/lib/modules/core/schema/ipc/consent.js +97 -18
  35. package/dist/lib/modules/core/schema/ipc/conversation-views.js +87 -0
  36. package/dist/lib/modules/core/schema/ipc/conversations.js +132 -0
  37. package/dist/lib/modules/core/schema/ipc/device.js +9 -0
  38. package/dist/lib/modules/core/schema/ipc/jelly.js +17 -45
  39. package/dist/lib/modules/core/schema/ipc/shapes.js +74 -73
  40. package/dist/lib/modules/core/schema/ipc/surfaces.js +12 -195
  41. package/dist/lib/modules/core/schema/ipc/tasks.js +31 -0
  42. package/dist/lib/modules/core/schema/ipc.js +68 -46
  43. package/dist/lib/modules/core/testing.js +1 -1
  44. package/dist/lib/modules/core/version.js +1 -1
  45. package/dist/lib/modules/ipc/client.js +10 -2
  46. package/dist/lib/modules/ipc/server.js +14 -5
  47. package/dist/lib/modules/ipc/testing.js +13 -23
  48. package/dist/spec/messaging-v1.md +854 -445
  49. package/dist/third-party-notices.md +1 -1
  50. package/dist/third-party.json +1 -1
  51. package/dist/types/core/agent/operations.d.ts +5 -52
  52. package/dist/types/core/agent/present.d.ts +6 -21
  53. package/dist/types/core/agent-tools.d.ts +295 -442
  54. package/dist/types/core/consent.d.ts +30 -7
  55. package/dist/types/core/contact-card.d.ts +3 -3
  56. package/dist/types/core/conversation/event.d.ts +6 -6
  57. package/dist/types/core/conversation/guest-invitation.d.ts +8 -0
  58. package/dist/types/core/conversation/log.d.ts +28 -13
  59. package/dist/types/core/conversation/request-log.d.ts +24 -0
  60. package/dist/types/core/conversation/request-seal.d.ts +6 -0
  61. package/dist/types/core/conversation/requests.d.ts +14 -0
  62. package/dist/types/core/conversation/seal.d.ts +32 -9
  63. package/dist/types/core/conversation-agent-tools.d.ts +939 -0
  64. package/dist/types/core/federation/directory-proof.d.ts +8 -0
  65. package/dist/types/core/federation/proof-state.d.ts +114 -0
  66. package/dist/types/core/federation/roster-proof.d.ts +7 -0
  67. package/dist/types/core/index.d.ts +11 -6
  68. package/dist/types/core/jelly-host.d.ts +1 -1
  69. package/dist/types/core/schema/common.d.ts +33 -6
  70. package/dist/types/core/schema/consent.d.ts +29 -8
  71. package/dist/types/core/schema/contact-request.d.ts +264 -0
  72. package/dist/types/core/schema/conv-frames.d.ts +1204 -0
  73. package/dist/types/core/schema/conversation.d.ts +1410 -264
  74. package/dist/types/core/schema/directory-frames.d.ts +8 -3
  75. package/dist/types/core/schema/envelope.d.ts +85 -130
  76. package/dist/types/core/schema/errors.d.ts +5 -1
  77. package/dist/types/core/schema/guest-invitation.d.ts +51 -0
  78. package/dist/types/core/schema/index.d.ts +5 -0
  79. package/dist/types/core/schema/ipc/consent.d.ts +464 -62
  80. package/dist/types/core/schema/ipc/conversation-views.d.ts +1199 -0
  81. package/dist/types/core/schema/ipc/conversations.d.ts +4355 -0
  82. package/dist/types/core/schema/ipc/device.d.ts +10 -0
  83. package/dist/types/core/schema/ipc/jelly.d.ts +16 -111
  84. package/dist/types/core/schema/ipc/shapes.d.ts +211 -95
  85. package/dist/types/core/schema/ipc/surfaces.d.ts +26 -427
  86. package/dist/types/core/schema/ipc/tasks.d.ts +210 -0
  87. package/dist/types/core/schema/ipc.d.ts +3859 -890
  88. package/dist/types/core/schema/relay.d.ts +12 -4
  89. package/dist/types/core/testing.d.ts +1 -1
  90. package/dist/types/core/version.d.ts +1 -1
  91. package/dist/types/ipc/client.d.ts +4 -1
  92. package/dist/types/ipc/server.d.ts +16 -1
  93. package/dist/types/ipc/testing.d.ts +21 -8
  94. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import type { Identity } from "./identity.js";
2
2
  import { type MachineId, type PersonId, type Ulid } from "./schema/common.js";
3
3
  import { type AgentMailLevel, type AskLevel, type ChatLevel, ConsentGrant, type GrantLevels, type GrantSubject } from "./schema/consent.js";
4
+ import type { ReachValue } from "./schema/ipc/consent.js";
4
5
  import type { RealmId } from "./schema/realm.js";
5
6
  export interface ConsentGrantArgs {
6
7
  realm: RealmId;
@@ -25,6 +26,22 @@ export declare function verifyConsentGrant(raw: unknown, ctx: {
25
26
  }): ConsentGrant;
26
27
  /** The key one grant is stored under: its subject. One grant per subject. */
27
28
  export declare function grantSubjectKey(subject: GrantSubject): string;
29
+ /**
30
+ * The person's two reach choices, from their relation grants. `message` ("Who can message you") is the `outside`
31
+ * grant's `chat`: `open`, `blocked` (Never), or a grant with no level (Ask me first). `ask` ("How agents may ask
32
+ * yours") is the `org` grant's `ask`: `open`, `request` (Ask me first), `no` (Never). Absent: no grant, the defaults.
33
+ */
34
+ export interface ReachChoices {
35
+ message?: ReachValue;
36
+ ask?: ReachValue;
37
+ }
38
+ /** The choices a person's two relation grants make; a grant absent (or not current) leaves its choice unset. */
39
+ export declare function reachChoices(outside: GrantLevels | undefined, org: GrantLevels | undefined): ReachChoices;
40
+ /** The relation grant subject and levels that record one choice: the inverse of `reachChoices`. */
41
+ export declare function reachGrant(group: keyof ReachChoices, value: ReachValue): {
42
+ subject: GrantSubject;
43
+ levels: GrantLevels;
44
+ };
28
45
  /**
29
46
  * Of two copies of the grant for one subject, the one that counts (spec §6.9, "Merging"): the newer by `ts`, then
30
47
  * by `id`. Copies that tie on both are one grant signed twice: a copy whose signer is current beats one whose
@@ -67,10 +84,11 @@ export interface EffectivePolicy {
67
84
  }
68
85
  /**
69
86
  * Spec §6.9, "Effective policy": each level is the person grant's when it sets one; otherwise, for `ask` and
70
- * `agentMail`, the most permissive among the grants of channels the sender is in; otherwise the relation's
71
- * default. An expired `trustedUntil` reads as absent. The caller passes only grants whose signer is current.
87
+ * `agentMail`, the most permissive among the grants of channels the sender is in; otherwise the relation's level
88
+ * under the person's reach choices (`baseLevels`). An expired `trustedUntil` reads as absent. The caller passes only
89
+ * grants whose signer is current.
72
90
  */
73
- export declare function effectivePolicy(relation: Exclude<Relation, "self">, person: GrantLevels | undefined, channels: readonly GrantLevels[], now: number): EffectivePolicy;
91
+ export declare function effectivePolicy(relation: Exclude<Relation, "self">, person: GrantLevels | undefined, channels: readonly GrantLevels[], now: number, reach?: ReachChoices): EffectivePolicy;
74
92
  /**
75
93
  * What arrived, classified by the receiver (spec §6.9, "Enforcement"):
76
94
  * - `answer`: a receipt, a task update or cancel, or a message the counterpart binding ties to this person's own
@@ -114,6 +132,8 @@ export interface DecideArgs {
114
132
  grant?: GrantLevels;
115
133
  /** Grants of channels the sender is in, in the receiver's own view, each with a current signer. */
116
134
  channels: readonly GrantLevels[];
135
+ /** The receiving person's reach choices (their current relation grants); absent, the relation defaults. */
136
+ reach?: ReachChoices;
117
137
  inbound: Inbound;
118
138
  now: number;
119
139
  }
@@ -121,12 +141,15 @@ export interface DecideArgs {
121
141
  * Spec §6.9, "Enforcement": step 10 of the receiver order (§5), before the inbound policy of §8.3.
122
142
  * - The person's own traffic is delivered as `self`.
123
143
  * - Answers to the person's own traffic are delivered whatever the grants, so a change never strands a task.
124
- * - A `blocked` chat level refuses every other class from the sender.
125
- * - A `stranger` reaches the person only through a level a grant opened; otherwise `request_required`.
144
+ * - A `blocked` chat level from the person grant refuses every other class from the sender.
145
+ * - A `blocked` chat level from the reach choice Never refuses the sender's lines, message requests and channel
146
+ * changes, `refused`; agent mail and asks follow their own levels, so a grant that opened them still counts.
147
+ * - A `stranger` reaches the person only through a level a grant or a choice opened; otherwise `request_required`.
126
148
  * - Lines follow `chat` (person) or `agentMail` (agent); `muted` delivers silently.
127
149
  * - Asks follow `ask`: `open` delivers guarded, or trusted while the person grant trusts the sender and every person
128
150
  * in the delegation chain is the sender or the receiver; `request` holds; `no` refuses, `request_required` when
129
- * it is the default of a `contact` or a `stranger`.
130
- * - A message request from a `stranger` is held for the person to accept; from anyone else it is a DM line.
151
+ * it is the default of a `contact` or a `stranger` and the person has not chosen Never for messages.
152
+ * - A message request is held for the person while `chat` is `request_required` (a `stranger` under Ask me first);
153
+ * otherwise it is a DM line.
131
154
  */
132
155
  export declare function decide(args: DecideArgs): ConsentDecision;
@@ -1,4 +1,4 @@
1
- import { type Relation } from "./consent.js";
1
+ import { type ReachChoices, type Relation } from "./consent.js";
2
2
  import type { Identity } from "./identity.js";
3
3
  import { type PersonId, type Ulid } from "./schema/common.js";
4
4
  import { type CardCan, ContactCard, type GrantLevels } from "./schema/consent.js";
@@ -29,6 +29,6 @@ export declare function verifyContactCard(raw: unknown, ctx: {
29
29
  }): ContactCard;
30
30
  /**
31
31
  * What a card says for a sender of `relation` with the person grant `grant` (spec §6.9, "Contact cards"): the
32
- * person grant over the relation's defaults. Channel grants are not on a card: the sender knows its own channels.
32
+ * person grant over the relation's level under the person's reach choices. Channel grants are not on a card: the sender knows its own channels.
33
33
  */
34
- export declare function cardCan(relation: Exclude<Relation, "self">, grant: GrantLevels | undefined, now: number): CardCan;
34
+ export declare function cardCan(relation: Exclude<Relation, "self">, grant: GrantLevels | undefined, now: number, reach?: ReachChoices): CardCan;
@@ -1,6 +1,6 @@
1
1
  import type { Identity } from "../identity.js";
2
2
  import { type Hash } from "../schema/common.js";
3
- import { type ConvEvent, type ConvEventHeader, type ConvId, type UnsignedConvEvent } from "../schema/conversation.js";
3
+ import { type ConvAnyEvent, type ConvEventHeader, type ConvId, type UnsignedConvEvent } from "../schema/conversation.js";
4
4
  /** h(0) of `cid`'s log: SHA-256(DOMAIN.convGenesis ‖ JCS(cid)), base64url. */
5
5
  export declare function convGenesisHash(cid: ConvId): Hash;
6
6
  /** SHA-256(JCS(event)), the raw digest, as the chain links it. Throws `invalid_request` for non-I-JSON. */
@@ -10,13 +10,13 @@ export declare function convEntryHash(prev: Hash, event: unknown): Hash;
10
10
  /** `convEntryHash` from the event's digest: what a member checks for an entry whose content has expired. */
11
11
  export declare function convLinkHash(prev: Hash, digest: Uint8Array): Hash;
12
12
  /** The header of an event: everything but `body` and `sig`. JCS of it is the AAD of a sealed body. */
13
- export declare function convEventHeader(event: ConvEvent | Omit<ConvEvent, "sig"> | ConvEventHeader): ConvEventHeader;
13
+ export declare function convEventHeader(event: ConvAnyEvent | Omit<ConvAnyEvent, "sig"> | ConvEventHeader): ConvEventHeader;
14
14
  /**
15
15
  * Checks that `raw` is I-JSON within `LIMITS.jsonDepth` and at most `LIMITS.convEventBytes` (`too_large`), that it
16
- * matches `ConvEvent`, and that `by.device` is a usable Ed25519 key. Returns a frozen JSON copy of the raw value, so
16
+ * matches `ConvAnyEvent` (an op, a msg or a key share), and that `by.device` is a usable Ed25519 key. Returns a frozen JSON copy of the raw value, so
17
17
  * the signature and the hash cover exactly what was received. The signature is not checked.
18
18
  */
19
- export declare function admitConvEvent(raw: unknown): ConvEvent;
19
+ export declare function admitConvEvent(raw: unknown): ConvAnyEvent;
20
20
  /**
21
21
  * Signs an event (spec §16.4): `sig = Ed25519(by.device, DOMAIN.convEvent ‖ JCS(event without sig))`. `by.device`
22
22
  * must be `identity`'s machine. Refuses an event that fails the schema (`invalid_request`) or is over
@@ -26,11 +26,11 @@ export declare function signConvEvent<E extends UnsignedConvEvent>(identity: Ide
26
26
  sig: string;
27
27
  };
28
28
  /** True only for a valid signature by `event.by.device` over the event without `sig`. Never throws. */
29
- export declare function convEventSigned(event: ConvEvent): boolean;
29
+ export declare function convEventSigned(event: ConvAnyEvent): boolean;
30
30
  /**
31
31
  * Admits `raw` (`admitConvEvent`) and checks its signature over the raw value (`bad_signature`). Membership and
32
32
  * authority are `ConvLog.apply`'s. Throws only MessagingError.
33
33
  */
34
- export declare function verifyConvEvent(raw: unknown): ConvEvent;
34
+ export declare function verifyConvEvent(raw: unknown): ConvAnyEvent;
35
35
  /** Freezes a JSON value and everything in it, iteratively. */
36
36
  export declare function deepFreeze<T>(value: T): T;
@@ -0,0 +1,8 @@
1
+ import type { Identity } from "../identity.js";
2
+ import { GuestInvitation } from "../schema/guest-invitation.js";
3
+ import type { ConvLog } from "./log.js";
4
+ /** The inviting device seals this preview to the invitee. No history or sender keys accompany it. */
5
+ export declare function createGuestInvitation(log: ConvLog, to: string, identity: Identity, issuedAt: number, expiresAt: number): GuestInvitation;
6
+ /** The accept event signs this same preview. Changed audience/policy/head requires a fresh preview. */
7
+ export declare function verifyGuestInvitation(log: ConvLog, raw: unknown, to: string, at: number): GuestInvitation;
8
+ export declare function guestHistoryExposure(history: "none" | "shared"): string;
@@ -1,7 +1,8 @@
1
1
  import type { AnchorRelation } from "../realm.js";
2
2
  import { type Hash, type MachineId, type PersonId } from "../schema/common.js";
3
- import { type AgentContext, type BridgePolicy, type ConvEvent, type ConvHead, type ConvId, type ConvKind, type ConvLogEntry, type ConvRole, type HistoryPolicy, type MsgKind, type ParticipantId, type Permit, type RekeyCause, type RespondTo, type Visibility } from "../schema/conversation.js";
3
+ import { type AgentContext, type BridgePolicy, type ConvEvent, type ConvExpiredEntry, type ConvHead, type ConvId, type ConvKeysEvent, type ConvKind, type ConvLogEntry, type ConvRole, type HistoryPolicy, type MsgKind, type ParticipantId, type Permit, type RekeyCause, type RespondTo, type Visibility } from "../schema/conversation.js";
4
4
  import type { RealmId } from "../schema/realm.js";
5
+ import type { RequestBinding } from "./requests.js";
5
6
  /** A participant at one position. */
6
7
  export interface ConvParticipant {
7
8
  p: ParticipantId;
@@ -80,6 +81,10 @@ export interface ConvLiveChecks {
80
81
  skewMs?: number;
81
82
  /** True when `device` is a current device of `person` in the realm (`unknown_device` otherwise). */
82
83
  isDevice?: (person: PersonId, device: MachineId) => boolean;
84
+ /** True only when the verified realm has removed this device. */
85
+ isRemovedDevice?: (device: MachineId) => boolean;
86
+ /** Retained identity history for portable request proofs, including historical devices. */
87
+ requestBinding?: RequestBinding;
83
88
  /** The org of `person`, for `join`, and for an add of a person who is not a guest (`forbidden`). */
84
89
  orgOf?: (person: PersonId) => string | undefined;
85
90
  }
@@ -88,11 +93,11 @@ export interface ConvApplyOptions {
88
93
  body?: unknown;
89
94
  live?: ConvLiveChecks;
90
95
  }
91
- /** An entry whose content the relay expired: its seq, its prev and the digest SHA-256(JCS(event)). */
92
- export interface ConvExpiredEntry {
93
- seq: number;
94
- prev: Hash;
95
- digest: Hash;
96
+ /** Local admission metadata, never part of an entry's signed wire representation. */
97
+ interface ReplayEntry {
98
+ entry: unknown;
99
+ body?: unknown;
100
+ held?: boolean;
96
101
  }
97
102
  /**
98
103
  * A verified conversation log. Every method throws only MessagingError. Entries are kept as frozen copies of the
@@ -105,17 +110,16 @@ export declare class ConvLog {
105
110
  private constructor();
106
111
  /** An empty log of `cid` in `realm`: its head is {0, h(0)}. */
107
112
  static open(cid: ConvId, realm: RealmId): ConvLog;
108
- /** Replays `entries` (each with the opened body of a `msg`, when the caller has it). Throws the first failure. */
109
- static fromEntries(cid: ConvId, realm: RealmId, entries: {
110
- entry: unknown;
111
- body?: unknown;
112
- }[]): ConvLog;
113
+ /** Replays a prefix; callers with a verified realm supply its removed-device check for every device rekey. */
114
+ static fromEntries(cid: ConvId, realm: RealmId, entries: ReplayEntry[], checks?: Pick<ConvLiveChecks, "isRemovedDevice" | "requestBinding">, onInvalidBody?: (seq: number) => void): ConvLog;
113
115
  head(): ConvHead;
114
116
  /** The last op's seq and hash, or {0, h(0)}: what an author puts in `opHead`. */
115
117
  opHead(): ConvHead;
116
118
  /** h(seq), for 0 ≤ seq ≤ head. */
117
119
  hashAt(seq: number): Hash | undefined;
118
120
  entries(): (ConvLogEntry | ConvExpiredEntry)[];
121
+ /** Held links are in the hash chain, but contribute neither state nor messages. */
122
+ held(): number[];
119
123
  /** The state at the head; undefined before `create`. */
120
124
  state(): ConvSnapshot | undefined;
121
125
  /** The state after the entry at `seq`, as a log holding only entries 1..seq has it. */
@@ -135,8 +139,19 @@ export declare class ConvLog {
135
139
  */
136
140
  apply(raw: unknown, options?: ConvApplyOptions): Hash;
137
141
  /**
138
- * Appends an entry whose content the relay expired (spec §16.4, "Retention"), by its digest: the chain stays
139
- * verifiable and the state does not change. An op is never expired: a later op head that names this seq fails.
142
+ * Appends a `msg` entry whose content the relay expired (spec §16.4, "Retention"), by its digest: the chain stays
143
+ * verifiable and the state does not change. The create (seq 1) never expires (`invalid_request`), nor does any op:
144
+ * a later op head that names this seq fails.
140
145
  */
141
146
  applyExpired(raw: ConvExpiredEntry): Hash;
147
+ /**
148
+ * Checks a key share against this log (spec §16.6); a share is not an entry, so nothing changes. In order: I-JSON,
149
+ * size and schema, realm and cid (`invalid_request`, `too_large`); the signature (`bad_signature`); the live checks
150
+ * given (`expired`, `unknown_device`); `by.agent` absent (`forbidden`); `opHead` names an op of this log
151
+ * (`conv_conflict`); then, in the state at `opHead`, the author's person is a member participant person
152
+ * (`not_member`) and the recipient's person a participant person (`forbidden`), and live, the recipient device is a
153
+ * current device of that person (`unknown_device`). Returns the frozen event.
154
+ */
155
+ checkShare(raw: unknown, live?: ConvLiveChecks): ConvKeysEvent;
142
156
  }
157
+ export {};
@@ -0,0 +1,24 @@
1
+ import { type RequestActivation } from "../schema/contact-request.js";
2
+ import { type ConvLogEntry } from "../schema/conversation.js";
3
+ import { type ConvApplyOptions, type ConvLog } from "./log.js";
4
+ import { type RequestBinding } from "./requests.js";
5
+ export interface RequestReservation {
6
+ proof: RequestActivation;
7
+ completed?: {
8
+ seq: number;
9
+ digest: string;
10
+ };
11
+ }
12
+ export interface RequestLogState {
13
+ required: boolean;
14
+ active: boolean;
15
+ reservations: Map<string, RequestReservation>;
16
+ }
17
+ /** Rebuilds permanent activation state even when imported messages have expired. */
18
+ export declare function requestLogState(log: ConvLog, binding: RequestBinding): RequestLogState;
19
+ /** Checks before appending. The relay also checks live org admission on create. No mutation on failure. */
20
+ export declare function checkRequestEvent(log: ConvLog, raw: unknown, binding: RequestBinding, body?: unknown): void;
21
+ /** Member admission seam for the cut-over engine; preserves wrapper authorship and verifies source separately. */
22
+ export declare function applyRequestEntry(log: ConvLog, entry: ConvLogEntry, binding: RequestBinding, options?: ConvApplyOptions): string;
23
+ /** Public author for a verified import, never the importing device. The renderer uses this only after admission. */
24
+ export declare function importedRequestAuthor(log: ConvLog, id: string, binding: RequestBinding): string | undefined;
@@ -0,0 +1,6 @@
1
+ import type { Identity } from "../identity.js";
2
+ import { RequestImport } from "../schema/contact-request.js";
3
+ import { type ConvMsgEvent } from "../schema/conversation.js";
4
+ import type { UnsealedMsg } from "./seal.js";
5
+ export declare function sealRequestImport(identity: Identity, header: UnsealedMsg, body: RequestImport, mk: Uint8Array): ConvMsgEvent;
6
+ export declare function openRequestImport(raw: unknown, mk: Uint8Array): RequestImport;
@@ -0,0 +1,14 @@
1
+ import type { Identity } from "../identity.js";
2
+ import { ContactAuthorization, PortableRequest, RequestActivation, RequestDecision, RequestDescriptor, RequestOpening } from "../schema/contact-request.js";
3
+ /** Retained, verified identity history must bind every proof's device to its person; absence fails closed. */
4
+ export type RequestBinding = (person: string, device: string) => boolean;
5
+ export declare const requestCommitment: (opening: RequestOpening) => string;
6
+ export declare const requestDigest: (descriptor: RequestDescriptor) => string;
7
+ export declare function verifyRequestDescriptor(raw: unknown, binding: RequestBinding): RequestDescriptor;
8
+ export declare function verifyPortableRequest(raw: unknown, binding: RequestBinding): PortableRequest;
9
+ export declare function createPortableRequest(identity: Identity, args: Omit<RequestDescriptor, "by" | "sig" | "commitment">, text: string): PortableRequest;
10
+ export declare function verifyRequestDecision(raw: unknown, descriptor: RequestDescriptor, binding: RequestBinding): RequestDecision;
11
+ export declare function signRequestDecision(identity: Identity, d: RequestDescriptor, answer: RequestDecision["answer"], at: number): RequestDecision;
12
+ export declare function verifyRequestActivation(raw: unknown, binding: RequestBinding): RequestActivation;
13
+ export declare function signContactAuthorization(identity: Identity, args: Omit<ContactAuthorization, "sig" | "by">): ContactAuthorization;
14
+ export declare function verifyContactAuthorization(raw: unknown, binding: RequestBinding): ContactAuthorization;
@@ -1,6 +1,6 @@
1
1
  import type { Identity } from "../identity.js";
2
2
  import { type EncKey, type MachineId, type PersonId } from "../schema/common.js";
3
- import { type ConvKeysEvent, ConvMeta, type ConvMsgEvent, type ConvOpEvent, type KeyShare, MsgBody } from "../schema/conversation.js";
3
+ import { type ConvKeysEvent, ConvMeta, type ConvMsgEvent, type ConvOp, type ConvOpEvent, type KeyShare, MsgBody, SettingBody } from "../schema/conversation.js";
4
4
  /** A message event before its body: the header its author signs, with `class: "msg"`. */
5
5
  export type UnsealedMsg = Omit<ConvMsgEvent, "body" | "sig">;
6
6
  /** A keys event before its body. */
@@ -33,15 +33,38 @@ export declare function sealConvMetaWith(header: Omit<ConvOpEvent, "body" | "sig
33
33
  /** Opens a `create` event's `sealedMeta`. Errors as for `openConvMsg`; `not_found` when it has none. */
34
34
  export declare function openConvMeta(event: ConvOpEvent, mk0: Uint8Array): ConvMeta;
35
35
  /**
36
- * Seals `shares` to each recipient device as the body of `unsealed`, and signs the event. One sealed share per
37
- * device; at most `LIMITS.keySharesPerEvent` devices and `LIMITS.keyShares` chain keys. Throws only MessagingError.
36
+ * Seals `shares` to one recipient device as the body of `unsealed`, and signs the event: one `keys` event per
37
+ * recipient device (spec §16.6), at most `LIMITS.keyShares` chain keys. Throws only MessagingError.
38
38
  */
39
- export declare function sealKeyShares(identity: Identity, unsealed: UnsealedKeys, recipients: ShareRecipient[], shares: KeyShare[]): ConvKeysEvent;
40
- /** `sealKeyShares` with fixed randomness per recipient, in order: for test vectors only. */
41
- export declare function sealKeySharesWith(identity: Identity, unsealed: UnsealedKeys, recipients: ShareRecipient[], shares: KeyShare[], randomness: ShareRandomness[]): ConvKeysEvent;
39
+ export declare function sealKeyShare(identity: Identity, unsealed: UnsealedKeys, recipient: ShareRecipient, shares: KeyShare[]): ConvKeysEvent;
40
+ /** `sealKeyShare` with fixed randomness: for test vectors only. */
41
+ export declare function sealKeyShareWith(identity: Identity, unsealed: UnsealedKeys, recipient: ShareRecipient, shares: KeyShare[], randomness: ShareRandomness): ConvKeysEvent;
42
42
  /**
43
- * Opens the share sealed to `identity`'s device in a `keys` event: `not_found` when there is none, `bad_signature`
44
- * when it fails to open, `invalid_request` when the plaintext is not a share payload. The caller has verified the
45
- * event's signature and applied it to the log.
43
+ * Opens a `keys` event sealed to `identity`'s device: `not_found` when it is another device's, `bad_signature` when it
44
+ * fails to open, `invalid_request` when the plaintext is not a share payload. The caller has checked the event
45
+ * (`ConvLog.checkShare`).
46
46
  */
47
47
  export declare function openKeyShares(event: ConvKeysEvent, identity: Identity): KeyShare[];
48
+ /** A sealed op as its author builds it: the op without `sealed`. */
49
+ export type UnsealedStateOp = Omit<Extract<ConvOp, {
50
+ op: "meta";
51
+ }>, "sealed"> | Omit<Extract<ConvOp, {
52
+ op: "setting";
53
+ }>, "sealed">;
54
+ /** An op event before its body is sealed: the header and the op without `sealed`. */
55
+ export type UnsealedOpEvent = Omit<ConvOpEvent, "body" | "sig"> & {
56
+ body: UnsealedStateOp;
57
+ };
58
+ /**
59
+ * Seals `content` (a `ConvMeta` for `meta`, a `SettingBody` of the op's kind for `setting`) under `mk`, the author's
60
+ * message key at the op's (`epoch`, `idx`), and signs the op event. Throws only MessagingError.
61
+ */
62
+ export declare function sealConvState(identity: Identity, unsealed: UnsealedOpEvent, content: unknown, mk: Uint8Array): ConvOpEvent;
63
+ /** `sealConvState` with a caller-chosen nonce: for test vectors only. */
64
+ export declare function sealConvStateWith(identity: Identity, unsealed: UnsealedOpEvent, content: unknown, mk: Uint8Array, nonce: Uint8Array): ConvOpEvent;
65
+ /**
66
+ * Opens a `meta` or `setting` op with the author's message key at its (`epoch`, `idx`): a `ConvMeta`, or a
67
+ * `SettingBody` whose `s` is the op's `kind` (`invalid_request` otherwise). `not_found` for another op; errors as
68
+ * for `openConvMsg`. The caller has applied the event to the log.
69
+ */
70
+ export declare function openConvState(event: ConvOpEvent, mk: Uint8Array): ConvMeta | SettingBody;