@agora-sdk/secure-chat-core 0.7.0 → 0.8.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 (53) hide show
  1. package/dist/cjs/content/builders.d.ts +40 -0
  2. package/dist/cjs/content/builders.js +85 -0
  3. package/dist/cjs/content/builders.js.map +1 -0
  4. package/dist/cjs/content/cbor.d.ts +48 -0
  5. package/dist/cjs/content/cbor.js +298 -0
  6. package/dist/cjs/content/cbor.js.map +1 -0
  7. package/dist/cjs/content/frame.d.ts +24 -0
  8. package/dist/cjs/content/frame.js +39 -0
  9. package/dist/cjs/content/frame.js.map +1 -0
  10. package/dist/cjs/content/mimi-content.d.ts +194 -0
  11. package/dist/cjs/content/mimi-content.js +289 -0
  12. package/dist/cjs/content/mimi-content.js.map +1 -0
  13. package/dist/cjs/hooks/message-fold.d.ts +91 -0
  14. package/dist/cjs/hooks/message-fold.js +218 -0
  15. package/dist/cjs/hooks/message-fold.js.map +1 -0
  16. package/dist/cjs/hooks/useSecureMessages.d.ts +30 -18
  17. package/dist/cjs/hooks/useSecureMessages.js +190 -238
  18. package/dist/cjs/hooks/useSecureMessages.js.map +1 -1
  19. package/dist/cjs/index.d.ts +7 -0
  20. package/dist/cjs/index.js +27 -1
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/persistence/repository.d.ts +11 -11
  23. package/dist/cjs/persistence/repository.js +19 -19
  24. package/dist/cjs/persistence/repository.js.map +1 -1
  25. package/dist/cjs/version.d.ts +1 -1
  26. package/dist/cjs/version.js +1 -1
  27. package/dist/esm/content/builders.d.ts +40 -0
  28. package/dist/esm/content/builders.js +77 -0
  29. package/dist/esm/content/builders.js.map +1 -0
  30. package/dist/esm/content/cbor.d.ts +48 -0
  31. package/dist/esm/content/cbor.js +292 -0
  32. package/dist/esm/content/cbor.js.map +1 -0
  33. package/dist/esm/content/frame.d.ts +24 -0
  34. package/dist/esm/content/frame.js +34 -0
  35. package/dist/esm/content/frame.js.map +1 -0
  36. package/dist/esm/content/mimi-content.d.ts +194 -0
  37. package/dist/esm/content/mimi-content.js +283 -0
  38. package/dist/esm/content/mimi-content.js.map +1 -0
  39. package/dist/esm/hooks/message-fold.d.ts +91 -0
  40. package/dist/esm/hooks/message-fold.js +214 -0
  41. package/dist/esm/hooks/message-fold.js.map +1 -0
  42. package/dist/esm/hooks/useSecureMessages.d.ts +30 -18
  43. package/dist/esm/hooks/useSecureMessages.js +192 -240
  44. package/dist/esm/hooks/useSecureMessages.js.map +1 -1
  45. package/dist/esm/index.d.ts +7 -0
  46. package/dist/esm/index.js +6 -0
  47. package/dist/esm/index.js.map +1 -1
  48. package/dist/esm/persistence/repository.d.ts +11 -11
  49. package/dist/esm/persistence/repository.js +19 -19
  50. package/dist/esm/persistence/repository.js.map +1 -1
  51. package/dist/esm/version.d.ts +1 -1
  52. package/dist/esm/version.js +1 -1
  53. package/package.json +3 -2
@@ -0,0 +1,292 @@
1
+ // Deterministic CBOR (RFC 8949) over a constrained subset — the wire form for MimiContent.
2
+ //
3
+ // Where it sits: this is pure byte-shuffling ABOVE the SecureChatCrypto seam and INSIDE the padding
4
+ // frame. It encodes message content to canonical CBOR so the SHA-256 contentHash is stable across
5
+ // runtimes (web/native), and decodes UNTRUSTED peer bytes strictly and within bounds (CLAUDE.md §1:
6
+ // validate-then-decode, fail closed). The subset is exactly what MimiContent needs — unsigned/negative
7
+ // integers, byte/text strings, arrays, maps, tags, and the simple values false/true/null — and
8
+ // deliberately EXCLUDES CBOR's hard, ambiguous parts: floats, indefinite-length items, and bignums.
9
+ //
10
+ // "Canonical" = RFC 8949 §4.2 core deterministic rules for this subset: shortest-form integers and
11
+ // lengths, definite lengths, map keys sorted by their encoded bytes, no duplicate keys.
12
+ /** A CBOR tagged value (major type 6): a `tag` number wrapping one nested value. */
13
+ export class CborTag {
14
+ constructor(
15
+ /** The CBOR tag number (major type 6 argument). */
16
+ tag,
17
+ /** The single nested value wrapped by this tag. */
18
+ value) {
19
+ this.tag = tag;
20
+ this.value = value;
21
+ }
22
+ }
23
+ const enc = new TextEncoder();
24
+ const dec = new TextDecoder("utf-8", { fatal: true });
25
+ function concat(parts) {
26
+ let n = 0;
27
+ for (const p of parts)
28
+ n += p.length;
29
+ const out = new Uint8Array(n);
30
+ let o = 0;
31
+ for (const p of parts) {
32
+ out.set(p, o);
33
+ o += p.length;
34
+ }
35
+ return out;
36
+ }
37
+ /** Compare two byte arrays lexicographically (the canonical map-key order). */
38
+ function cmpBytes(a, b) {
39
+ const n = Math.min(a.length, b.length);
40
+ for (let i = 0; i < n; i++)
41
+ if (a[i] !== b[i])
42
+ return a[i] - b[i];
43
+ return a.length - b.length;
44
+ }
45
+ /** Emit a CBOR head: the major type (0..7) and its argument, in shortest form. */
46
+ function head(major, arg) {
47
+ const m = major << 5;
48
+ const n = typeof arg === "bigint" ? arg : BigInt(arg);
49
+ if (n < 0n)
50
+ throw new Error("cbor: negative head argument");
51
+ if (n < 24n)
52
+ return Uint8Array.of(m | Number(n));
53
+ if (n < 0x100n)
54
+ return Uint8Array.of(m | 24, Number(n));
55
+ if (n < 0x10000n)
56
+ return Uint8Array.of(m | 25, Number(n >> 8n) & 0xff, Number(n & 0xffn));
57
+ if (n < 0x100000000n)
58
+ return Uint8Array.of(m | 26, Number((n >> 24n) & 0xffn), Number((n >> 16n) & 0xffn), Number((n >> 8n) & 0xffn), Number(n & 0xffn));
59
+ if (n < 0x10000000000000000n) {
60
+ const out = new Uint8Array(9);
61
+ out[0] = m | 27;
62
+ let v = n;
63
+ for (let i = 8; i >= 1; i--) {
64
+ out[i] = Number(v & 0xffn);
65
+ v >>= 8n;
66
+ }
67
+ return out;
68
+ }
69
+ throw new Error("cbor: integer exceeds u64 (no bignum support)");
70
+ }
71
+ function encodeInto(v, parts) {
72
+ if (v === null)
73
+ return void parts.push(Uint8Array.of(0xf6));
74
+ if (v === false)
75
+ return void parts.push(Uint8Array.of(0xf4));
76
+ if (v === true)
77
+ return void parts.push(Uint8Array.of(0xf5));
78
+ const t = typeof v;
79
+ if (t === "number" || t === "bigint") {
80
+ if (t === "number" && !Number.isInteger(v))
81
+ throw new Error("cbor: non-integer number (no float support)");
82
+ const n = typeof v === "bigint" ? v : BigInt(v);
83
+ if (n >= 0n)
84
+ parts.push(head(0, n));
85
+ else
86
+ parts.push(head(1, -1n - n));
87
+ return;
88
+ }
89
+ if (v instanceof Uint8Array) {
90
+ parts.push(head(2, v.length));
91
+ parts.push(v);
92
+ return;
93
+ }
94
+ if (t === "string") {
95
+ const b = enc.encode(v);
96
+ parts.push(head(3, b.length));
97
+ parts.push(b);
98
+ return;
99
+ }
100
+ if (Array.isArray(v)) {
101
+ parts.push(head(4, v.length));
102
+ for (const e of v)
103
+ encodeInto(e, parts);
104
+ return;
105
+ }
106
+ if (v instanceof CborTag) {
107
+ parts.push(head(6, v.tag));
108
+ encodeInto(v.value, parts);
109
+ return;
110
+ }
111
+ if (v instanceof Map) {
112
+ const entries = [...v.entries()].map(([k, val]) => [encode(k), val]);
113
+ entries.sort((a, b) => cmpBytes(a[0], b[0]));
114
+ for (let i = 1; i < entries.length; i++)
115
+ if (cmpBytes(entries[i - 1][0], entries[i][0]) === 0)
116
+ throw new Error("cbor: duplicate map key");
117
+ parts.push(head(5, entries.length));
118
+ for (const [kb, val] of entries) {
119
+ parts.push(kb);
120
+ encodeInto(val, parts);
121
+ }
122
+ return;
123
+ }
124
+ throw new Error("cbor: unsupported value");
125
+ }
126
+ /**
127
+ * Encode a {@link CborValue} to canonical CBOR bytes (RFC 8949 §4.2 core deterministic rules).
128
+ *
129
+ * @param value - A value in the supported subset.
130
+ * @returns The canonical CBOR byte encoding.
131
+ * @throws {Error} On a non-integer number, an integer above u64, or an unsupported value type.
132
+ * @example
133
+ * ```ts
134
+ * encode(new Map([[1, "a"]])); // → a2 01 61 61 … (keys sorted by encoded bytes)
135
+ * ```
136
+ */
137
+ export function encode(value) {
138
+ const parts = [];
139
+ encodeInto(value, parts);
140
+ return concat(parts);
141
+ }
142
+ class Reader {
143
+ constructor(buf, limits) {
144
+ this.buf = buf;
145
+ this.limits = limits;
146
+ this.pos = 0;
147
+ }
148
+ byte() {
149
+ if (this.pos >= this.buf.length)
150
+ throw new Error("cbor: unexpected end of input");
151
+ return this.buf[this.pos++];
152
+ }
153
+ /** Read the argument for additional-info `ai`, enforcing shortest-form (canonical). */
154
+ arg(ai) {
155
+ if (ai < 24)
156
+ return BigInt(ai);
157
+ if (ai === 24) {
158
+ const n = BigInt(this.byte());
159
+ if (n < 24n)
160
+ throw new Error("cbor: non-canonical (shortest-form) integer");
161
+ return n;
162
+ }
163
+ if (ai === 25) {
164
+ const n = (BigInt(this.byte()) << 8n) | BigInt(this.byte());
165
+ if (n < 0x100n)
166
+ throw new Error("cbor: non-canonical (shortest-form) integer");
167
+ return n;
168
+ }
169
+ if (ai === 26) {
170
+ let n = 0n;
171
+ for (let i = 0; i < 4; i++)
172
+ n = (n << 8n) | BigInt(this.byte());
173
+ if (n < 0x10000n)
174
+ throw new Error("cbor: non-canonical (shortest-form) integer");
175
+ return n;
176
+ }
177
+ if (ai === 27) {
178
+ let n = 0n;
179
+ for (let i = 0; i < 8; i++)
180
+ n = (n << 8n) | BigInt(this.byte());
181
+ if (n < 0x100000000n)
182
+ throw new Error("cbor: non-canonical (shortest-form) integer");
183
+ return n;
184
+ }
185
+ throw new Error("cbor: reserved/indefinite additional info (outside subset)");
186
+ }
187
+ take(n) {
188
+ if (n > BigInt(this.limits.maxBytes))
189
+ throw new Error("cbor: length exceeds bounds");
190
+ const len = Number(n);
191
+ if (this.pos + len > this.buf.length)
192
+ throw new Error("cbor: unexpected end of input");
193
+ const slice = this.buf.subarray(this.pos, this.pos + len);
194
+ this.pos += len;
195
+ return slice;
196
+ }
197
+ /** Integers small enough stay `number`; larger become `bigint`. */
198
+ intVal(n, negative) {
199
+ const v = negative ? -1n - n : n;
200
+ return v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER)
201
+ ? Number(v)
202
+ : v;
203
+ }
204
+ value(depth) {
205
+ if (depth > this.limits.maxDepth)
206
+ throw new Error("cbor: nesting depth exceeds bounds");
207
+ const ib = this.byte();
208
+ const major = ib >> 5;
209
+ const ai = ib & 0x1f;
210
+ switch (major) {
211
+ case 0:
212
+ return this.intVal(this.arg(ai), false);
213
+ case 1:
214
+ return this.intVal(this.arg(ai), true);
215
+ case 2:
216
+ return this.take(this.arg(ai)).slice(); // copy out of the backing buffer
217
+ case 3:
218
+ return dec.decode(this.take(this.arg(ai)));
219
+ case 4: {
220
+ const len = this.arg(ai);
221
+ if (len > BigInt(this.limits.maxItems))
222
+ throw new Error("cbor: array length exceeds bounds");
223
+ const out = [];
224
+ for (let i = 0n; i < len; i++)
225
+ out.push(this.value(depth + 1));
226
+ return out;
227
+ }
228
+ case 5: {
229
+ const len = this.arg(ai);
230
+ if (len > BigInt(this.limits.maxItems))
231
+ throw new Error("cbor: map length exceeds bounds");
232
+ const out = new Map();
233
+ let prevKey = null;
234
+ for (let i = 0n; i < len; i++) {
235
+ const k = this.value(depth + 1);
236
+ const kb = encode(k); // canonical key bytes — enforce strictly-increasing order
237
+ if (prevKey) {
238
+ const c = cmpBytes(prevKey, kb);
239
+ if (c === 0)
240
+ throw new Error("cbor: duplicate map key");
241
+ if (c > 0)
242
+ throw new Error("cbor: map keys not sorted (non-canonical)");
243
+ }
244
+ prevKey = kb;
245
+ out.set(k, this.value(depth + 1));
246
+ }
247
+ return out;
248
+ }
249
+ case 6: {
250
+ // Normalize the tag the same way as integers (safe-int → number, larger → bigint) so a tag
251
+ // round-trips to the same JS type a caller would naturally pass to `new CborTag(...)`.
252
+ const tag = this.intVal(this.arg(ai), false);
253
+ return new CborTag(tag, this.value(depth + 1));
254
+ }
255
+ case 7:
256
+ if (ai === 20)
257
+ return false;
258
+ if (ai === 21)
259
+ return true;
260
+ if (ai === 22)
261
+ return null;
262
+ throw new Error("cbor: float/simple value outside subset");
263
+ default:
264
+ throw new Error("cbor: unknown major type");
265
+ }
266
+ }
267
+ }
268
+ /**
269
+ * Strict-decode canonical CBOR bytes from the supported subset. Rejects non-canonical encodings,
270
+ * out-of-subset major/simple values, trailing bytes, and anything exceeding {@link CborLimits}.
271
+ *
272
+ * @param bytes - The CBOR input (untrusted peer data — decoded fail-closed).
273
+ * @param limits - Optional {@link CborLimits} bounds.
274
+ * @returns The decoded {@link CborValue}.
275
+ * @throws {Error} On any non-canonical encoding, out-of-subset value, truncation, trailing bytes, or
276
+ * a bound (size/depth/item-count) being exceeded.
277
+ */
278
+ export function decode(bytes, limits = {}) {
279
+ const resolved = {
280
+ maxBytes: limits.maxBytes ?? 1 << 20,
281
+ maxDepth: limits.maxDepth ?? 32,
282
+ maxItems: limits.maxItems ?? 4096,
283
+ };
284
+ if (bytes.length > resolved.maxBytes)
285
+ throw new Error("cbor: input too large (bounds)");
286
+ const r = new Reader(bytes, resolved);
287
+ const v = r.value(0);
288
+ if (r.pos !== bytes.length)
289
+ throw new Error("cbor: trailing bytes after top-level value");
290
+ return v;
291
+ }
292
+ //# sourceMappingURL=cbor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cbor.js","sourceRoot":"","sources":["../../../src/content/cbor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** Content-frame discriminator. `Mimi` = MimiContent CBOR; `IucControl` is reserved for the IUC state machine. */
2
+ export declare const ContentKind: {
3
+ readonly Mimi: 0;
4
+ readonly IucControl: 1;
5
+ };
6
+ export type ContentKind = (typeof ContentKind)[keyof typeof ContentKind];
7
+ /**
8
+ * Prefix `payload` with its routing `kind` byte.
9
+ * @param kind - The discriminator (0..255); use {@link ContentKind}.
10
+ * @param payload - The bytes to route (e.g. MimiContent CBOR).
11
+ * @returns `[kind][payload]`.
12
+ * @throws {Error} If `kind` is not an integer in 0..255.
13
+ */
14
+ export declare function frameContent(kind: number, payload: Uint8Array): Uint8Array;
15
+ /**
16
+ * Split a content frame into its routing `kind` and the remaining `payload`.
17
+ * @param bytes - A `[kind][payload]` frame (after unpadding).
18
+ * @returns `{ kind, payload }`.
19
+ * @throws {Error} If `bytes` is empty (no kind byte).
20
+ */
21
+ export declare function unframe(bytes: Uint8Array): {
22
+ kind: number;
23
+ payload: Uint8Array;
24
+ };
@@ -0,0 +1,34 @@
1
+ // Content routing frame — a single discriminator byte INSIDE the padding frame, ABOVE MimiContent.
2
+ //
3
+ // padPlaintext( frameContent(kind, payload) ) → encrypt. One byte routes user content vs control
4
+ // traffic without wrapping the MimiContent CBOR in another struct (keeps the MIMI bytes pure). The
5
+ // padding frame (util/padding) is the transport concern and is unchanged.
6
+ /** Content-frame discriminator. `Mimi` = MimiContent CBOR; `IucControl` is reserved for the IUC state machine. */
7
+ export const ContentKind = { Mimi: 0, IucControl: 1 };
8
+ /**
9
+ * Prefix `payload` with its routing `kind` byte.
10
+ * @param kind - The discriminator (0..255); use {@link ContentKind}.
11
+ * @param payload - The bytes to route (e.g. MimiContent CBOR).
12
+ * @returns `[kind][payload]`.
13
+ * @throws {Error} If `kind` is not an integer in 0..255.
14
+ */
15
+ export function frameContent(kind, payload) {
16
+ if (!Number.isInteger(kind) || kind < 0 || kind > 255)
17
+ throw new Error("content frame: kind must be a byte (0..255)");
18
+ const out = new Uint8Array(payload.length + 1);
19
+ out[0] = kind;
20
+ out.set(payload, 1);
21
+ return out;
22
+ }
23
+ /**
24
+ * Split a content frame into its routing `kind` and the remaining `payload`.
25
+ * @param bytes - A `[kind][payload]` frame (after unpadding).
26
+ * @returns `{ kind, payload }`.
27
+ * @throws {Error} If `bytes` is empty (no kind byte).
28
+ */
29
+ export function unframe(bytes) {
30
+ if (bytes.length < 1)
31
+ throw new Error("content frame: empty (too short)");
32
+ return { kind: bytes[0], payload: bytes.subarray(1) };
33
+ }
34
+ //# sourceMappingURL=frame.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frame.js","sourceRoot":"","sources":["../../../src/content/frame.ts"],"names":[],"mappings":"AAAA,mGAAmG;AACnG,EAAE;AACF,iGAAiG;AACjG,mGAAmG;AACnG,0EAA0E;AAE1E,kHAAkH;AAClH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAW,CAAC;AAG/D;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,OAAmB;IAC5D,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACtH,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC/C,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IACd,GAAG,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACpB,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,KAAiB;IACvC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC1E,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;AACxD,CAAC"}
@@ -0,0 +1,194 @@
1
+ import { type CborMap } from "./cbor.js";
2
+ /**
3
+ * Part cardinality tag. Values per draft-ietf-mimi-content-08
4
+ * (`nullpart=0, single=1, external=2, multi=3`).
5
+ */
6
+ export declare const Cardinality: {
7
+ readonly Null: 0;
8
+ readonly Single: 1;
9
+ readonly External: 2;
10
+ readonly Multi: 3;
11
+ };
12
+ /** The set of valid {@link Cardinality} tag values. */
13
+ export type Cardinality = (typeof Cardinality)[keyof typeof Cardinality];
14
+ /**
15
+ * Part disposition (draft-ietf-mimi-content-08 `baseDispos`). `Reaction` distinguishes a reaction
16
+ * from a reply; `Attachment`/`Inline`/etc. drive client rendering.
17
+ */
18
+ export declare const Disposition: {
19
+ readonly Unspecified: 0;
20
+ readonly Render: 1;
21
+ readonly Reaction: 2;
22
+ readonly Profile: 3;
23
+ readonly Inline: 4;
24
+ readonly Icon: 5;
25
+ readonly Attachment: 6;
26
+ readonly Session: 7;
27
+ readonly Preview: 8;
28
+ };
29
+ /** The set of valid {@link Disposition} values. */
30
+ export type Disposition = (typeof Disposition)[keyof typeof Disposition];
31
+ /**
32
+ * {@link MultiPart} `partSemantics` — how a client treats the child parts (draft-ietf-mimi-content-08:
33
+ * `chooseOne=0, singleUnit=1, processAll=2`).
34
+ */
35
+ export declare const PartSemantics: {
36
+ readonly ChooseOne: 0;
37
+ readonly SingleUnit: 1;
38
+ readonly ProcessAll: 2;
39
+ };
40
+ /** The set of valid {@link PartSemantics} values. */
41
+ export type PartSemantics = (typeof PartSemantics)[keyof typeof PartSemantics];
42
+ /**
43
+ * Named-Information hash algorithm. SHA-256 is the only value we emit (identifier `0x01`, per
44
+ * draft-ietf-mimi-content-08).
45
+ */
46
+ export declare const HashAlg: {
47
+ readonly Sha256: 1;
48
+ };
49
+ /** The set of valid {@link HashAlg} values. */
50
+ export type HashAlg = (typeof HashAlg)[keyof typeof HashAlg];
51
+ /** A tombstone body (delete / un-react) — `NullPart` with the NestedPart wrapper's disposition/language. */
52
+ export interface NullPart {
53
+ /** Cardinality tag — always {@link Cardinality.Null}. */
54
+ cardinality: typeof Cardinality.Null;
55
+ /** Wrapper disposition (typically {@link Disposition.Render}); kept for wire-faithful round-trip. */
56
+ disposition: Disposition;
57
+ /** BCP-47 language tag, or `""`. */
58
+ language: string;
59
+ }
60
+ /** An inline body part (text, reaction token, …) — draft `SinglePart` + the NestedPart wrapper fields. */
61
+ export interface SinglePart {
62
+ /** Cardinality tag — always {@link Cardinality.Single}. */
63
+ cardinality: typeof Cardinality.Single;
64
+ /** How a client should treat this part (`Render` for text, `Reaction` for a reaction token, …). */
65
+ disposition: Disposition;
66
+ /** BCP-47 language tag for `content`, or `""` when not applicable. */
67
+ language: string;
68
+ /** MIME type of `content` (e.g. `text/markdown`). */
69
+ contentType: string;
70
+ /** The raw body bytes (UTF-8 for text types). */
71
+ content: Uint8Array;
72
+ }
73
+ /** An external (by-reference, encrypted) attachment part — Tier 3; encoded, not yet surfaced. */
74
+ export interface ExternalPart {
75
+ /** Cardinality tag — always {@link Cardinality.External}. */
76
+ cardinality: typeof Cardinality.External;
77
+ /** How a client should treat this part (typically {@link Disposition.Attachment}). */
78
+ disposition: Disposition;
79
+ /** BCP-47 language tag, or `""`. */
80
+ language: string;
81
+ /** MIME type of the referenced blob. */
82
+ contentType: string;
83
+ /** Fetch URL for the encrypted blob. */
84
+ url: string;
85
+ /** Absolute expiry of the URL (0 = none). */
86
+ expires: number;
87
+ /** Plaintext size in bytes. */
88
+ size: number;
89
+ /** Symmetric encryption algorithm identifier for the blob (draft `encAlg`). */
90
+ encAlgorithm: number;
91
+ /** Symmetric key for the blob (kept client-side only). */
92
+ key: Uint8Array;
93
+ /** AEAD nonce. */
94
+ nonce: Uint8Array;
95
+ /** AEAD associated data. */
96
+ aad: Uint8Array;
97
+ /** Hash algorithm of {@link ExternalPart.contentHash} (we emit {@link HashAlg.Sha256}). */
98
+ hashAlgorithm: HashAlg;
99
+ /** Hash of the plaintext blob (integrity). */
100
+ contentHash: Uint8Array;
101
+ /** Human-readable description / alt text. */
102
+ description: string;
103
+ /** Suggested filename. */
104
+ filename: string;
105
+ }
106
+ /** A composite body of ordered sub-parts (draft `MultiPart`; at least 2 children). */
107
+ export interface MultiPart {
108
+ /** Cardinality tag — always {@link Cardinality.Multi}. */
109
+ cardinality: typeof Cardinality.Multi;
110
+ /** Wrapper disposition for the composite. */
111
+ disposition: Disposition;
112
+ /** BCP-47 language tag, or `""`. */
113
+ language: string;
114
+ /** How the child parts relate ({@link PartSemantics}). */
115
+ partSemantics: PartSemantics;
116
+ /** The ordered child parts (draft requires 2 or more). */
117
+ parts: Part[];
118
+ }
119
+ /** The body tree: a cardinality-tagged union of {@link NullPart}, {@link SinglePart}, {@link ExternalPart}, {@link MultiPart}. */
120
+ export type Part = NullPart | SinglePart | ExternalPart | MultiPart;
121
+ /** Expiry directive (draft `Expiration = [relative: bool, time: uint .size 4]`). */
122
+ export interface Expiration {
123
+ /** `true` = `time` is seconds relative to receipt; `false` = absolute UNIX time. */
124
+ relative: boolean;
125
+ /** The expiry time (seconds). */
126
+ time: number;
127
+ }
128
+ /** The MIMI message content structure (draft-ietf-mimi-content-08; see file header for the CDDL). */
129
+ export interface MimiContent {
130
+ /** Per-message CSPRNG bytes (draft `salt`, 16 bytes) — unlinkability of the content hash. */
131
+ salt: Uint8Array;
132
+ /** 32-byte content-hash (MessageId) of a message this replaces (edit/delete/un-react), or `null`. */
133
+ replaces: Uint8Array | null;
134
+ /** Threading topic id (Tier 3; encoded, unsurfaced). Empty = none. */
135
+ topicId: Uint8Array;
136
+ /** Expiry directive (draft `Expiration`), or `null` for none. Tier 3; encoded, unsurfaced. */
137
+ expires: Expiration | null;
138
+ /** 32-byte content-hash (MessageId) of the reply target, or `null`. */
139
+ inReplyTo: Uint8Array | null;
140
+ /** Extension map (round-tripped opaquely). */
141
+ extensions: CborMap;
142
+ /** The message body tree (draft `NestedPart`). */
143
+ nestedPart: Part;
144
+ }
145
+ /**
146
+ * Schema bounds enforced on decode (DoS / abuse guard): max sibling parts in a {@link MultiPart}, and
147
+ * max part-tree depth. (draft-08 has no `lastSeen`, so there is no list bound here.)
148
+ */
149
+ export declare const MIMI_LIMITS: {
150
+ readonly maxParts: 64;
151
+ readonly maxNesting: 8;
152
+ };
153
+ /**
154
+ * Encode a {@link MimiContent} to canonical CBOR bytes per the draft-08 wire layout.
155
+ * @param c - The content to encode.
156
+ * @returns Canonical CBOR bytes (stable for equal content — the basis for {@link contentHash}).
157
+ * @throws {Error} If a field carries an out-of-subset CBOR value (e.g. a non-integer number).
158
+ * @example
159
+ * ```ts
160
+ * const bytes = encodeMimiContent(myContent);
161
+ * const same = decodeMimiContent(bytes); // round-trips
162
+ * ```
163
+ */
164
+ export declare function encodeMimiContent(c: MimiContent): Uint8Array;
165
+ /**
166
+ * Strict-decode + schema-validate canonical CBOR into a {@link MimiContent}. Fails closed on any
167
+ * structural or bounds violation (untrusted peer input — CLAUDE.md §1).
168
+ * @param bytes - The canonical CBOR content bytes (after unframing).
169
+ * @returns The validated {@link MimiContent}.
170
+ * @throws {Error} On a malformed structure, wrong field type, an unknown {@link Cardinality}, or a
171
+ * {@link MIMI_LIMITS} bound exceeded. The error message never includes message plaintext.
172
+ * @example
173
+ * ```ts
174
+ * const content = decodeMimiContent(peerBytes); // throws on any tampering
175
+ * ```
176
+ */
177
+ export declare function decodeMimiContent(bytes: Uint8Array): MimiContent;
178
+ /**
179
+ * The MIMI content-hash: a 32-byte, MessageId-SHAPED reference value used to point at a message
180
+ * (reply / edit / delete / un-react). Per the file-header deviation note, we lack federation
181
+ * identities, so instead of draft-08's URI-prefixed input we compute
182
+ * `0x01 || sha256(encodeMimiContent(c))[0..30]` — the leading `0x01` is the SHA-256 hash-algorithm
183
+ * identifier, then the first 31 bytes of the SHA-256 over our canonical CBOR (which already includes
184
+ * the per-message `salt`). Structurally a real MIMI MessageId; stable across runtimes; salt-sensitive.
185
+ * The blind server never sees this. `replaces` / `inReplyTo` are populated with this value.
186
+ * @param c - The content to hash.
187
+ * @returns A 32-byte MessageId (`[0]` is `0x01`; `[1..31]` are `sha256(canonical CBOR)[0..30]`).
188
+ * @example
189
+ * ```ts
190
+ * const id = contentHash(myContent); // 32 bytes, id[0] === 0x01, salt-sensitive
191
+ * reply.inReplyTo = id;
192
+ * ```
193
+ */
194
+ export declare function contentHash(c: MimiContent): Uint8Array;