sealkeep 0.9.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (274) hide show
  1. package/ARCHITECTURE.md +163 -14
  2. package/CHANGELOG.md +252 -1
  3. package/CONTROL_PLANE.md +2 -2
  4. package/LICENSE +1 -1
  5. package/README.md +108 -22
  6. package/THIRD_PARTY.md +2 -2
  7. package/THREAT_MODEL.md +23 -4
  8. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/chunk-access.d.ts +26 -4
  9. package/dist/packages/sealkeep-crypto/src/chunk-access.js +219 -0
  10. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/envelope.d.ts +11 -1
  11. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/envelope.js +58 -21
  12. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/format.d.ts +2 -2
  13. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/index.d.ts +1 -0
  14. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/index.js +1 -0
  15. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/recipients.d.ts +1 -0
  16. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/recipients.js +53 -13
  17. package/dist/packages/sealkeep-crypto/src/squeeze.d.ts +6 -0
  18. package/dist/packages/sealkeep-crypto/src/squeeze.js +39 -0
  19. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/stream.d.ts +36 -3
  20. package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/stream.js +196 -37
  21. package/dist/site/index.html +1808 -1904
  22. package/dist/site/llms.txt +67 -0
  23. package/dist/site/trust/architecture-data-flow.html +53 -0
  24. package/dist/site/trust/audit-roadmap.html +37 -0
  25. package/dist/site/trust/deployment-responsibility.html +11 -0
  26. package/dist/site/trust/dpa-sample.html +30 -0
  27. package/dist/site/trust/release-provenance.html +21 -0
  28. package/dist/site/trust/subprocessors.html +15 -0
  29. package/dist/site/trust/threat-model.html +34 -0
  30. package/dist/site/trust/toms.html +41 -0
  31. package/dist/site/trust-document.css +32 -0
  32. package/dist/site/trust.html +73 -0
  33. package/dist/site/visual/assets/index-8Nxnkc7o.js +207 -0
  34. package/dist/site/visual/assets/index-oxLy1bpy.css +1 -0
  35. package/dist/site/visual/index.html +18 -0
  36. package/dist/site.zip +0 -0
  37. package/dist/src/activity.d.ts +9 -0
  38. package/dist/src/activity.js +90 -1
  39. package/dist/src/adapters.d.ts +175 -5
  40. package/dist/src/adapters.js +961 -73
  41. package/dist/src/agent-context.d.ts +135 -0
  42. package/dist/src/agent-context.js +1059 -0
  43. package/dist/src/archive-copies.d.ts +47 -0
  44. package/dist/src/archive-copies.js +179 -0
  45. package/dist/src/audit.d.ts +1 -1
  46. package/dist/src/audit.js +29 -4
  47. package/dist/src/autopilot.d.ts +52 -7
  48. package/dist/src/autopilot.js +143 -25
  49. package/dist/src/background-bandwidth.d.ts +46 -0
  50. package/dist/src/background-bandwidth.js +301 -0
  51. package/dist/src/background-cpu.d.ts +82 -0
  52. package/dist/src/background-cpu.js +212 -0
  53. package/dist/src/background-worker-error.d.ts +12 -0
  54. package/dist/src/background-worker-error.js +18 -0
  55. package/dist/src/branding.d.ts +24 -1
  56. package/dist/src/branding.js +31 -1
  57. package/dist/src/bridge.d.ts +233 -0
  58. package/dist/src/bridge.js +604 -0
  59. package/dist/src/byte-stream.d.ts +91 -0
  60. package/dist/src/byte-stream.js +385 -0
  61. package/dist/src/chunk-store.d.ts +41 -8
  62. package/dist/src/chunk-store.js +161 -65
  63. package/dist/src/cli.js +1698 -163
  64. package/dist/src/cloud.d.ts +841 -31
  65. package/dist/src/cloud.js +3196 -277
  66. package/dist/src/context-background.d.ts +37 -0
  67. package/dist/src/context-background.js +309 -0
  68. package/dist/src/context-drain-child.d.ts +1 -0
  69. package/dist/src/context-drain-child.js +98 -0
  70. package/dist/src/context-reader.d.ts +118 -0
  71. package/dist/src/context-reader.js +447 -0
  72. package/dist/src/control-plane/auth.d.ts +32 -4
  73. package/dist/src/control-plane/auth.js +85 -24
  74. package/dist/src/control-plane/server.js +19 -6
  75. package/dist/src/control-plane.d.ts +17 -1
  76. package/dist/src/control-plane.js +32 -6
  77. package/dist/src/crypto.d.ts +1 -1
  78. package/dist/src/crypto.js +5 -5
  79. package/dist/src/daemon-lease.d.ts +70 -0
  80. package/dist/src/daemon-lease.js +420 -0
  81. package/dist/src/daemon.d.ts +94 -1
  82. package/dist/src/daemon.js +1082 -105
  83. package/dist/src/darwin-service-policy.d.ts +41 -0
  84. package/dist/src/darwin-service-policy.js +60 -0
  85. package/dist/src/dashboard-cli.js +15 -15
  86. package/dist/src/device-authorization.d.ts +37 -0
  87. package/dist/src/device-authorization.js +199 -0
  88. package/dist/src/device-enrollment.d.ts +91 -0
  89. package/dist/src/device-enrollment.js +349 -0
  90. package/dist/src/disk.d.ts +17 -12
  91. package/dist/src/disk.js +43 -17
  92. package/dist/src/doctor.d.ts +35 -1
  93. package/dist/src/doctor.js +332 -41
  94. package/dist/src/durable-ticket-lock.d.ts +24 -0
  95. package/dist/src/durable-ticket-lock.js +232 -0
  96. package/dist/src/enroll.d.ts +1 -1
  97. package/dist/src/enroll.js +13 -7
  98. package/dist/src/env.d.ts +10 -1
  99. package/dist/src/env.js +11 -3
  100. package/dist/src/errors.d.ts +8 -8
  101. package/dist/src/errors.js +6 -6
  102. package/dist/src/flush.d.ts +12 -0
  103. package/dist/src/flush.js +37 -0
  104. package/dist/src/heartbeat.d.ts +86 -12
  105. package/dist/src/heartbeat.js +415 -29
  106. package/dist/src/index-background-watchdog.d.ts +1 -0
  107. package/dist/src/index-background-watchdog.js +94 -0
  108. package/dist/src/index-background-work.d.ts +21 -0
  109. package/dist/src/index-background-work.js +25 -0
  110. package/dist/src/index-background.d.ts +64 -0
  111. package/dist/src/index-background.js +394 -0
  112. package/dist/src/index-build-child.d.ts +1 -0
  113. package/dist/src/index-build-child.js +109 -0
  114. package/dist/src/index-manifest.d.ts +52 -0
  115. package/dist/src/index-manifest.js +444 -0
  116. package/dist/src/index-publication-proof.d.ts +84 -0
  117. package/dist/src/index-publication-proof.js +380 -0
  118. package/dist/src/index-publication-state.d.ts +149 -0
  119. package/dist/src/index-publication-state.js +696 -0
  120. package/dist/src/index-publication-verifier.d.ts +89 -0
  121. package/dist/src/index-publication-verifier.js +341 -0
  122. package/dist/src/index-publish.d.ts +62 -0
  123. package/dist/src/index-publish.js +540 -0
  124. package/dist/src/index-scratch-cleanup.d.ts +19 -0
  125. package/dist/src/index-scratch-cleanup.js +166 -0
  126. package/dist/src/index-segment-types.d.ts +132 -0
  127. package/dist/src/index-segment-types.js +21 -0
  128. package/dist/src/index-segments.d.ts +9 -0
  129. package/dist/src/index-segments.js +516 -0
  130. package/dist/src/index-store.d.ts +123 -0
  131. package/dist/src/index-store.js +495 -0
  132. package/dist/src/index-sync.d.ts +91 -15
  133. package/dist/src/index-sync.js +286 -53
  134. package/dist/src/index-upgrade-publication.d.ts +30 -0
  135. package/dist/src/index-upgrade-publication.js +179 -0
  136. package/dist/src/integration-manager.d.ts +32 -0
  137. package/dist/src/integration-manager.js +394 -0
  138. package/dist/src/leakscan.js +1 -1
  139. package/dist/src/local-api.d.ts +56 -15
  140. package/dist/src/local-api.js +4979 -541
  141. package/dist/src/machine-settings.d.ts +51 -0
  142. package/dist/src/machine-settings.js +166 -0
  143. package/dist/src/managed-chunks.d.ts +5 -2
  144. package/dist/src/managed-chunks.js +14 -14
  145. package/dist/src/mcp-install.d.ts +11 -9
  146. package/dist/src/mcp-install.js +73 -28
  147. package/dist/src/mcp-workspace.d.ts +18 -0
  148. package/dist/src/mcp-workspace.js +50 -0
  149. package/dist/src/mcp.js +294 -25
  150. package/dist/src/migrate.js +27 -21
  151. package/dist/src/notify.d.ts +1 -1
  152. package/dist/src/notify.js +5 -5
  153. package/dist/src/offload.d.ts +201 -14
  154. package/dist/src/offload.js +1848 -140
  155. package/dist/src/onboarding.d.ts +8 -1
  156. package/dist/src/onboarding.js +4 -4
  157. package/dist/src/packages.d.ts +2 -2
  158. package/dist/src/packages.js +10 -2
  159. package/dist/src/passkey.d.ts +0 -1
  160. package/dist/src/passkey.js +2 -7
  161. package/dist/src/password-lock.d.ts +2 -2
  162. package/dist/src/password-lock.js +6 -6
  163. package/dist/src/paths.d.ts +2 -0
  164. package/dist/src/paths.js +2 -0
  165. package/dist/src/presence.d.ts +86 -0
  166. package/dist/src/presence.js +240 -0
  167. package/dist/src/progress-deadline.d.ts +21 -0
  168. package/dist/src/progress-deadline.js +91 -0
  169. package/dist/src/project-repair.d.ts +55 -0
  170. package/dist/src/project-repair.js +131 -0
  171. package/dist/src/providers/gcs.d.ts +28 -7
  172. package/dist/src/providers/gcs.js +35 -24
  173. package/dist/src/providers/gdrive.d.ts +71 -8
  174. package/dist/src/providers/gdrive.js +223 -50
  175. package/dist/src/providers/index.d.ts +11 -3
  176. package/dist/src/providers/index.js +30 -10
  177. package/dist/src/providers/s3.d.ts +30 -8
  178. package/dist/src/providers/s3.js +41 -30
  179. package/dist/src/providers/safe-storage-fetch.d.ts +12 -0
  180. package/dist/src/providers/safe-storage-fetch.js +72 -0
  181. package/dist/src/queue.d.ts +136 -19
  182. package/dist/src/queue.js +862 -96
  183. package/dist/src/reclaim-transaction.d.ts +156 -0
  184. package/dist/src/reclaim-transaction.js +1027 -0
  185. package/dist/src/recovery-codes.d.ts +32 -0
  186. package/dist/src/recovery-codes.js +338 -0
  187. package/dist/src/recovery.js +12 -9
  188. package/dist/src/rehydrate.d.ts +25 -22
  189. package/dist/src/rehydrate.js +319 -23
  190. package/dist/src/restore.d.ts +57 -4
  191. package/dist/src/restore.js +272 -36
  192. package/dist/src/resume-stub.d.ts +92 -0
  193. package/dist/src/resume-stub.js +417 -0
  194. package/dist/src/retention.d.ts +98 -7
  195. package/dist/src/retention.js +1066 -62
  196. package/dist/src/rotate.js +3 -3
  197. package/dist/src/search.d.ts +566 -8
  198. package/dist/src/search.js +5940 -297
  199. package/dist/src/secrets.d.ts +51 -7
  200. package/dist/src/secrets.js +316 -24
  201. package/dist/src/service.d.ts +49 -11
  202. package/dist/src/service.js +776 -35
  203. package/dist/src/share.js +3 -3
  204. package/dist/src/shared-spaces.d.ts +98 -0
  205. package/dist/src/shared-spaces.js +214 -0
  206. package/dist/src/source-reader.d.ts +73 -0
  207. package/dist/src/source-reader.js +715 -0
  208. package/dist/src/spool.d.ts +1 -1
  209. package/dist/src/spool.js +1 -1
  210. package/dist/src/start-tui.js +2 -1
  211. package/dist/src/start.js +2 -2
  212. package/dist/src/storage-endpoint.d.ts +21 -0
  213. package/dist/src/storage-endpoint.js +122 -0
  214. package/dist/src/storage-setup.js +12 -12
  215. package/dist/src/storage-targets.d.ts +109 -6
  216. package/dist/src/storage-targets.js +975 -67
  217. package/dist/src/stream-to-cloud.d.ts +5 -1
  218. package/dist/src/stream-to-cloud.js +34 -14
  219. package/dist/src/sync-rules.d.ts +31 -6
  220. package/dist/src/sync-rules.js +153 -14
  221. package/dist/src/team-backfill-scheduling.d.ts +8 -0
  222. package/dist/src/team-backfill-scheduling.js +33 -0
  223. package/dist/src/team-backfill.d.ts +116 -0
  224. package/dist/src/team-backfill.js +1429 -0
  225. package/dist/src/team-index-cache.d.ts +16 -0
  226. package/dist/src/team-index-cache.js +152 -0
  227. package/dist/src/team-offboarding.d.ts +38 -0
  228. package/dist/src/team-offboarding.js +1043 -0
  229. package/dist/src/team-presence.d.ts +127 -0
  230. package/dist/src/team-presence.js +904 -0
  231. package/dist/src/team-publication-policy.d.ts +20 -0
  232. package/dist/src/team-publication-policy.js +140 -0
  233. package/dist/src/team-realtime.d.ts +68 -0
  234. package/dist/src/team-realtime.js +816 -0
  235. package/dist/src/team-source-facts-cache.d.ts +23 -0
  236. package/dist/src/team-source-facts-cache.js +255 -0
  237. package/dist/src/trash.d.ts +1 -1
  238. package/dist/src/trash.js +2 -2
  239. package/dist/src/tui.js +11 -12
  240. package/dist/src/types.d.ts +173 -7
  241. package/dist/src/types.js +20 -0
  242. package/dist/src/ui-server.d.ts +163 -35
  243. package/dist/src/ui-server.js +712 -72
  244. package/dist/src/ui.d.ts +1 -2
  245. package/dist/src/ui.js +1 -2
  246. package/dist/src/upload.d.ts +27 -0
  247. package/dist/src/upload.js +383 -43
  248. package/dist/src/vault.d.ts +226 -30
  249. package/dist/src/vault.js +1776 -192
  250. package/dist/src/watcher.d.ts +7 -1
  251. package/dist/src/watcher.js +198 -55
  252. package/dist/src/worker.d.ts +27 -3
  253. package/dist/src/worker.js +274 -55
  254. package/package.json +33 -12
  255. package/scripts/native-reboot-rehearsal.mjs +90 -0
  256. package/web/app.js +6032 -343
  257. package/web/bootstrap.js +17 -0
  258. package/web/index.html +255 -57
  259. package/web/rail.js +317 -40
  260. package/web/retention.html +2 -2
  261. package/web/rules-view.js +188 -16
  262. package/web/sessions-view.js +485 -62
  263. package/web/sessions.html +2 -2
  264. package/web/setup-api.js +152 -29
  265. package/web/setup-logic.js +68 -9
  266. package/web/setup.html +113 -44
  267. package/web/setup.js +604 -71
  268. package/web/style.css +513 -98
  269. package/dist/packages/vaultline-crypto/src/chunk-access.js +0 -93
  270. /package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/aead.d.ts +0 -0
  271. /package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/aead.js +0 -0
  272. /package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/format.js +0 -0
  273. /package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/sha256-stream.d.ts +0 -0
  274. /package/dist/packages/{vaultline-crypto → sealkeep-crypto}/src/sha256-stream.js +0 -0
@@ -1,23 +1,41 @@
1
- import { type Recipient } from "../packages/vaultline-crypto/src/index.js";
1
+ import { type Recipient } from "../packages/sealkeep-crypto/src/index.js";
2
2
  import { type ArchiveRecord, type ArchiveRecordV2, type VaultConfig } from "./types.js";
3
3
  import type { ProviderConfig } from "./control-plane.js";
4
+ export declare function withoutArchiveRecordWarnings<T>(operation: () => Promise<T>): Promise<T>;
4
5
  /** Bumped when the adapter's preservation behaviour changes, recorded in every envelope. */
6
+ export type RecordWriteOperations = {
7
+ /** Test seam for proving the durability boundary; production uses fsync(2). */
8
+ syncFile?: (path: string) => Promise<void>;
9
+ rename?: (from: string, to: string) => Promise<void>;
10
+ syncDirectory?: (path: string) => Promise<void>;
11
+ };
5
12
  /**
6
13
  * Writes one archive record atomically.
7
14
  *
8
- * Written to a temporary file beside the target and renamed into place, so a
9
- * crash never leaves a half-written record that would strand an archive. This
10
- * lived as three byte-identical private copies in upload, migrate and
11
- * retention; a fourth was about to be added for the managed push path.
15
+ * The complete temporary file is fsynced before rename, then the archive
16
+ * directory is fsynced after rename. Atomic visibility alone is not enough for
17
+ * source reclaim: the purge journal must never become more durable than the
18
+ * record saying where the recoverable archive lives.
19
+ */
20
+ export declare function writeRecord(root: string, record: ArchiveRecord, operations?: RecordWriteOperations): Promise<void>;
21
+ /**
22
+ * Serialize a read/modify/write of one archive record across the daemon, CLI,
23
+ * dashboard and hooks. Atomic rename prevents torn JSON, but by itself it
24
+ * still lets two valid stale documents overwrite one another (for example an
25
+ * upload adding a remote copy while retention marks the source reclaimed).
12
26
  */
13
- export declare function writeRecord(root: string, record: ArchiveRecord): Promise<void>;
27
+ export declare function mutateArchiveRecord(root: string, archiveId: string, change: (current: ArchiveRecord) => ArchiveRecord | Promise<ArchiveRecord>, options?: {
28
+ initial?: ArchiveRecord;
29
+ }): Promise<ArchiveRecord>;
14
30
  export declare const ADAPTER_VERSION = "1";
15
31
  export declare const CONFIG_VERSION = 1;
16
32
  /**
17
- * ~/.sealkeep for new vaults; an existing ~/.Sealkeep keeps working forever —
18
- * the rebrand must never strand a vault that predates it.
33
+ * ~/.sealkeep for new vaults; an existing ~/.vaultline keeps working forever.
34
+ * A unique initialized vault named by owned integrations is the same vault a
35
+ * bare CLI/UI/MCP process must use. Multiple initialized candidates are never
36
+ * guessed between: explicit `--data-dir` is then required.
19
37
  */
20
- export declare const defaultDataDir: () => string;
38
+ export declare const defaultDataDir: (home?: string, environment?: NodeJS.ProcessEnv) => string;
21
39
  /**
22
40
  * Reads and version-gates the vault config. A config written by a newer build is
23
41
  * refused rather than silently reinterpreted; migrations attach here when v2 lands.
@@ -34,7 +52,14 @@ export declare function vaultStatus(dataDir: string): Promise<{
34
52
  region?: string;
35
53
  } | undefined;
36
54
  archiveCount: number;
55
+ sessionCount: number;
37
56
  archivedBytes: number;
57
+ sealedBytes: number;
58
+ cloudArchiveCount: number;
59
+ incompleteChainCount: number;
60
+ blockedUploadCount: number;
61
+ pendingUploadCount: number;
62
+ pendingUploadBytes: number;
38
63
  }>;
39
64
  export declare function configureRemoteStorage(dataDir: string, remoteStorage: ProviderConfig): Promise<VaultConfig>;
40
65
  export declare function initialize(dataDir: string, providedPhrase?: string, opts?: {
@@ -57,7 +82,7 @@ export declare function initialize(dataDir: string, providedPhrase?: string, opt
57
82
  * 3 MB reports the 3 MB archive. Nothing is returned when the file was
58
83
  * rewritten, truncated, or has never been archived.
59
84
  */
60
- export declare function provenAppendOffset(archives: readonly ArchiveRecord[], sourcePath: string, currentBytes: number): Promise<{
85
+ export declare function provenAppendOffset(archives: readonly ArchiveRecord[], sourcePath: string, currentBytes: number, onActivity?: (bytesRead: number) => void, signal?: AbortSignal, onYield?: () => void | Promise<void>): Promise<{
61
86
  archiveId: string;
62
87
  bytes: number;
63
88
  } | null>;
@@ -75,6 +100,9 @@ export type ArchiveDelta = {
75
100
  export type DeltaArchiveRecord = ArchiveRecordV2 & {
76
101
  delta: ArchiveDelta;
77
102
  };
103
+ /** Bound replay work for an agent that appends forever. The next snapshot
104
+ * after this many physical links is sealed whole and becomes a new base. */
105
+ export declare const MAX_DELTA_CHAIN_LINKS = 16;
78
106
  /**
79
107
  * The delta pointer on a record, when the record is a delta archive.
80
108
  *
@@ -86,26 +114,47 @@ export declare function deltaOf(record: ArchiveRecord): ArchiveDelta | null;
86
114
  export type ArchiveResult = ArchiveRecord & {
87
115
  deduplicated: boolean;
88
116
  };
89
- /**
90
- * Seals one transcript, reading and writing a chunk at a time.
91
- *
92
- * An existing archive is returned unchanged when the same source bytes are
93
- * archived again, so a duplicate lifecycle event costs a hash rather than an
94
- * archive.
95
- *
96
- * `hooks.delta` opts in to incremental sealing: when the newest archive of
97
- * this path is a *proven* prefix of the live file, only the appended range is
98
- * sealed and the record carries a `delta` pointer to its base. Off by default
99
- * so every existing caller keeps writing complete, standalone archives; the
100
- * queue worker turns it on, because re-sealing a growing session whole on
101
- * every snapshot is exactly how 4 GB of transcript became 40 GB of storage.
102
- */
103
117
  export declare function archiveFile(dataDir: string, sourcePath: string, rawPhrase: string, agent?: string, hooks?: {
104
118
  onProgress?: (bytesRead: number) => void;
119
+ /** Internal liveness signal while validating a prior snapshot; unlike onProgress it does not describe bytes being sealed. */
120
+ onActivity?: (bytesRead: number) => void;
121
+ /** Cancels lock waiting, hashing, compression, and the unpublished partial. */
122
+ signal?: AbortSignal;
123
+ /** Internal cooperative scheduler used by unattended/background sealing. */
124
+ onYield?: () => void | Promise<void>;
105
125
  delta?: boolean;
106
126
  chunkBytes?: number;
107
127
  /** Which project this session belongs to — decides which members are wrapped in. */
108
128
  project?: string | null;
129
+ /** Stable identity for access decisions. When supplied, label fallback is forbidden. */
130
+ projectKey?: string | null;
131
+ teamRecipients?: Recipient[];
132
+ /**
133
+ * Whole-file zstd instead of per-chunk gzip: 59x rather than 2x on a
134
+ * transcript, because the duplicate screenshots this collapses sit megabytes
135
+ * apart and a 4 MB window never sees them.
136
+ *
137
+ * Not the default, and the reason is a real trade rather than caution. Chunk
138
+ * compression is what makes a chunk stand alone, and two shipped things
139
+ * depend on that: a cold search answers by ranged-reading the few chunks it
140
+ * needs instead of pulling the whole archive, and sealing streams at bounded
141
+ * memory. Whole-file compression gives up both. `squeeze` opts in because it
142
+ * exists to give a full disk back and its archives are read whole anyway;
143
+ * anything headed for a bucket it will later search should not.
144
+ */
145
+ compression?: "gzip-chunk" | "zstd" | "zstd-chunk";
146
+ /**
147
+ * Index this seal's tokens into the local content index as part of the seal
148
+ * (chunk-compressed full seals up to the whale threshold; a delta is indexed
149
+ * by the catch-up as one chain). The daemon, the CLI and the MCP server set
150
+ * it: a person's session is searchable the moment it is sealed, not after a
151
+ * background pass that on a real vault sits behind hours of multi-gigabyte
152
+ * snapshots. Off by default so callers that build the index themselves
153
+ * (tests, migrations) see exactly what they built. Advisory: a seal is
154
+ * durable before its index entry exists, and an entry that fails is named
155
+ * (`SealkeepIndexDeferred`, audit `index.merge`), never a failed seal.
156
+ */
157
+ indexInline?: boolean;
109
158
  }): Promise<ArchiveResult>;
110
159
  /**
111
160
  * The recovery phrase always gets a recipient, so a recovery kit alone can restore.
@@ -114,12 +163,94 @@ export declare function archiveFile(dataDir: string, sourcePath: string, rawPhra
114
163
  export declare function configuredRecipients(config: VaultConfig, rawPhrase: string, scope?: string | {
115
164
  group?: string;
116
165
  project?: string;
166
+ projectKey?: string;
117
167
  }): Recipient[];
168
+ /** Accepted managed team members that should open future project archives. */
169
+ export declare function teamRecipientsForProject(dataDir: string, project: string | null | undefined, projectKey?: string | null): Promise<Recipient[]>;
170
+ /**
171
+ * Every archive this vault knows about.
172
+ *
173
+ * One unreadable record used to take the whole list with it: `JSON.parse`
174
+ * threw inside a `Promise.all`, so a single truncated file — a crash mid-write,
175
+ * a disk that filled between `open` and `close` — made `status`, `search`,
176
+ * `retention` and every other command that lists archives fail outright. A
177
+ * vault of two hundred good records became a vault of none, over one bad byte.
178
+ *
179
+ * A record that will not parse is skipped and NAMED, not swallowed: it may be
180
+ * the only trace of an archive, and quietly dropping it would turn a loud
181
+ * problem into a missing one. The archives that do parse still answer.
182
+ */
118
183
  export declare function listArchives(dataDir: string): Promise<ArchiveRecord[]>;
119
184
  /**
120
185
  * Registers an X25519 public key that may open future archives. Only the public
121
186
  * key is stored; the matching private key stays on its own device.
122
187
  */
188
+ export declare function projectSharingOf(config: VaultConfig, project: string | undefined | null, projectKey?: string | null): "active" | "passive";
189
+ export declare function setProjectSharing(dataDir: string, project: string, mode: "active" | "passive", projectKey?: string | null): Promise<VaultConfig>;
190
+ export type TeamSpaceBinding = {
191
+ spaceKey: string;
192
+ role?: "owner" | "member";
193
+ keyVersion?: number;
194
+ realtimeKey?: string;
195
+ localConfirmed?: true;
196
+ /** Display-only label for a binding stored under an opaque project key. */
197
+ localProject?: string;
198
+ };
199
+ export type TeamSpaceBindingPatch = Partial<Omit<TeamSpaceBinding, "spaceKey">>;
200
+ export type TeamProjectDraft = {
201
+ projectName: string;
202
+ projects: string[];
203
+ projectSelections?: ProjectSelection[];
204
+ createdAt: string;
205
+ };
206
+ export type ProjectSelection = {
207
+ projectKey: string;
208
+ project: string;
209
+ };
210
+ export declare function teamSpaceOf(config: VaultConfig, project: string | undefined | null, projectKey?: string | null): TeamSpaceBinding | null;
211
+ /**
212
+ * Adds keyed aliases for old label-keyed bindings only when local discovery
213
+ * proves that label names exactly one stable project. The legacy entry stays
214
+ * in place for older Sealkeep builds; duplicate labels stay untouched and are
215
+ * therefore invisible to new exact-key access decisions.
216
+ */
217
+ export declare function migrateLegacyTeamSpaceBindings(dataDir: string, identities: readonly {
218
+ project: string | null;
219
+ projectKey: string | null;
220
+ }[]): Promise<VaultConfig>;
221
+ /**
222
+ * Records the dashboard-visible choice that this checkout participates in a
223
+ * team space. It stores only the opaque space id; encryption keys never enter
224
+ * config.json. Binding also enables the automatic live lane for that project.
225
+ */
226
+ export declare function bindTeamSpace(dataDir: string, project: string, binding: TeamSpaceBinding, projectKey?: string | null): Promise<VaultConfig>;
227
+ /**
228
+ * Remember which detected local folders should become one logical project.
229
+ * No path or project label is sent to the hosted plane here. The account page
230
+ * creates the logical project, then normal daemon reconciliation consumes this
231
+ * local draft when the matching project appears.
232
+ */
233
+ export declare function stageTeamProjectDraft(dataDir: string, projectName: string, projects: string[] | ProjectSelection[]): Promise<TeamProjectDraft>;
234
+ export declare function removeTeamProjectDraft(dataDir: string, projectName: string): Promise<VaultConfig>;
235
+ export declare function unbindTeamSpace(dataDir: string, project: string, projectKey?: string | null): Promise<VaultConfig>;
236
+ /**
237
+ * Disconnect one hosted project from this machine without changing cloud
238
+ * membership. The tombstone is deliberate: daemon reconciliation must not
239
+ * silently recreate a binding the person just removed.
240
+ */
241
+ export declare function disconnectTeamSpaceOnMachine(dataDir: string, spaceKey: string): Promise<VaultConfig>;
242
+ /**
243
+ * Apply a hosted key/version/route update to every local checkout bound to one
244
+ * logical space. `undefined` patch members are ignored so an older hosted
245
+ * response cannot erase a newer route already learned by this machine.
246
+ */
247
+ export declare function updateTeamSpaceBindings(dataDir: string, spaceKey: string, patch: TeamSpaceBindingPatch): Promise<VaultConfig>;
248
+ /**
249
+ * Revoke every checkout bound to a removed hosted membership in one atomic
250
+ * config replacement. The logical space disappears and all affected projects
251
+ * become passive together; encrypted archives and project files are untouched.
252
+ */
253
+ export declare function revokeTeamSpaceBindings(dataDir: string, spaceKey: string): Promise<VaultConfig>;
123
254
  export declare function addRecipient(dataDir: string, label: string, publicKeyBase64: string, group?: string,
124
255
  /**
125
256
  * Tie this key to one project and it becomes a member of that project only:
@@ -127,12 +258,38 @@ export declare function addRecipient(dataDir: string, label: string, publicKeyBa
127
258
  * seals. A colleague on `checkout-rewrite` never receives the rest of your
128
259
  * work, which is the difference between sharing a folder and handing over a
129
260
  * drive.
130
- */
131
- project?: string): Promise<VaultConfig>;
261
+ */
262
+ project?: string, projectKey?: string): Promise<VaultConfig>;
132
263
  /** Removes a recipient from future archives. Run `sealkeep rewrap` to revoke it on existing ones. */
133
264
  export declare function removeRecipient(dataDir: string, id: string): Promise<VaultConfig>;
134
- /** Persists a full config document after validation by the caller. */
265
+ /**
266
+ * Persists a full config document after validation by the caller. Team state
267
+ * is deliberately retained from the lock-protected current file: bindings and
268
+ * revocations are changed only through their dedicated atomic helpers.
269
+ */
135
270
  export declare function writeConfig(dataDir: string, config: VaultConfig): Promise<void>;
271
+ /**
272
+ * Installs a vault identity that was authenticated and decrypted by a transfer
273
+ * protocol before this call. Unlike `initialize`, this must not mint a new id
274
+ * or phrase; unlike `writeConfig`, it must work before config.json exists.
275
+ * The storage root is always local to this data directory, regardless of what
276
+ * the sending machine used, and the same cross-process lock/refusal protects
277
+ * against replacing a vault that appeared while approval was in flight.
278
+ */
279
+ export declare function initializeTransferredVault(dataDir: string, transferred: VaultConfig): Promise<VaultConfig>;
280
+ /** Merge a top-level patch into the latest lock-protected config document. */
281
+ export declare function updateConfigFields(dataDir: string, patch: Partial<VaultConfig>): Promise<VaultConfig>;
282
+ /**
283
+ * Compare and update top-level config fields while holding the same
284
+ * cross-process lock as every other supported config mutation. This is the
285
+ * config-file equivalent of compare-and-set: callers which obtained a value
286
+ * before an asynchronous network read can refuse to replace a newer local
287
+ * choice which landed while that read was in flight.
288
+ */
289
+ export declare function updateConfigFieldsIf(dataDir: string, predicate: (current: VaultConfig) => boolean, patch: Partial<VaultConfig>): Promise<{
290
+ matched: boolean;
291
+ config: VaultConfig;
292
+ }>;
136
293
  export type RetentionCandidate = {
137
294
  id: string;
138
295
  agent: string;
@@ -184,10 +341,21 @@ export declare function restoreRecordToFile(dataDir: string, record: ArchiveReco
184
341
  */
185
342
  rawPhrase: string | {
186
343
  privateKey: string;
187
- }, destination: string,
344
+ },
345
+ /**
346
+ * A path, or a Writable to stream the plaintext into. The stream form exists
347
+ * so an archive can be PROVED to decrypt without spending its own size in
348
+ * free disk; the delta and plain-mode paths below still need a real file and
349
+ * say so rather than silently writing somewhere unexpected.
350
+ */
351
+ destination: string | NodeJS.WritableStream,
188
352
  /** Injectable so the offloaded-archive path can be proved without a bucket. */
189
353
  options?: {
190
354
  client?: import("./offload.js").FetchClient;
355
+ /** Historical indexing owns a cancellable child; cancellation must also
356
+ * withdraw a queued/materialising compatibility archive. */
357
+ signal?: AbortSignal;
358
+ scratchWaitMs?: number;
191
359
  }): Promise<{
192
360
  bytes: number;
193
361
  }>;
@@ -202,7 +370,15 @@ options?: {
202
370
  * base whose recorded length is not what the delta sealed from is refused
203
371
  * here, before any restore starts writing.
204
372
  */
205
- export declare function resolveDeltaChain(archives: readonly ArchiveRecord[], target: ArchiveRecord): ArchiveRecord[];
373
+ export declare function resolveDeltaChain(archives: readonly ArchiveRecord[], target: ArchiveRecord,
374
+ /**
375
+ * Callers resolving many heads from one ledger may supply its shared index.
376
+ * Rebuilding the same thousands-entry map once per visible session turned a
377
+ * linear dashboard question into quadratic work. The optional argument does
378
+ * not change resolution semantics; it only lets that immutable lookup be
379
+ * built once for the batch.
380
+ */
381
+ archiveIndex?: ReadonlyMap<string, ArchiveRecord>): ArchiveRecord[];
206
382
  /**
207
383
  * Restores a delta archive by reassembling its chain: the base archive first,
208
384
  * then each delta's appended range, concatenated in order into `destination`.
@@ -221,7 +397,27 @@ export declare function restoreDeltaChainToFile(dataDir: string, record: Archive
221
397
  bytes: number;
222
398
  chain: string[];
223
399
  }>;
224
- export declare function decryptRecord(dataDir: string, id: string, rawPhrase: string): Promise<{
400
+ /**
401
+ * Verifies then decrypts one archive in memory. Ciphertext integrity is checked
402
+ * before the key touches it, and plaintext integrity after.
403
+ *
404
+ * This holds the whole transcript at once; `restoreRecordToFile` is the
405
+ * constant-memory path and is what restoring uses. Callers that genuinely need
406
+ * the bytes in hand — indexing, the v1 migration — still come through here.
407
+ */
408
+ /**
409
+ * The sealed bytes of a record, wherever they live. A local blob reads
410
+ * straight from disk; an OFFLOADED archive — sealed copy in the cloud, local
411
+ * blob reclaimed — is fetched hash-checked and held only for the read. Found
412
+ * by the live value drill: `sealkeep index build` died with ENOENT on the
413
+ * first offloaded legacy archive it met, because this read assumed the blob.
414
+ */
415
+ export type DecryptRecordOptions = {
416
+ client?: import("./offload.js").FetchClient;
417
+ signal?: AbortSignal;
418
+ scratchWaitMs?: number;
419
+ };
420
+ export declare function decryptRecord(dataDir: string, id: string, rawPhrase: string, options?: DecryptRecordOptions): Promise<{
225
421
  record: ArchiveRecord;
226
422
  plaintext: Buffer;
227
423
  }>;