@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.
- package/dist/cjs/content/builders.d.ts +40 -0
- package/dist/cjs/content/builders.js +85 -0
- package/dist/cjs/content/builders.js.map +1 -0
- package/dist/cjs/content/cbor.d.ts +48 -0
- package/dist/cjs/content/cbor.js +298 -0
- package/dist/cjs/content/cbor.js.map +1 -0
- package/dist/cjs/content/frame.d.ts +24 -0
- package/dist/cjs/content/frame.js +39 -0
- package/dist/cjs/content/frame.js.map +1 -0
- package/dist/cjs/content/mimi-content.d.ts +194 -0
- package/dist/cjs/content/mimi-content.js +289 -0
- package/dist/cjs/content/mimi-content.js.map +1 -0
- package/dist/cjs/hooks/message-fold.d.ts +91 -0
- package/dist/cjs/hooks/message-fold.js +218 -0
- package/dist/cjs/hooks/message-fold.js.map +1 -0
- package/dist/cjs/hooks/useSecureMessages.d.ts +30 -18
- package/dist/cjs/hooks/useSecureMessages.js +190 -238
- package/dist/cjs/hooks/useSecureMessages.js.map +1 -1
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.js +27 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/persistence/repository.d.ts +11 -11
- package/dist/cjs/persistence/repository.js +19 -19
- package/dist/cjs/persistence/repository.js.map +1 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/content/builders.d.ts +40 -0
- package/dist/esm/content/builders.js +77 -0
- package/dist/esm/content/builders.js.map +1 -0
- package/dist/esm/content/cbor.d.ts +48 -0
- package/dist/esm/content/cbor.js +292 -0
- package/dist/esm/content/cbor.js.map +1 -0
- package/dist/esm/content/frame.d.ts +24 -0
- package/dist/esm/content/frame.js +34 -0
- package/dist/esm/content/frame.js.map +1 -0
- package/dist/esm/content/mimi-content.d.ts +194 -0
- package/dist/esm/content/mimi-content.js +283 -0
- package/dist/esm/content/mimi-content.js.map +1 -0
- package/dist/esm/hooks/message-fold.d.ts +91 -0
- package/dist/esm/hooks/message-fold.js +214 -0
- package/dist/esm/hooks/message-fold.js.map +1 -0
- package/dist/esm/hooks/useSecureMessages.d.ts +30 -18
- package/dist/esm/hooks/useSecureMessages.js +192 -240
- package/dist/esm/hooks/useSecureMessages.js.map +1 -1
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/persistence/repository.d.ts +11 -11
- package/dist/esm/persistence/repository.js +19 -19
- package/dist/esm/persistence/repository.js.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { type MimiContent } from "./mimi-content.js";
|
|
2
|
+
/**
|
|
3
|
+
* A plain text post.
|
|
4
|
+
* @param body - The markdown message body.
|
|
5
|
+
* @returns A {@link MimiContent} with a SinglePart `text/markdown` Render body and a fresh salt.
|
|
6
|
+
*/
|
|
7
|
+
export declare function buildPost(body: string): MimiContent;
|
|
8
|
+
/**
|
|
9
|
+
* A reply to another message.
|
|
10
|
+
* @param body - The reply body.
|
|
11
|
+
* @param targetHash - The replied-to message's 32-byte content-hash (MessageId).
|
|
12
|
+
* @returns A text {@link MimiContent} with `inReplyTo` set to `targetHash`.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildReply(body: string, targetHash: Uint8Array): MimiContent;
|
|
15
|
+
/**
|
|
16
|
+
* An edit of an existing message.
|
|
17
|
+
* @param targetHash - The edited message's 32-byte content-hash.
|
|
18
|
+
* @param body - The new body.
|
|
19
|
+
* @returns A text {@link MimiContent} with `replaces` set to `targetHash`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function buildEdit(targetHash: Uint8Array, body: string): MimiContent;
|
|
22
|
+
/**
|
|
23
|
+
* A delete (tombstone) of an existing message.
|
|
24
|
+
* @param targetHash - The deleted message's 32-byte content-hash.
|
|
25
|
+
* @returns A {@link MimiContent} with `replaces` set and a NullPart body.
|
|
26
|
+
*/
|
|
27
|
+
export declare function buildDelete(targetHash: Uint8Array): MimiContent;
|
|
28
|
+
/**
|
|
29
|
+
* A reaction to a message.
|
|
30
|
+
* @param targetHash - The reacted-to message's 32-byte content-hash.
|
|
31
|
+
* @param token - The reaction token (e.g. an emoji).
|
|
32
|
+
* @returns A {@link MimiContent} with `inReplyTo` set and a Reaction-disposition `text/plain` body.
|
|
33
|
+
*/
|
|
34
|
+
export declare function buildReaction(targetHash: Uint8Array, token: string): MimiContent;
|
|
35
|
+
/**
|
|
36
|
+
* An un-react: withdraws one of your own reactions.
|
|
37
|
+
* @param reactionHash - The 32-byte content-hash of YOUR reaction message being withdrawn.
|
|
38
|
+
* @returns A {@link MimiContent} with `replaces` set and a NullPart body.
|
|
39
|
+
*/
|
|
40
|
+
export declare function buildUnreact(reactionHash: Uint8Array): MimiContent;
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Tier-2 MimiContent builders — the six surfaced operations (post/reply/edit/delete/react/un-react).
|
|
3
|
+
//
|
|
4
|
+
// Each mints a fresh CSPRNG salt (crypto.getRandomValues — never Math.random; CLAUDE.md §1) so equal
|
|
5
|
+
// bodies still hash distinctly (unlinkability). The structural details of draft-08 MimiContent
|
|
6
|
+
// (bare-MessageId references, disposition/language on the NestedPart wrapper, NullPart tombstones) stay
|
|
7
|
+
// here so the hook deals only in builders. References (inReplyTo/replaces) are 32-byte content-hashes
|
|
8
|
+
// computed by the caller via contentHash(...).
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.buildPost = buildPost;
|
|
11
|
+
exports.buildReply = buildReply;
|
|
12
|
+
exports.buildEdit = buildEdit;
|
|
13
|
+
exports.buildDelete = buildDelete;
|
|
14
|
+
exports.buildReaction = buildReaction;
|
|
15
|
+
exports.buildUnreact = buildUnreact;
|
|
16
|
+
const mimi_content_js_1 = require("./mimi-content.js");
|
|
17
|
+
const utf8 = (s) => new TextEncoder().encode(s);
|
|
18
|
+
/** 16 bytes of CSPRNG salt. WebCrypto `getRandomValues` is present on web, React Native, and Node ≥ 19. */
|
|
19
|
+
function freshSalt() {
|
|
20
|
+
return crypto.getRandomValues(new Uint8Array(16));
|
|
21
|
+
}
|
|
22
|
+
/** A SinglePart text body with the given disposition + MIME type. */
|
|
23
|
+
function singleText(body, disposition, contentType) {
|
|
24
|
+
return { cardinality: mimi_content_js_1.Cardinality.Single, disposition, language: "", contentType, content: utf8(body) };
|
|
25
|
+
}
|
|
26
|
+
/** A NullPart tombstone (delete / un-react). The wrapper still carries disposition + language. */
|
|
27
|
+
function nullPart() {
|
|
28
|
+
return { cardinality: mimi_content_js_1.Cardinality.Null, disposition: mimi_content_js_1.Disposition.Render, language: "" };
|
|
29
|
+
}
|
|
30
|
+
/** The fields shared by every built message (fresh salt; no topic/expiry/extensions). */
|
|
31
|
+
function base() {
|
|
32
|
+
return { salt: freshSalt(), topicId: new Uint8Array(), expires: null, extensions: new Map() };
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A plain text post.
|
|
36
|
+
* @param body - The markdown message body.
|
|
37
|
+
* @returns A {@link MimiContent} with a SinglePart `text/markdown` Render body and a fresh salt.
|
|
38
|
+
*/
|
|
39
|
+
function buildPost(body) {
|
|
40
|
+
return { ...base(), replaces: null, inReplyTo: null, nestedPart: singleText(body, mimi_content_js_1.Disposition.Render, "text/markdown") };
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* A reply to another message.
|
|
44
|
+
* @param body - The reply body.
|
|
45
|
+
* @param targetHash - The replied-to message's 32-byte content-hash (MessageId).
|
|
46
|
+
* @returns A text {@link MimiContent} with `inReplyTo` set to `targetHash`.
|
|
47
|
+
*/
|
|
48
|
+
function buildReply(body, targetHash) {
|
|
49
|
+
return { ...base(), replaces: null, inReplyTo: targetHash, nestedPart: singleText(body, mimi_content_js_1.Disposition.Render, "text/markdown") };
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* An edit of an existing message.
|
|
53
|
+
* @param targetHash - The edited message's 32-byte content-hash.
|
|
54
|
+
* @param body - The new body.
|
|
55
|
+
* @returns A text {@link MimiContent} with `replaces` set to `targetHash`.
|
|
56
|
+
*/
|
|
57
|
+
function buildEdit(targetHash, body) {
|
|
58
|
+
return { ...base(), replaces: targetHash, inReplyTo: null, nestedPart: singleText(body, mimi_content_js_1.Disposition.Render, "text/markdown") };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A delete (tombstone) of an existing message.
|
|
62
|
+
* @param targetHash - The deleted message's 32-byte content-hash.
|
|
63
|
+
* @returns A {@link MimiContent} with `replaces` set and a NullPart body.
|
|
64
|
+
*/
|
|
65
|
+
function buildDelete(targetHash) {
|
|
66
|
+
return { ...base(), replaces: targetHash, inReplyTo: null, nestedPart: nullPart() };
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A reaction to a message.
|
|
70
|
+
* @param targetHash - The reacted-to message's 32-byte content-hash.
|
|
71
|
+
* @param token - The reaction token (e.g. an emoji).
|
|
72
|
+
* @returns A {@link MimiContent} with `inReplyTo` set and a Reaction-disposition `text/plain` body.
|
|
73
|
+
*/
|
|
74
|
+
function buildReaction(targetHash, token) {
|
|
75
|
+
return { ...base(), replaces: null, inReplyTo: targetHash, nestedPart: singleText(token, mimi_content_js_1.Disposition.Reaction, "text/plain") };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* An un-react: withdraws one of your own reactions.
|
|
79
|
+
* @param reactionHash - The 32-byte content-hash of YOUR reaction message being withdrawn.
|
|
80
|
+
* @returns A {@link MimiContent} with `replaces` set and a NullPart body.
|
|
81
|
+
*/
|
|
82
|
+
function buildUnreact(reactionHash) {
|
|
83
|
+
return { ...base(), replaces: reactionHash, inReplyTo: null, nestedPart: nullPart() };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=builders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.js","sourceRoot":"","sources":["../../../src/content/builders.ts"],"names":[],"mappings":";AAAA,qGAAqG;AACrG,EAAE;AACF,qGAAqG;AACrG,+FAA+F;AAC/F,wGAAwG;AACxG,sGAAsG;AACtG,+CAA+C;;AAiC/C,8BAEC;AAQD,gCAEC;AAQD,8BAEC;AAOD,kCAEC;AAQD,sCAEC;AAOD,oCAEC;AAjFD,uDAE2B;AAE3B,MAAM,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAExD,2GAA2G;AAC3G,SAAS,SAAS;IAChB,OAAO,MAAM,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC;AAED,qEAAqE;AACrE,SAAS,UAAU,CAAC,IAAY,EAAE,WAAwB,EAAE,WAAmB;IAC7E,OAAO,EAAE,WAAW,EAAE,6BAAW,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;AAC1G,CAAC;AAED,kGAAkG;AAClG,SAAS,QAAQ;IACf,OAAO,EAAE,WAAW,EAAE,6BAAW,CAAC,IAAI,EAAE,WAAW,EAAE,6BAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;AAC1F,CAAC;AAED,yFAAyF;AACzF,SAAS,IAAI;IACX,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,UAAU,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;AAChG,CAAC;AAED;;;;GAIG;AACH,SAAgB,SAAS,CAAC,IAAY;IACpC,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,6BAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;AAC3H,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,IAAY,EAAE,UAAsB;IAC7D,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,6BAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;AACjI,CAAC;AAED;;;;;GAKG;AACH,SAAgB,SAAS,CAAC,UAAsB,EAAE,IAAY;IAC5D,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,6BAAW,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,CAAC;AACjI,CAAC;AAED;;;;GAIG;AACH,SAAgB,WAAW,CAAC,UAAsB;IAChD,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC;AACtF,CAAC;AAED;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,UAAsB,EAAE,KAAa;IACjE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC,KAAK,EAAE,6BAAW,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;AACjI,CAAC;AAED;;;;GAIG;AACH,SAAgB,YAAY,CAAC,YAAwB;IACnD,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,CAAC;AACxF,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/** A value in the supported CBOR subset. Integers in safe-int range are `number`; larger are `bigint`. */
|
|
2
|
+
export type CborValue = number | bigint | Uint8Array | string | CborValue[] | CborMap | CborTag | boolean | null;
|
|
3
|
+
/** A CBOR map (major type 5). Keys are encoded and sorted deterministically on encode. */
|
|
4
|
+
export type CborMap = Map<CborValue, CborValue>;
|
|
5
|
+
/** A CBOR tagged value (major type 6): a `tag` number wrapping one nested value. */
|
|
6
|
+
export declare class CborTag {
|
|
7
|
+
/** The CBOR tag number (major type 6 argument). */
|
|
8
|
+
readonly tag: number | bigint;
|
|
9
|
+
/** The single nested value wrapped by this tag. */
|
|
10
|
+
readonly value: CborValue;
|
|
11
|
+
constructor(
|
|
12
|
+
/** The CBOR tag number (major type 6 argument). */
|
|
13
|
+
tag: number | bigint,
|
|
14
|
+
/** The single nested value wrapped by this tag. */
|
|
15
|
+
value: CborValue);
|
|
16
|
+
}
|
|
17
|
+
/** Strict-decode bounds. Defaults: 1 MiB total, depth 32, 4096 items per array/map. */
|
|
18
|
+
export interface CborLimits {
|
|
19
|
+
/** Reject inputs longer than this many bytes (DoS guard). Default 1 << 20. */
|
|
20
|
+
maxBytes?: number;
|
|
21
|
+
/** Reject nesting deeper than this. Default 32. */
|
|
22
|
+
maxDepth?: number;
|
|
23
|
+
/** Reject any array/map with more than this many items. Default 4096. */
|
|
24
|
+
maxItems?: number;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Encode a {@link CborValue} to canonical CBOR bytes (RFC 8949 §4.2 core deterministic rules).
|
|
28
|
+
*
|
|
29
|
+
* @param value - A value in the supported subset.
|
|
30
|
+
* @returns The canonical CBOR byte encoding.
|
|
31
|
+
* @throws {Error} On a non-integer number, an integer above u64, or an unsupported value type.
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* encode(new Map([[1, "a"]])); // → a2 01 61 61 … (keys sorted by encoded bytes)
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare function encode(value: CborValue): Uint8Array;
|
|
38
|
+
/**
|
|
39
|
+
* Strict-decode canonical CBOR bytes from the supported subset. Rejects non-canonical encodings,
|
|
40
|
+
* out-of-subset major/simple values, trailing bytes, and anything exceeding {@link CborLimits}.
|
|
41
|
+
*
|
|
42
|
+
* @param bytes - The CBOR input (untrusted peer data — decoded fail-closed).
|
|
43
|
+
* @param limits - Optional {@link CborLimits} bounds.
|
|
44
|
+
* @returns The decoded {@link CborValue}.
|
|
45
|
+
* @throws {Error} On any non-canonical encoding, out-of-subset value, truncation, trailing bytes, or
|
|
46
|
+
* a bound (size/depth/item-count) being exceeded.
|
|
47
|
+
*/
|
|
48
|
+
export declare function decode(bytes: Uint8Array, limits?: CborLimits): CborValue;
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Deterministic CBOR (RFC 8949) over a constrained subset — the wire form for MimiContent.
|
|
3
|
+
//
|
|
4
|
+
// Where it sits: this is pure byte-shuffling ABOVE the SecureChatCrypto seam and INSIDE the padding
|
|
5
|
+
// frame. It encodes message content to canonical CBOR so the SHA-256 contentHash is stable across
|
|
6
|
+
// runtimes (web/native), and decodes UNTRUSTED peer bytes strictly and within bounds (CLAUDE.md §1:
|
|
7
|
+
// validate-then-decode, fail closed). The subset is exactly what MimiContent needs — unsigned/negative
|
|
8
|
+
// integers, byte/text strings, arrays, maps, tags, and the simple values false/true/null — and
|
|
9
|
+
// deliberately EXCLUDES CBOR's hard, ambiguous parts: floats, indefinite-length items, and bignums.
|
|
10
|
+
//
|
|
11
|
+
// "Canonical" = RFC 8949 §4.2 core deterministic rules for this subset: shortest-form integers and
|
|
12
|
+
// lengths, definite lengths, map keys sorted by their encoded bytes, no duplicate keys.
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.CborTag = void 0;
|
|
15
|
+
exports.encode = encode;
|
|
16
|
+
exports.decode = decode;
|
|
17
|
+
/** A CBOR tagged value (major type 6): a `tag` number wrapping one nested value. */
|
|
18
|
+
class CborTag {
|
|
19
|
+
constructor(
|
|
20
|
+
/** The CBOR tag number (major type 6 argument). */
|
|
21
|
+
tag,
|
|
22
|
+
/** The single nested value wrapped by this tag. */
|
|
23
|
+
value) {
|
|
24
|
+
this.tag = tag;
|
|
25
|
+
this.value = value;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.CborTag = CborTag;
|
|
29
|
+
const enc = new TextEncoder();
|
|
30
|
+
const dec = new TextDecoder("utf-8", { fatal: true });
|
|
31
|
+
function concat(parts) {
|
|
32
|
+
let n = 0;
|
|
33
|
+
for (const p of parts)
|
|
34
|
+
n += p.length;
|
|
35
|
+
const out = new Uint8Array(n);
|
|
36
|
+
let o = 0;
|
|
37
|
+
for (const p of parts) {
|
|
38
|
+
out.set(p, o);
|
|
39
|
+
o += p.length;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
/** Compare two byte arrays lexicographically (the canonical map-key order). */
|
|
44
|
+
function cmpBytes(a, b) {
|
|
45
|
+
const n = Math.min(a.length, b.length);
|
|
46
|
+
for (let i = 0; i < n; i++)
|
|
47
|
+
if (a[i] !== b[i])
|
|
48
|
+
return a[i] - b[i];
|
|
49
|
+
return a.length - b.length;
|
|
50
|
+
}
|
|
51
|
+
/** Emit a CBOR head: the major type (0..7) and its argument, in shortest form. */
|
|
52
|
+
function head(major, arg) {
|
|
53
|
+
const m = major << 5;
|
|
54
|
+
const n = typeof arg === "bigint" ? arg : BigInt(arg);
|
|
55
|
+
if (n < 0n)
|
|
56
|
+
throw new Error("cbor: negative head argument");
|
|
57
|
+
if (n < 24n)
|
|
58
|
+
return Uint8Array.of(m | Number(n));
|
|
59
|
+
if (n < 0x100n)
|
|
60
|
+
return Uint8Array.of(m | 24, Number(n));
|
|
61
|
+
if (n < 0x10000n)
|
|
62
|
+
return Uint8Array.of(m | 25, Number(n >> 8n) & 0xff, Number(n & 0xffn));
|
|
63
|
+
if (n < 0x100000000n)
|
|
64
|
+
return Uint8Array.of(m | 26, Number((n >> 24n) & 0xffn), Number((n >> 16n) & 0xffn), Number((n >> 8n) & 0xffn), Number(n & 0xffn));
|
|
65
|
+
if (n < 0x10000000000000000n) {
|
|
66
|
+
const out = new Uint8Array(9);
|
|
67
|
+
out[0] = m | 27;
|
|
68
|
+
let v = n;
|
|
69
|
+
for (let i = 8; i >= 1; i--) {
|
|
70
|
+
out[i] = Number(v & 0xffn);
|
|
71
|
+
v >>= 8n;
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
throw new Error("cbor: integer exceeds u64 (no bignum support)");
|
|
76
|
+
}
|
|
77
|
+
function encodeInto(v, parts) {
|
|
78
|
+
if (v === null)
|
|
79
|
+
return void parts.push(Uint8Array.of(0xf6));
|
|
80
|
+
if (v === false)
|
|
81
|
+
return void parts.push(Uint8Array.of(0xf4));
|
|
82
|
+
if (v === true)
|
|
83
|
+
return void parts.push(Uint8Array.of(0xf5));
|
|
84
|
+
const t = typeof v;
|
|
85
|
+
if (t === "number" || t === "bigint") {
|
|
86
|
+
if (t === "number" && !Number.isInteger(v))
|
|
87
|
+
throw new Error("cbor: non-integer number (no float support)");
|
|
88
|
+
const n = typeof v === "bigint" ? v : BigInt(v);
|
|
89
|
+
if (n >= 0n)
|
|
90
|
+
parts.push(head(0, n));
|
|
91
|
+
else
|
|
92
|
+
parts.push(head(1, -1n - n));
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if (v instanceof Uint8Array) {
|
|
96
|
+
parts.push(head(2, v.length));
|
|
97
|
+
parts.push(v);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (t === "string") {
|
|
101
|
+
const b = enc.encode(v);
|
|
102
|
+
parts.push(head(3, b.length));
|
|
103
|
+
parts.push(b);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(v)) {
|
|
107
|
+
parts.push(head(4, v.length));
|
|
108
|
+
for (const e of v)
|
|
109
|
+
encodeInto(e, parts);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (v instanceof CborTag) {
|
|
113
|
+
parts.push(head(6, v.tag));
|
|
114
|
+
encodeInto(v.value, parts);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (v instanceof Map) {
|
|
118
|
+
const entries = [...v.entries()].map(([k, val]) => [encode(k), val]);
|
|
119
|
+
entries.sort((a, b) => cmpBytes(a[0], b[0]));
|
|
120
|
+
for (let i = 1; i < entries.length; i++)
|
|
121
|
+
if (cmpBytes(entries[i - 1][0], entries[i][0]) === 0)
|
|
122
|
+
throw new Error("cbor: duplicate map key");
|
|
123
|
+
parts.push(head(5, entries.length));
|
|
124
|
+
for (const [kb, val] of entries) {
|
|
125
|
+
parts.push(kb);
|
|
126
|
+
encodeInto(val, parts);
|
|
127
|
+
}
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
throw new Error("cbor: unsupported value");
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Encode a {@link CborValue} to canonical CBOR bytes (RFC 8949 §4.2 core deterministic rules).
|
|
134
|
+
*
|
|
135
|
+
* @param value - A value in the supported subset.
|
|
136
|
+
* @returns The canonical CBOR byte encoding.
|
|
137
|
+
* @throws {Error} On a non-integer number, an integer above u64, or an unsupported value type.
|
|
138
|
+
* @example
|
|
139
|
+
* ```ts
|
|
140
|
+
* encode(new Map([[1, "a"]])); // → a2 01 61 61 … (keys sorted by encoded bytes)
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
function encode(value) {
|
|
144
|
+
const parts = [];
|
|
145
|
+
encodeInto(value, parts);
|
|
146
|
+
return concat(parts);
|
|
147
|
+
}
|
|
148
|
+
class Reader {
|
|
149
|
+
constructor(buf, limits) {
|
|
150
|
+
this.buf = buf;
|
|
151
|
+
this.limits = limits;
|
|
152
|
+
this.pos = 0;
|
|
153
|
+
}
|
|
154
|
+
byte() {
|
|
155
|
+
if (this.pos >= this.buf.length)
|
|
156
|
+
throw new Error("cbor: unexpected end of input");
|
|
157
|
+
return this.buf[this.pos++];
|
|
158
|
+
}
|
|
159
|
+
/** Read the argument for additional-info `ai`, enforcing shortest-form (canonical). */
|
|
160
|
+
arg(ai) {
|
|
161
|
+
if (ai < 24)
|
|
162
|
+
return BigInt(ai);
|
|
163
|
+
if (ai === 24) {
|
|
164
|
+
const n = BigInt(this.byte());
|
|
165
|
+
if (n < 24n)
|
|
166
|
+
throw new Error("cbor: non-canonical (shortest-form) integer");
|
|
167
|
+
return n;
|
|
168
|
+
}
|
|
169
|
+
if (ai === 25) {
|
|
170
|
+
const n = (BigInt(this.byte()) << 8n) | BigInt(this.byte());
|
|
171
|
+
if (n < 0x100n)
|
|
172
|
+
throw new Error("cbor: non-canonical (shortest-form) integer");
|
|
173
|
+
return n;
|
|
174
|
+
}
|
|
175
|
+
if (ai === 26) {
|
|
176
|
+
let n = 0n;
|
|
177
|
+
for (let i = 0; i < 4; i++)
|
|
178
|
+
n = (n << 8n) | BigInt(this.byte());
|
|
179
|
+
if (n < 0x10000n)
|
|
180
|
+
throw new Error("cbor: non-canonical (shortest-form) integer");
|
|
181
|
+
return n;
|
|
182
|
+
}
|
|
183
|
+
if (ai === 27) {
|
|
184
|
+
let n = 0n;
|
|
185
|
+
for (let i = 0; i < 8; i++)
|
|
186
|
+
n = (n << 8n) | BigInt(this.byte());
|
|
187
|
+
if (n < 0x100000000n)
|
|
188
|
+
throw new Error("cbor: non-canonical (shortest-form) integer");
|
|
189
|
+
return n;
|
|
190
|
+
}
|
|
191
|
+
throw new Error("cbor: reserved/indefinite additional info (outside subset)");
|
|
192
|
+
}
|
|
193
|
+
take(n) {
|
|
194
|
+
if (n > BigInt(this.limits.maxBytes))
|
|
195
|
+
throw new Error("cbor: length exceeds bounds");
|
|
196
|
+
const len = Number(n);
|
|
197
|
+
if (this.pos + len > this.buf.length)
|
|
198
|
+
throw new Error("cbor: unexpected end of input");
|
|
199
|
+
const slice = this.buf.subarray(this.pos, this.pos + len);
|
|
200
|
+
this.pos += len;
|
|
201
|
+
return slice;
|
|
202
|
+
}
|
|
203
|
+
/** Integers small enough stay `number`; larger become `bigint`. */
|
|
204
|
+
intVal(n, negative) {
|
|
205
|
+
const v = negative ? -1n - n : n;
|
|
206
|
+
return v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER)
|
|
207
|
+
? Number(v)
|
|
208
|
+
: v;
|
|
209
|
+
}
|
|
210
|
+
value(depth) {
|
|
211
|
+
if (depth > this.limits.maxDepth)
|
|
212
|
+
throw new Error("cbor: nesting depth exceeds bounds");
|
|
213
|
+
const ib = this.byte();
|
|
214
|
+
const major = ib >> 5;
|
|
215
|
+
const ai = ib & 0x1f;
|
|
216
|
+
switch (major) {
|
|
217
|
+
case 0:
|
|
218
|
+
return this.intVal(this.arg(ai), false);
|
|
219
|
+
case 1:
|
|
220
|
+
return this.intVal(this.arg(ai), true);
|
|
221
|
+
case 2:
|
|
222
|
+
return this.take(this.arg(ai)).slice(); // copy out of the backing buffer
|
|
223
|
+
case 3:
|
|
224
|
+
return dec.decode(this.take(this.arg(ai)));
|
|
225
|
+
case 4: {
|
|
226
|
+
const len = this.arg(ai);
|
|
227
|
+
if (len > BigInt(this.limits.maxItems))
|
|
228
|
+
throw new Error("cbor: array length exceeds bounds");
|
|
229
|
+
const out = [];
|
|
230
|
+
for (let i = 0n; i < len; i++)
|
|
231
|
+
out.push(this.value(depth + 1));
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
case 5: {
|
|
235
|
+
const len = this.arg(ai);
|
|
236
|
+
if (len > BigInt(this.limits.maxItems))
|
|
237
|
+
throw new Error("cbor: map length exceeds bounds");
|
|
238
|
+
const out = new Map();
|
|
239
|
+
let prevKey = null;
|
|
240
|
+
for (let i = 0n; i < len; i++) {
|
|
241
|
+
const k = this.value(depth + 1);
|
|
242
|
+
const kb = encode(k); // canonical key bytes — enforce strictly-increasing order
|
|
243
|
+
if (prevKey) {
|
|
244
|
+
const c = cmpBytes(prevKey, kb);
|
|
245
|
+
if (c === 0)
|
|
246
|
+
throw new Error("cbor: duplicate map key");
|
|
247
|
+
if (c > 0)
|
|
248
|
+
throw new Error("cbor: map keys not sorted (non-canonical)");
|
|
249
|
+
}
|
|
250
|
+
prevKey = kb;
|
|
251
|
+
out.set(k, this.value(depth + 1));
|
|
252
|
+
}
|
|
253
|
+
return out;
|
|
254
|
+
}
|
|
255
|
+
case 6: {
|
|
256
|
+
// Normalize the tag the same way as integers (safe-int → number, larger → bigint) so a tag
|
|
257
|
+
// round-trips to the same JS type a caller would naturally pass to `new CborTag(...)`.
|
|
258
|
+
const tag = this.intVal(this.arg(ai), false);
|
|
259
|
+
return new CborTag(tag, this.value(depth + 1));
|
|
260
|
+
}
|
|
261
|
+
case 7:
|
|
262
|
+
if (ai === 20)
|
|
263
|
+
return false;
|
|
264
|
+
if (ai === 21)
|
|
265
|
+
return true;
|
|
266
|
+
if (ai === 22)
|
|
267
|
+
return null;
|
|
268
|
+
throw new Error("cbor: float/simple value outside subset");
|
|
269
|
+
default:
|
|
270
|
+
throw new Error("cbor: unknown major type");
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Strict-decode canonical CBOR bytes from the supported subset. Rejects non-canonical encodings,
|
|
276
|
+
* out-of-subset major/simple values, trailing bytes, and anything exceeding {@link CborLimits}.
|
|
277
|
+
*
|
|
278
|
+
* @param bytes - The CBOR input (untrusted peer data — decoded fail-closed).
|
|
279
|
+
* @param limits - Optional {@link CborLimits} bounds.
|
|
280
|
+
* @returns The decoded {@link CborValue}.
|
|
281
|
+
* @throws {Error} On any non-canonical encoding, out-of-subset value, truncation, trailing bytes, or
|
|
282
|
+
* a bound (size/depth/item-count) being exceeded.
|
|
283
|
+
*/
|
|
284
|
+
function decode(bytes, limits = {}) {
|
|
285
|
+
const resolved = {
|
|
286
|
+
maxBytes: limits.maxBytes ?? 1 << 20,
|
|
287
|
+
maxDepth: limits.maxDepth ?? 32,
|
|
288
|
+
maxItems: limits.maxItems ?? 4096,
|
|
289
|
+
};
|
|
290
|
+
if (bytes.length > resolved.maxBytes)
|
|
291
|
+
throw new Error("cbor: input too large (bounds)");
|
|
292
|
+
const r = new Reader(bytes, resolved);
|
|
293
|
+
const v = r.value(0);
|
|
294
|
+
if (r.pos !== bytes.length)
|
|
295
|
+
throw new Error("cbor: trailing bytes after top-level value");
|
|
296
|
+
return v;
|
|
297
|
+
}
|
|
298
|
+
//# 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,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Content routing frame — a single discriminator byte INSIDE the padding frame, ABOVE MimiContent.
|
|
3
|
+
//
|
|
4
|
+
// padPlaintext( frameContent(kind, payload) ) → encrypt. One byte routes user content vs control
|
|
5
|
+
// traffic without wrapping the MimiContent CBOR in another struct (keeps the MIMI bytes pure). The
|
|
6
|
+
// padding frame (util/padding) is the transport concern and is unchanged.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.ContentKind = void 0;
|
|
9
|
+
exports.frameContent = frameContent;
|
|
10
|
+
exports.unframe = unframe;
|
|
11
|
+
/** Content-frame discriminator. `Mimi` = MimiContent CBOR; `IucControl` is reserved for the IUC state machine. */
|
|
12
|
+
exports.ContentKind = { Mimi: 0, IucControl: 1 };
|
|
13
|
+
/**
|
|
14
|
+
* Prefix `payload` with its routing `kind` byte.
|
|
15
|
+
* @param kind - The discriminator (0..255); use {@link ContentKind}.
|
|
16
|
+
* @param payload - The bytes to route (e.g. MimiContent CBOR).
|
|
17
|
+
* @returns `[kind][payload]`.
|
|
18
|
+
* @throws {Error} If `kind` is not an integer in 0..255.
|
|
19
|
+
*/
|
|
20
|
+
function frameContent(kind, payload) {
|
|
21
|
+
if (!Number.isInteger(kind) || kind < 0 || kind > 255)
|
|
22
|
+
throw new Error("content frame: kind must be a byte (0..255)");
|
|
23
|
+
const out = new Uint8Array(payload.length + 1);
|
|
24
|
+
out[0] = kind;
|
|
25
|
+
out.set(payload, 1);
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Split a content frame into its routing `kind` and the remaining `payload`.
|
|
30
|
+
* @param bytes - A `[kind][payload]` frame (after unpadding).
|
|
31
|
+
* @returns `{ kind, payload }`.
|
|
32
|
+
* @throws {Error} If `bytes` is empty (no kind byte).
|
|
33
|
+
*/
|
|
34
|
+
function unframe(bytes) {
|
|
35
|
+
if (bytes.length < 1)
|
|
36
|
+
throw new Error("content frame: empty (too short)");
|
|
37
|
+
return { kind: bytes[0], payload: bytes.subarray(1) };
|
|
38
|
+
}
|
|
39
|
+
//# 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;;;AAa1E,oCAMC;AAQD,0BAGC;AA5BD,kHAAkH;AACrG,QAAA,WAAW,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAW,CAAC;AAG/D;;;;;;GAMG;AACH,SAAgB,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,SAAgB,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"}
|