@needmoretruth/nmts-cli 0.17.2

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 (151) hide show
  1. package/AGENTS.md +591 -0
  2. package/LICENSE +202 -0
  3. package/LICENSING.md +49 -0
  4. package/README.ko.md +641 -0
  5. package/README.md +657 -0
  6. package/dist/account-proof.js +78 -0
  7. package/dist/account.js +75 -0
  8. package/dist/api-key.js +310 -0
  9. package/dist/api.js +271 -0
  10. package/dist/args.js +137 -0
  11. package/dist/artifact-about.js +70 -0
  12. package/dist/autonomy.js +98 -0
  13. package/dist/code-access.js +76 -0
  14. package/dist/code-vault.js +233 -0
  15. package/dist/collision.js +133 -0
  16. package/dist/commands/balance.js +93 -0
  17. package/dist/commands/consent.js +77 -0
  18. package/dist/commands/create.js +356 -0
  19. package/dist/commands/env.js +136 -0
  20. package/dist/commands/expiring.js +167 -0
  21. package/dist/commands/extend.js +236 -0
  22. package/dist/commands/get.js +130 -0
  23. package/dist/commands/kit.js +136 -0
  24. package/dist/commands/listfile.js +105 -0
  25. package/dist/commands/login.js +335 -0
  26. package/dist/commands/logout.js +33 -0
  27. package/dist/commands/ls.js +202 -0
  28. package/dist/commands/marks.js +176 -0
  29. package/dist/commands/mcp.js +139 -0
  30. package/dist/commands/mode.js +54 -0
  31. package/dist/commands/on-collision.js +45 -0
  32. package/dist/commands/organise.js +296 -0
  33. package/dist/commands/public-code.js +89 -0
  34. package/dist/commands/pull.js +185 -0
  35. package/dist/commands/push.js +278 -0
  36. package/dist/commands/put.js +282 -0
  37. package/dist/commands/rebuild.js +160 -0
  38. package/dist/commands/receive.js +125 -0
  39. package/dist/commands/recovery-list.js +104 -0
  40. package/dist/commands/recovery.js +291 -0
  41. package/dist/commands/s3.js +241 -0
  42. package/dist/commands/settings.js +28 -0
  43. package/dist/commands/share.js +276 -0
  44. package/dist/commands/sweep.js +240 -0
  45. package/dist/commands/trash.js +288 -0
  46. package/dist/commands/trial.js +264 -0
  47. package/dist/commands/update.js +169 -0
  48. package/dist/commands/usage.js +84 -0
  49. package/dist/commands/verify.js +331 -0
  50. package/dist/commands/wallet.js +122 -0
  51. package/dist/commands/whoami.js +33 -0
  52. package/dist/consent.js +200 -0
  53. package/dist/credentials.js +311 -0
  54. package/dist/crypto-surface.js +54 -0
  55. package/dist/crypto.js +137 -0
  56. package/dist/download-part.js +144 -0
  57. package/dist/download-sink.js +213 -0
  58. package/dist/download.js +163 -0
  59. package/dist/drive-paths.js +170 -0
  60. package/dist/environment.js +190 -0
  61. package/dist/errors.js +71 -0
  62. package/dist/exit.js +107 -0
  63. package/dist/expiry.js +115 -0
  64. package/dist/extend-chain.js +137 -0
  65. package/dist/extend-plan.js +149 -0
  66. package/dist/extend-sign.js +130 -0
  67. package/dist/guards.js +15 -0
  68. package/dist/help.js +192 -0
  69. package/dist/human-check.js +54 -0
  70. package/dist/item-trash.js +25 -0
  71. package/dist/kit-file.js +133 -0
  72. package/dist/list-file.js +71 -0
  73. package/dist/list-view-find.js +71 -0
  74. package/dist/list-view-order.js +96 -0
  75. package/dist/main.js +394 -0
  76. package/dist/manifest-create.js +81 -0
  77. package/dist/manifest-write.js +244 -0
  78. package/dist/manifest.js +213 -0
  79. package/dist/mark-render.js +45 -0
  80. package/dist/mcp-args.js +154 -0
  81. package/dist/mcp-tools/context.js +50 -0
  82. package/dist/mcp-tools/files.js +133 -0
  83. package/dist/mcp-tools/organise.js +128 -0
  84. package/dist/mcp-tools/reads.js +89 -0
  85. package/dist/mcp-tools/share.js +61 -0
  86. package/dist/mcp.js +142 -0
  87. package/dist/net-retry.js +84 -0
  88. package/dist/network.js +43 -0
  89. package/dist/notice.js +45 -0
  90. package/dist/product.js +38 -0
  91. package/dist/progress.js +110 -0
  92. package/dist/prompt.js +145 -0
  93. package/dist/rebuild.js +255 -0
  94. package/dist/recovery-assemble.js +148 -0
  95. package/dist/recovery-build.js +260 -0
  96. package/dist/recovery-map-file.js +114 -0
  97. package/dist/recovery-map.js +191 -0
  98. package/dist/recovery-release.js +229 -0
  99. package/dist/recovery-seq.js +63 -0
  100. package/dist/recovery-source.js +143 -0
  101. package/dist/registration.js +83 -0
  102. package/dist/s3/listing.js +134 -0
  103. package/dist/s3/multipart.js +104 -0
  104. package/dist/s3/response-sink.js +41 -0
  105. package/dist/s3/same-file.js +117 -0
  106. package/dist/s3/server.js +252 -0
  107. package/dist/s3/sigv4.js +168 -0
  108. package/dist/s3/staging.js +87 -0
  109. package/dist/s3/xml.js +80 -0
  110. package/dist/safe-path.js +89 -0
  111. package/dist/seal.js +206 -0
  112. package/dist/secret-reader.js +112 -0
  113. package/dist/server.js +33 -0
  114. package/dist/session.js +49 -0
  115. package/dist/setup-questions.js +31 -0
  116. package/dist/share.js +195 -0
  117. package/dist/shared/lib/crypto/size-padding.js +126 -0
  118. package/dist/shared/lib/drive/manifest-codec.js +287 -0
  119. package/dist/shared/lib/drive/manifest-index.js +235 -0
  120. package/dist/shared/lib/drive/manifest-ops.js +267 -0
  121. package/dist/shared/lib/drive/manifest-settings.js +65 -0
  122. package/dist/shared/lib/drive/name-conflict.js +121 -0
  123. package/dist/shared/lib/drive/unique-name.js +48 -0
  124. package/dist/shared/lib/extend/epochs.js +256 -0
  125. package/dist/shared/lib/net/retry-budget.js +95 -0
  126. package/dist/shared/lib/share/shared-file-info.js +65 -0
  127. package/dist/shared/lib/storage-network.js +64 -0
  128. package/dist/shared/lib/upload/part-plan.js +28 -0
  129. package/dist/stdout.js +109 -0
  130. package/dist/trash-sweep.js +123 -0
  131. package/dist/units.js +19 -0
  132. package/dist/update-check.js +164 -0
  133. package/dist/update-source.js +143 -0
  134. package/dist/upload-api.js +98 -0
  135. package/dist/upload-file.js +242 -0
  136. package/dist/upload-price.js +117 -0
  137. package/dist/upload-steps.js +111 -0
  138. package/dist/upload-store.js +252 -0
  139. package/dist/upload-wire.js +25 -0
  140. package/dist/upload.js +294 -0
  141. package/dist/usage-report.js +54 -0
  142. package/dist/wallet-chain.js +76 -0
  143. package/dist/wallet.js +209 -0
  144. package/dist/walrus-write.js +188 -0
  145. package/dist/walrus.js +156 -0
  146. package/package.json +56 -0
  147. package/vendor/nmts-crypto/nmts_crypto_wasm.d.ts +469 -0
  148. package/vendor/nmts-crypto/nmts_crypto_wasm.js +1300 -0
  149. package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm +0 -0
  150. package/vendor/nmts-crypto/nmts_crypto_wasm_bg.wasm.d.ts +55 -0
  151. package/vendor/nmts-crypto/package.json +17 -0
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@needmoretruth/nmts-cli",
3
+ "version": "0.17.2",
4
+ "description": "Command-line access to NMTS end-to-end encrypted storage, for people and for their agents.",
5
+ "license": "Apache-2.0",
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "homepage": "https://github.com/needmoretruth/nmts-cli",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/needmoretruth/nmts-cli.git"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/needmoretruth/nmts-cli/issues"
16
+ },
17
+ "keywords": [
18
+ "nmts",
19
+ "walrus",
20
+ "sui",
21
+ "encryption",
22
+ "e2ee",
23
+ "storage",
24
+ "cli",
25
+ "mcp",
26
+ "agent"
27
+ ],
28
+ "type": "module",
29
+ "bin": {
30
+ "nmts": "./dist/main.js"
31
+ },
32
+ "engines": {
33
+ "node": ">=22"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "vendor",
38
+ "README.md",
39
+ "AGENTS.md",
40
+ "LICENSE",
41
+ "LICENSING.md"
42
+ ],
43
+ "scripts": {
44
+ "compile": "tsc -p tsconfig.json",
45
+ "typecheck": "tsc -p tsconfig.json --noEmit",
46
+ "test": "node --test \"test/**/*.test.ts\""
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "^24.3.0",
50
+ "typescript": "^5.9.3"
51
+ },
52
+ "dependencies": {
53
+ "@mysten/sui": "^2.20.1",
54
+ "@mysten/walrus": "^1.2.3"
55
+ }
56
+ }
@@ -0,0 +1,469 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Incremental SHA-256 over a file's PLAINTEXT, for the content-hash envelope
6
+ * (`docs/CRYPTO-FORMAT-NCF3.md` §3).
7
+ *
8
+ * WHY STREAMING: the one-shot `sha256` needs the whole file in memory at once. Uploads run
9
+ * to many gigabytes and parts may be encrypted concurrently, so the hash is accumulated by
10
+ * a separate sequential pass that never holds more than one slice. `update()` in order,
11
+ * then `finalize()` exactly once. Call `free()` afterwards to release the wasm-side memory.
12
+ *
13
+ * Not key material: the digest is of plaintext the caller already holds. It is the SEALED
14
+ * form (see `wrap::seal_content_hash`) that ever reaches the server.
15
+ */
16
+ export class Sha256Hasher {
17
+ free(): void;
18
+ [Symbol.dispose](): void;
19
+ /**
20
+ * The 32-byte digest. Consumes the state — calling twice errors rather than returning
21
+ * the digest of a silently restarted hasher.
22
+ */
23
+ finalize(): Uint8Array;
24
+ /**
25
+ * A fresh hasher with empty state.
26
+ */
27
+ constructor();
28
+ /**
29
+ * Absorb the next plaintext slice, in order. Any slice size.
30
+ */
31
+ update(data: Uint8Array): void;
32
+ }
33
+
34
+ /**
35
+ * Streaming sequential NCF-3 decryptor with full anti-truncation/reorder verification
36
+ * (the download path). Construct with the file DEK and the 72-byte stream header,
37
+ * `push()` ciphertext in arbitrary slice sizes — each call returns decrypted plaintext
38
+ * for any chunks that completed — then call `finish()` after the last byte: it enforces
39
+ * every end-of-stream invariant (all chunks consumed, final chunk flagged, decoded total
40
+ * equals `plaintext_len`, no trailing bytes). Call `free()` afterwards.
41
+ */
42
+ export class StreamDecryptor {
43
+ free(): void;
44
+ [Symbol.dispose](): void;
45
+ /**
46
+ * Verifies the stream ended cleanly (end-of-stream invariants above). Errors on an
47
+ * incomplete or oversized stream; idempotent after a successful call (mirrors Rust).
48
+ */
49
+ finish(): void;
50
+ /**
51
+ * `dek` must be 32 bytes; `header` the 72-byte NCF-3 stream header (parsed and
52
+ * validated here — bad magic/version/chunk size error immediately).
53
+ */
54
+ constructor(dek: Uint8Array, header: Uint8Array);
55
+ /**
56
+ * Feeds ciphertext in. Returns decrypted plaintext for any chunks that completed
57
+ * (possibly empty). Tampering, reordering, and truncation surface as errors here.
58
+ */
59
+ push(data: Uint8Array): Uint8Array;
60
+ }
61
+
62
+ /**
63
+ * Streaming NCF-3 encryptor (misuse-resistant by construction): the random
64
+ * `nonce_prefix` is generated INSIDE Rust and chunk indexes are managed internally, so a
65
+ * JS-side bug can never cause nonce reuse or out-of-order sealing.
66
+ *
67
+ * Protocol (CRYPTO-FORMAT §3): construct with the file DEK and the total plaintext
68
+ * length, emit `header()` (32 bytes) first, `push()` plaintext in arbitrary slice sizes —
69
+ * each call returns any now-complete sealed NON-final chunks (possibly empty) — then call
70
+ * `finish()` exactly once for the remaining sealed bytes including the final chunk.
71
+ * `header || push outputs || finish output`, concatenated in order, is the complete
72
+ * stream. Call `free()` afterwards to release the wasm-side memory.
73
+ */
74
+ export class StreamEncryptor {
75
+ free(): void;
76
+ [Symbol.dispose](): void;
77
+ /**
78
+ * Total chunk count for this stream: `max(1, ceil(plaintext_len / chunk_size))`.
79
+ */
80
+ chunk_count(): number;
81
+ /**
82
+ * Flushes any buffered chunks plus the final chunk (sealed with `is_final = 0x01`).
83
+ * Errors if fewer than `plaintext_len` bytes were pushed. A second call returns an
84
+ * empty array (idempotent — mirrors the Rust engine's `finish`).
85
+ */
86
+ finish(): Uint8Array;
87
+ /**
88
+ * The 32 plaintext header bytes (magic/version/log2/plaintext_len/nonce_prefix).
89
+ * Emit these first, before any chunk output. On a resume handle these are the SAME
90
+ * bytes passed to `resumeFromHeader`.
91
+ */
92
+ header(): Uint8Array;
93
+ /**
94
+ * `dek` must be 32 bytes; `plaintext_len` a non-negative integer ≤ 2^53. Uses the
95
+ * production constructor only: fresh random nonce prefix, chunk_size_log2 = 22
96
+ * (4 MiB) — callers can never supply nonces or chunk sizes.
97
+ *
98
+ * `part_index` and `part_total` say WHERE this blob sits in the file (NCF-3 §4.1, defect
99
+ * A4). They go into the header and therefore into every chunk's AAD, so a part that is
100
+ * later served in another part's position fails authentication instead of decrypting into
101
+ * the wrong place. A whole file in one blob is part 0 of 1.
102
+ *
103
+ * The pair is validated HERE rather than left to Rust's debug assertion: an impossible
104
+ * placement panics inside the engine, and a panic across the wasm boundary aborts the
105
+ * worker rather than raising something the caller can handle.
106
+ */
107
+ constructor(dek: Uint8Array, plaintext_len: number, part_index: number, part_total: number);
108
+ /**
109
+ * Feeds plaintext in. Returns the sealed bytes (`ciphertext||tag` each) of any chunks
110
+ * that became complete — possibly empty. Errors if more than `plaintext_len` bytes
111
+ * are pushed in total.
112
+ */
113
+ push(data: Uint8Array): Uint8Array;
114
+ /**
115
+ * ☠️ RESUME RE-DERIVATION ONLY. Reconstructs an encryptor from a PERSISTED 72-byte NCF-3
116
+ * header so a cross-reload resume can re-derive a registered part's EXACT ciphertext.
117
+ * Validates the header like the parser (magic/version/chunk_size_log2/plaintext_len) and
118
+ * re-emits those same 32 header bytes; seeds the nonce prefix + chunk sizing from it and
119
+ * starts at chunk index 0.
120
+ *
121
+ * The caller MUST NOT transmit any output unless its Walrus blobId bit-matches the
122
+ * originally registered blobId — reusing `(DEK, nonce_prefix)` for DIFFERENT plaintext is
123
+ * catastrophic. This is NEVER a fresh-upload path (use the constructor, random nonce).
124
+ * See `ResumeEncryptor`'s safety note for the full rationale.
125
+ */
126
+ static resumeFromHeader(dek: Uint8Array, header: Uint8Array): StreamEncryptor;
127
+ }
128
+
129
+ /**
130
+ * The display string for a set of 20 raw account-code bytes.
131
+ */
132
+ export function account_code_display(code_bytes: Uint8Array): string;
133
+
134
+ /**
135
+ * Generates a fresh 160-bit account code and returns its display string
136
+ * (`XXXX-XXXX-…-XXXXC`). The bytes never leave the worker except as this one-time string.
137
+ */
138
+ export function account_code_generate(): string;
139
+
140
+ /**
141
+ * Parses+validates a user-entered account code (any spacing/case), returning the 20 raw
142
+ * bytes. Errors if the check symbol fails.
143
+ */
144
+ export function account_code_parse(input: string): Uint8Array;
145
+
146
+ /**
147
+ * Unpadded base64url of arbitrary bytes. The textual `accountId` is
148
+ * `b64_encode(account_id_16_bytes)`.
149
+ */
150
+ export function b64_encode(data: Uint8Array): string;
151
+
152
+ /**
153
+ * Derives the 32-byte wrapping key for a passphrase-protected "remember this device" record.
154
+ *
155
+ * `salt` is 16 bytes the CALLER generated fresh for that record and stores beside the
156
+ * ciphertext — a human-chosen passphrase must never share a salt with another user's (see
157
+ * `kdf::derive_device_wrap_key`). Errors on a short passphrase or a wrong-length salt rather
158
+ * than deriving something weak.
159
+ *
160
+ * The returned key is ordinary bytes: the browser imports it into WebCrypto to seal the record
161
+ * and drops it. It is NOT an account key and reaches nothing an account key reaches.
162
+ */
163
+ export function device_wrap_key(passphrase: Uint8Array, salt: Uint8Array): Uint8Array;
164
+
165
+ /**
166
+ * Decrypts and authenticates an envelope (`nonce||ct||tag`) under `key`, checking `aad`.
167
+ */
168
+ export function envelope_open(key: Uint8Array, aad: Uint8Array, envelope: Uint8Array): Uint8Array;
169
+
170
+ /**
171
+ * Encrypts `plaintext` under `key` with a FRESH random 24-byte nonce (production path).
172
+ */
173
+ export function envelope_seal(key: Uint8Array, aad: Uint8Array, plaintext: Uint8Array): Uint8Array;
174
+
175
+ /**
176
+ * A fresh random 32-byte file DEK (WebCrypto-backed).
177
+ */
178
+ export function generate_dek(): Uint8Array;
179
+
180
+ /**
181
+ * Chunk count derived from a validated header: `max(1, ceil(plaintext_len/chunk_size))`.
182
+ * Errors on a malformed header or a count beyond 2^53.
183
+ */
184
+ export function header_chunk_count(header: Uint8Array): number;
185
+
186
+ /**
187
+ * Chunk size in bytes from a validated header (`1 << chunk_size_log2`; 4 MiB in v1).
188
+ * Errors on a malformed header. Always a power of two, hence exact as a JS number.
189
+ */
190
+ export function header_chunk_size(header: Uint8Array): number;
191
+
192
+ /**
193
+ * Where this part sits in its file, and how many parts the file has (NCF-3 §4.1).
194
+ * Exposed so the download path can show and check placement without decrypting anything.
195
+ */
196
+ export function header_part_index(header: Uint8Array): number;
197
+
198
+ export function header_part_total(header: Uint8Array): number;
199
+
200
+ /**
201
+ * `plaintext_len` from a validated 32-byte header (u64 LE at offset 8). Errors on a
202
+ * malformed header, or on a declared length beyond 2^53 (not a JS-safe integer).
203
+ */
204
+ export function header_plaintext_len(header: Uint8Array): number;
205
+
206
+ /**
207
+ * Derives the account keys from the 20 raw account-code bytes (NCF-3 §1).
208
+ *
209
+ * Returns one concatenated buffer (`KDF_DERIVE_LEN` = 256 bytes) the caller slices:
210
+ * ```text
211
+ * 0.. 16 account_id public — the server's lookup key
212
+ * 16.. 48 auth_secret secret — sent to the server over TLS at login
213
+ * 48.. 80 data_key secret — wraps every file DEK; NEVER leaves the worker
214
+ * 80..112 file_list_key secret — opens the sealed drive index, and nothing else
215
+ * 112..144 share_kem_seed secret — X-Wing seed for private sharing (NCF-3 §5.1)
216
+ * 144..176 share_auth_secret secret — proves this account SENT a share (NCF-3 §5.5)
217
+ * 176..208 wallet_root secret — parent of EVERY wallet, including the first
218
+ * 208..224 share_address public — the address a user hands out to be shared with
219
+ * 224..256 share_sig_seed secret — ML-DSA-44 seed; its key IS the identity root (§5.2a)
220
+ * ```
221
+ * Every secret region above must be retained inside the crypto worker and never cross the
222
+ * postMessage boundary.
223
+ *
224
+ * ⚠ **This layout only ever grows at the TAIL.** `share_sig_seed` was appended in 2026-08-02
225
+ * rather than filed beside the other two share secrets, where it would read better, because
226
+ * inserting it there would shift `wallet_root` and `share_address` and every constant on the
227
+ * JS side would be silently wrong about which 32 bytes it was holding. Readability loses to
228
+ * that, every time.
229
+ *
230
+ * `share_address` is included even though it is not an HKDF output: since NCF-3 it is the
231
+ * FINGERPRINT of the share identity's root (§5.2), and computing it here means the browser never
232
+ * has to decide for itself which key an address belongs to.
233
+ */
234
+ export function kdf_derive(code_bytes: Uint8Array): Uint8Array;
235
+
236
+ /**
237
+ * The name this account's recovery manifest is stored under inside a quilt (NCF-3 §2.5).
238
+ *
239
+ * Public, and deliberately not secret-looking: it is a v4-shaped UUID exactly like the random
240
+ * per-item identifiers beside it in the same quilt. What it buys is that a recovery holding only
241
+ * an account code can compute the one name to ask a public aggregator for — no NMTS server, no
242
+ * saved file, no prior knowledge of the account's data.
243
+ *
244
+ * Takes `dataKey` rather than the account code because that key already lives in the worker; the
245
+ * code does not, and moving it here to hash it would put it somewhere it has no reason to be.
246
+ */
247
+ export function recovery_patch_name(data_key: Uint8Array): string;
248
+
249
+ /**
250
+ * SHA-256 using the same `sha2` implementation as the Rust engine.
251
+ */
252
+ export function sha256(data: Uint8Array): Uint8Array;
253
+
254
+ /**
255
+ * The display form of a share address (`kdf_derive` bytes 208..224):
256
+ * `XXXXXXXXX-XXXXXXXXX-XXXXXXXXC` — Crockford Base32 with a trailing check symbol.
257
+ */
258
+ export function share_address_display(share_address: Uint8Array): string;
259
+
260
+ /**
261
+ * The 16-byte share ADDRESS a published identity fingerprints to (NCF-3 §5.2).
262
+ *
263
+ * ⚠ **It parses the whole bundle first**, which means an identity whose self-signature does not
264
+ * verify, whose version is unknown, or whose X25519 halves are degenerate has no address at all
265
+ * as far as this function is concerned — it throws instead of returning one. Returning an address
266
+ * for a bundle nothing vouches for would be handing the caller a value that looks checkable and
267
+ * is not.
268
+ *
269
+ * Exposed so the browser can show a sender WHY a share was refused: the address it looked up and
270
+ * the address the returned identity actually belongs to are different values, and saying so is
271
+ * more useful than "failed".
272
+ */
273
+ export function share_address_of(recipient_public: Uint8Array): Uint8Array;
274
+
275
+ /**
276
+ * Parses a user-entered share address (any spacing/case) back to its 16 bytes, verifying the
277
+ * check symbol. A typo fails HERE, in the browser, before any lookup reaches the server.
278
+ */
279
+ export function share_address_parse(input: string): Uint8Array;
280
+
281
+ /**
282
+ * The sender address an envelope CLAIMS, so the caller knows whose identity to fetch.
283
+ *
284
+ * ⚠ A claim, not a fact, until `share_unwrap_dek` succeeds — the address is bound into the
285
+ * wrapping key, so an envelope that opens is one whose claim was true.
286
+ */
287
+ export function share_claimed_sender(envelope: Uint8Array): Uint8Array;
288
+
289
+ /**
290
+ * The 4989-byte PUBLIC share identity, built from the three secrets at `kdf_derive` bytes
291
+ * 112..176 and 224..256 (KEM seed, auth secret, signing seed).
292
+ *
293
+ * Layout: `version(1) || derivation_index(4) || pk_sig(1312) || key_epoch(4) || pk_kem(1216) ||
294
+ * pk_auth(32) || self_sig(2420)`. This is the only part of the identity the server holds, the
295
+ * address is the fingerprint of its ROOT, and the self-signature is what makes every key after
296
+ * the root attributable to that address (NCF-3 §5.2a).
297
+ *
298
+ * ⚠ The bytes are the same on every device the account code is entered on — deterministic
299
+ * signing, never hedged — which is what lets the server hold one bundle per account
300
+ * first-writer-wins without rejecting the account's own second device.
301
+ */
302
+ export function share_public_key(share_kem_seed: Uint8Array, share_auth_secret: Uint8Array, share_sig_seed: Uint8Array): Uint8Array;
303
+
304
+ /**
305
+ * Unwraps a share envelope addressed to us, returning the 32-byte file DEK.
306
+ *
307
+ * An envelope meant for somebody else fails exactly like a tampered one — the recipient's key is
308
+ * bound into the wrapping key, so there is nothing to tell the two cases apart. Since NCF-3 §5.3
309
+ * the same is true of an envelope stored beside a substituted name, digest or item id: the row is
310
+ * bound in too, and a rewritten row is indistinguishable from a forged envelope.
311
+ */
312
+ export function share_unwrap_dek(share_kem_seed: Uint8Array, share_auth_secret: Uint8Array, share_sig_seed: Uint8Array, sender_public: Uint8Array, envelope: Uint8Array, item_id: string, name_share_ct: Uint8Array, content_hash_share_ct: Uint8Array): Uint8Array;
313
+
314
+ /**
315
+ * Wraps a file DEK for ONE recipient, given the public key the server returned AND the address
316
+ * the sender was actually given.
317
+ *
318
+ * ⚠ **Both arguments are required on purpose.** The key is checked against the address before
319
+ * anything is encrypted to it, so a server that substitutes its own key is refused here rather
320
+ * than silently handed a readable DEK (NCF-3 §5.2, defect A1). There is deliberately no
321
+ * two-argument form.
322
+ *
323
+ * ⚠ **The last three arguments are the row this envelope will be stored in** — the item id and
324
+ * the already-sealed name and content digest — and they are required for the same kind of reason
325
+ * (NCF-3 §5.3, defect A6). They are hashed into the wrapping key, so an envelope kept next to
326
+ * different columns stops opening. **This therefore has to be called AFTER `share_seal_name` and
327
+ * the re-sealed digest, not before.**
328
+ *
329
+ * Returns the 1240-byte share envelope (`sender_address(16) || kem_ciphertext(1120) || sealed
330
+ * DEK(104)`). A fresh encapsulation is drawn per call, so wrapping the same DEK for the same
331
+ * recipient twice produces unrelated bytes — the server cannot tell two shares went to the same
332
+ * person.
333
+ */
334
+ export function share_wrap_dek(sender_auth_secret: Uint8Array, sender_sig_seed: Uint8Array, recipient_public: Uint8Array, recipient_address: Uint8Array, dek: Uint8Array, item_id: string, name_share_ct: Uint8Array, content_hash_share_ct: Uint8Array): Uint8Array;
335
+
336
+ /**
337
+ * Decrypts a whole NCF-3 stream under the file DEK, verifying framing/anti-tamper.
338
+ */
339
+ export function stream_decrypt_all(dek: Uint8Array, stream: Uint8Array): Uint8Array;
340
+
341
+ /**
342
+ * Decrypts ONE chunk for random access (ranged reads), independent of any stream state.
343
+ *
344
+ * `header` is the 72-byte stream header; `chunk_index` the zero-based chunk index (non-negative
345
+ * integer); `ciphertext` must be EXACTLY that chunk's bytes — chunk `i` starts at stream
346
+ * offset `72 + i·(chunk_size+16)` and is `chunk_plaintext_len(i) + 16` bytes. `is_final`
347
+ * is derived from the header INSIDE Rust, so callers cannot mis-authenticate finality;
348
+ * a wrongly sized or out-of-range slice is rejected.
349
+ *
350
+ * `expected_part_index` / `expected_part_total` are WHERE THE CALLER BELIEVES IT IS READING
351
+ * (§4.1, defect A4) and are required, not optional. A ranged reader receives the header and the
352
+ * chunk in the SAME response, so the AAD it authenticates against is self-consistent whichever
353
+ * part the server actually served — and every part of a file is sealed under one DEK, so the
354
+ * wrong part opens cleanly with a valid tag. A whole file in one blob is `0, 1`. Take these from
355
+ * the position the byte range was computed FROM; reading them back out of `header` compares a
356
+ * value with itself and restores the hole.
357
+ */
358
+ export function stream_decrypt_chunk(dek: Uint8Array, header: Uint8Array, expected_part_index: number, expected_part_total: number, chunk_index: number, ciphertext: Uint8Array): Uint8Array;
359
+
360
+ /**
361
+ * Encrypts `plaintext` into a whole NCF-3 stream under `dek` (production: random nonce prefix).
362
+ */
363
+ export function stream_encrypt_all(dek: Uint8Array, plaintext: Uint8Array): Uint8Array;
364
+
365
+ /**
366
+ * Checks that a multi-part file's headers are the complete set, in order, of one file
367
+ * (NCF-3 §4.1, defect A4). `headers` is the parts' headers CONCATENATED in the order they
368
+ * will be decrypted — `part_total × 72` bytes.
369
+ *
370
+ * ⚠ Order is the whole point: the check is "the i-th header says part i", not "every index
371
+ * appears once". Sorting the parts by their own claimed index before calling this would make
372
+ * it pass on any permutation, which is exactly the attack it exists to catch. Pass them in
373
+ * the order the download will actually consume, straight from the server's list.
374
+ */
375
+ export function verify_part_set(headers: Uint8Array): void;
376
+
377
+ /**
378
+ * `SHA-256(normalize(input))` — the voucher redemption hash for arbitrary user input.
379
+ */
380
+ export function voucher_hash_from_input(input: string): Uint8Array;
381
+
382
+ /**
383
+ * Derives the Ed25519 seed for wallet number `index` from the 32-byte `wallet_root`.
384
+ *
385
+ * EVERY wallet comes from here, including wallet 0. NCF-2 gave the first wallet its own
386
+ * derivation off the account PRK because it already existed on chain and could not move; NCF-3
387
+ * deletes that exception, so there is one rule and no index this function refuses.
388
+ */
389
+ export function wallet_seed_for(wallet_root: Uint8Array, index: number): Uint8Array;
390
+
391
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
392
+
393
+ export interface InitOutput {
394
+ readonly memory: WebAssembly.Memory;
395
+ readonly __wbg_sha256hasher_free: (a: number, b: number) => void;
396
+ readonly __wbg_streamdecryptor_free: (a: number, b: number) => void;
397
+ readonly __wbg_streamencryptor_free: (a: number, b: number) => void;
398
+ readonly account_code_display: (a: number, b: number) => [number, number, number, number];
399
+ readonly account_code_generate: () => [number, number];
400
+ readonly account_code_parse: (a: number, b: number) => [number, number, number, number];
401
+ readonly b64_encode: (a: number, b: number) => [number, number];
402
+ readonly device_wrap_key: (a: number, b: number, c: number, d: number) => [number, number, number, number];
403
+ readonly envelope_open: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
404
+ readonly envelope_seal: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
405
+ readonly generate_dek: () => [number, number];
406
+ readonly header_chunk_count: (a: number, b: number) => [number, number, number];
407
+ readonly header_chunk_size: (a: number, b: number) => [number, number, number];
408
+ readonly header_part_index: (a: number, b: number) => [number, number, number];
409
+ readonly header_part_total: (a: number, b: number) => [number, number, number];
410
+ readonly header_plaintext_len: (a: number, b: number) => [number, number, number];
411
+ readonly kdf_derive: (a: number, b: number) => [number, number, number, number];
412
+ readonly recovery_patch_name: (a: number, b: number) => [number, number, number, number];
413
+ readonly sha256: (a: number, b: number) => [number, number];
414
+ readonly sha256hasher_finalize: (a: number) => [number, number, number, number];
415
+ readonly sha256hasher_new: () => number;
416
+ readonly sha256hasher_update: (a: number, b: number, c: number) => [number, number];
417
+ readonly share_address_display: (a: number, b: number) => [number, number, number, number];
418
+ readonly share_address_of: (a: number, b: number) => [number, number, number, number];
419
+ readonly share_address_parse: (a: number, b: number) => [number, number, number, number];
420
+ readonly share_claimed_sender: (a: number, b: number) => [number, number, number, number];
421
+ readonly share_public_key: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number, number, number];
422
+ readonly share_unwrap_dek: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number) => [number, number, number, number];
423
+ readonly share_wrap_dek: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number) => [number, number, number, number];
424
+ readonly stream_decrypt_all: (a: number, b: number, c: number, d: number) => [number, number, number, number];
425
+ readonly stream_decrypt_chunk: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number) => [number, number, number, number];
426
+ readonly stream_encrypt_all: (a: number, b: number, c: number, d: number) => [number, number, number, number];
427
+ readonly streamdecryptor_finish: (a: number) => [number, number];
428
+ readonly streamdecryptor_new: (a: number, b: number, c: number, d: number) => [number, number, number];
429
+ readonly streamdecryptor_push: (a: number, b: number, c: number) => [number, number, number, number];
430
+ readonly streamencryptor_chunk_count: (a: number) => number;
431
+ readonly streamencryptor_finish: (a: number) => [number, number, number, number];
432
+ readonly streamencryptor_header: (a: number) => [number, number];
433
+ readonly streamencryptor_new: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
434
+ readonly streamencryptor_push: (a: number, b: number, c: number) => [number, number, number, number];
435
+ readonly streamencryptor_resumeFromHeader: (a: number, b: number, c: number, d: number) => [number, number, number];
436
+ readonly verify_part_set: (a: number, b: number) => [number, number];
437
+ readonly voucher_hash_from_input: (a: number, b: number) => [number, number];
438
+ readonly wallet_seed_for: (a: number, b: number, c: number) => [number, number, number, number];
439
+ readonly __wbindgen_exn_store: (a: number) => void;
440
+ readonly __externref_table_alloc: () => number;
441
+ readonly __wbindgen_externrefs: WebAssembly.Table;
442
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
443
+ readonly __externref_table_dealloc: (a: number) => void;
444
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
445
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
446
+ readonly __wbindgen_start: () => void;
447
+ }
448
+
449
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
450
+
451
+ /**
452
+ * Instantiates the given `module`, which can either be bytes or
453
+ * a precompiled `WebAssembly.Module`.
454
+ *
455
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
456
+ *
457
+ * @returns {InitOutput}
458
+ */
459
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
460
+
461
+ /**
462
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
463
+ * for everything else, calls `WebAssembly.instantiate` directly.
464
+ *
465
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
466
+ *
467
+ * @returns {Promise<InitOutput>}
468
+ */
469
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;