@threadbase-sh/streamer 1.62.0 → 1.64.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/dist/agent/agent-client.d.ts +14 -0
  2. package/dist/agent/agent-client.d.ts.map +1 -0
  3. package/dist/agent/agent-config.d.ts +24 -0
  4. package/dist/agent/agent-config.d.ts.map +1 -0
  5. package/dist/agent/conversation-writer.d.ts +13 -0
  6. package/dist/agent/conversation-writer.d.ts.map +1 -0
  7. package/dist/agent/dedupe.d.ts +6 -0
  8. package/dist/agent/dedupe.d.ts.map +1 -0
  9. package/dist/agent/errors.d.ts +23 -0
  10. package/dist/agent/errors.d.ts.map +1 -0
  11. package/dist/agent/handle-send-agent-input.d.ts +21 -0
  12. package/dist/agent/handle-send-agent-input.d.ts.map +1 -0
  13. package/dist/agent/handle-start-agent-session.d.ts +21 -0
  14. package/dist/agent/handle-start-agent-session.d.ts.map +1 -0
  15. package/dist/agent/history-mapper.d.ts +4 -0
  16. package/dist/agent/history-mapper.d.ts.map +1 -0
  17. package/dist/agent/payload-guard.d.ts +29 -0
  18. package/dist/agent/payload-guard.d.ts.map +1 -0
  19. package/dist/api/app.d.ts +28 -0
  20. package/dist/api/app.d.ts.map +1 -0
  21. package/dist/api/handlers/conversations.handlers.d.ts +69 -0
  22. package/dist/api/handlers/conversations.handlers.d.ts.map +1 -0
  23. package/dist/api/handlers/http-helpers.d.ts +50 -0
  24. package/dist/api/handlers/http-helpers.d.ts.map +1 -0
  25. package/dist/api/handlers/sessions.handlers.d.ts +230 -0
  26. package/dist/api/handlers/sessions.handlers.d.ts.map +1 -0
  27. package/dist/api/middleware/auth.middleware.d.ts +5 -0
  28. package/dist/api/middleware/auth.middleware.d.ts.map +1 -0
  29. package/dist/api/middleware/cors.middleware.d.ts +5 -0
  30. package/dist/api/middleware/cors.middleware.d.ts.map +1 -0
  31. package/dist/api/middleware/error.middleware.d.ts +4 -0
  32. package/dist/api/middleware/error.middleware.d.ts.map +1 -0
  33. package/dist/api/routes/backup.routes.d.ts +5 -0
  34. package/dist/api/routes/backup.routes.d.ts.map +1 -0
  35. package/dist/api/routes/browse.routes.d.ts +5 -0
  36. package/dist/api/routes/browse.routes.d.ts.map +1 -0
  37. package/dist/api/routes/cacheAlert.routes.d.ts +5 -0
  38. package/dist/api/routes/cacheAlert.routes.d.ts.map +1 -0
  39. package/dist/api/routes/config.routes.d.ts +5 -0
  40. package/dist/api/routes/config.routes.d.ts.map +1 -0
  41. package/dist/api/routes/conversations.routes.d.ts +5 -0
  42. package/dist/api/routes/conversations.routes.d.ts.map +1 -0
  43. package/dist/api/routes/devices.routes.d.ts +17 -0
  44. package/dist/api/routes/devices.routes.d.ts.map +1 -0
  45. package/dist/api/routes/diagnostics.routes.d.ts +5 -0
  46. package/dist/api/routes/diagnostics.routes.d.ts.map +1 -0
  47. package/dist/api/routes/health.routes.d.ts +5 -0
  48. package/dist/api/routes/health.routes.d.ts.map +1 -0
  49. package/dist/api/routes/logs.routes.d.ts +3 -0
  50. package/dist/api/routes/logs.routes.d.ts.map +1 -0
  51. package/dist/api/routes/misc.routes.d.ts +77 -0
  52. package/dist/api/routes/misc.routes.d.ts.map +1 -0
  53. package/dist/api/routes/pair.routes.d.ts +5 -0
  54. package/dist/api/routes/pair.routes.d.ts.map +1 -0
  55. package/dist/api/routes/progress.routes.d.ts +39 -0
  56. package/dist/api/routes/progress.routes.d.ts.map +1 -0
  57. package/dist/api/routes/projects.routes.d.ts +5 -0
  58. package/dist/api/routes/projects.routes.d.ts.map +1 -0
  59. package/dist/api/routes/providers.routes.d.ts +19 -0
  60. package/dist/api/routes/providers.routes.d.ts.map +1 -0
  61. package/dist/api/routes/scanner.routes.d.ts +5 -0
  62. package/dist/api/routes/scanner.routes.d.ts.map +1 -0
  63. package/dist/api/routes/sessions.routes.d.ts +6 -0
  64. package/dist/api/routes/sessions.routes.d.ts.map +1 -0
  65. package/dist/api/routes/ws.routes.d.ts +7 -0
  66. package/dist/api/routes/ws.routes.d.ts.map +1 -0
  67. package/dist/api/types/api-deps.d.ts +114 -0
  68. package/dist/api/types/api-deps.d.ts.map +1 -0
  69. package/dist/auth.d.ts +81 -0
  70. package/dist/auth.d.ts.map +1 -0
  71. package/dist/browse.d.ts +17 -0
  72. package/dist/browse.d.ts.map +1 -0
  73. package/dist/claude-flags.d.ts +76 -0
  74. package/dist/claude-flags.d.ts.map +1 -0
  75. package/dist/cli.cjs +1917 -1795
  76. package/dist/cli.cjs.map +1 -1
  77. package/dist/codex-pty-runner.d.ts +90 -0
  78. package/dist/codex-pty-runner.d.ts.map +1 -0
  79. package/dist/config/update-config.d.ts +13 -0
  80. package/dist/config/update-config.d.ts.map +1 -0
  81. package/dist/conversation-cache.d.ts +336 -0
  82. package/dist/conversation-cache.d.ts.map +1 -0
  83. package/dist/db/config.d.ts +11 -0
  84. package/dist/db/config.d.ts.map +1 -0
  85. package/dist/db/index.d.ts +5 -0
  86. package/dist/db/index.d.ts.map +1 -0
  87. package/dist/db/migrations.d.ts +3 -0
  88. package/dist/db/migrations.d.ts.map +1 -0
  89. package/dist/db/pool.d.ts +5 -0
  90. package/dist/db/pool.d.ts.map +1 -0
  91. package/dist/db/query-timing.d.ts +52 -0
  92. package/dist/db/query-timing.d.ts.map +1 -0
  93. package/dist/db/repositories/cacheMetadata.repository.d.ts +12 -0
  94. package/dist/db/repositories/cacheMetadata.repository.d.ts.map +1 -0
  95. package/dist/db/repositories/conversations.repository.d.ts +27 -0
  96. package/dist/db/repositories/conversations.repository.d.ts.map +1 -0
  97. package/dist/db/repositories/devices.repository.d.ts +137 -0
  98. package/dist/db/repositories/devices.repository.d.ts.map +1 -0
  99. package/dist/db/repositories/managed-sessions.repository.d.ts +127 -0
  100. package/dist/db/repositories/managed-sessions.repository.d.ts.map +1 -0
  101. package/dist/db/repositories/projects.repository.d.ts +28 -0
  102. package/dist/db/repositories/projects.repository.d.ts.map +1 -0
  103. package/dist/db/repositories/push.repository.d.ts +186 -0
  104. package/dist/db/repositories/push.repository.d.ts.map +1 -0
  105. package/dist/db/repositories/sessions.repository.d.ts +16 -0
  106. package/dist/db/repositories/sessions.repository.d.ts.map +1 -0
  107. package/dist/db/runtime-store.d.ts +80 -0
  108. package/dist/db/runtime-store.d.ts.map +1 -0
  109. package/dist/db/sqlite-migrate.d.ts +13 -0
  110. package/dist/db/sqlite-migrate.d.ts.map +1 -0
  111. package/dist/db/upload-records.d.ts +11 -0
  112. package/dist/db/upload-records.d.ts.map +1 -0
  113. package/dist/e2ee/noise.d.ts +261 -0
  114. package/dist/e2ee/noise.d.ts.map +1 -0
  115. package/dist/e2ee/pair-payload.d.ts +60 -0
  116. package/dist/e2ee/pair-payload.d.ts.map +1 -0
  117. package/dist/e2ee/pair-request.d.ts +24 -0
  118. package/dist/e2ee/pair-request.d.ts.map +1 -0
  119. package/dist/external-tails.d.ts +91 -0
  120. package/dist/external-tails.d.ts.map +1 -0
  121. package/dist/feature-flags.d.ts +212 -0
  122. package/dist/feature-flags.d.ts.map +1 -0
  123. package/dist/handlers/handleListProjects.d.ts +3 -0
  124. package/dist/handlers/handleListProjects.d.ts.map +1 -0
  125. package/dist/index.cjs +84 -15
  126. package/dist/index.cjs.map +1 -1
  127. package/dist/index.d.ts +18 -2571
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +84 -15
  130. package/dist/index.js.map +1 -1
  131. package/dist/lifecycle/constants.d.ts +21 -0
  132. package/dist/lifecycle/constants.d.ts.map +1 -0
  133. package/dist/lifecycle/process-liveness.d.ts +7 -0
  134. package/dist/lifecycle/process-liveness.d.ts.map +1 -0
  135. package/dist/live-session-manager.d.ts +59 -0
  136. package/dist/live-session-manager.d.ts.map +1 -0
  137. package/dist/logger.d.ts +14 -0
  138. package/dist/logger.d.ts.map +1 -0
  139. package/dist/pair-store.d.ts +60 -0
  140. package/dist/pair-store.d.ts.map +1 -0
  141. package/dist/platform.d.ts +25 -0
  142. package/dist/platform.d.ts.map +1 -0
  143. package/dist/process-discovery.d.ts +35 -0
  144. package/dist/process-discovery.d.ts.map +1 -0
  145. package/dist/providers.d.ts +7 -0
  146. package/dist/providers.d.ts.map +1 -0
  147. package/dist/pty-host/protocol.d.ts +270 -0
  148. package/dist/pty-host/protocol.d.ts.map +1 -0
  149. package/dist/pty-host/remote-session-runner.d.ts +133 -0
  150. package/dist/pty-host/remote-session-runner.d.ts.map +1 -0
  151. package/dist/pty-host/socket.d.ts +54 -0
  152. package/dist/pty-host/socket.d.ts.map +1 -0
  153. package/dist/pty-host/spawn-host.d.ts +30 -0
  154. package/dist/pty-host/spawn-host.d.ts.map +1 -0
  155. package/dist/pty-manager.d.ts +65 -0
  156. package/dist/pty-manager.d.ts.map +1 -0
  157. package/dist/pty-shared.d.ts +27 -0
  158. package/dist/pty-shared.d.ts.map +1 -0
  159. package/dist/scanner-manager.d.ts +126 -0
  160. package/dist/scanner-manager.d.ts.map +1 -0
  161. package/dist/schemas/cacheAlert.schema.d.ts +14 -0
  162. package/dist/schemas/cacheAlert.schema.d.ts.map +1 -0
  163. package/dist/schemas/claudeFlags.schema.d.ts +7 -0
  164. package/dist/schemas/claudeFlags.schema.d.ts.map +1 -0
  165. package/dist/schemas/project.schema.d.ts +18 -0
  166. package/dist/schemas/project.schema.d.ts.map +1 -0
  167. package/dist/schemas/updateConfig.schema.d.ts +19 -0
  168. package/dist/schemas/updateConfig.schema.d.ts.map +1 -0
  169. package/dist/seal.d.ts +14 -0
  170. package/dist/seal.d.ts.map +1 -0
  171. package/dist/server-identity.d.ts +43 -0
  172. package/dist/server-identity.d.ts.map +1 -0
  173. package/dist/server-wiring.d.ts +184 -0
  174. package/dist/server-wiring.d.ts.map +1 -0
  175. package/dist/server.d.ts +390 -0
  176. package/dist/server.d.ts.map +1 -0
  177. package/dist/services/backup/backup.d.ts +103 -0
  178. package/dist/services/backup/backup.d.ts.map +1 -0
  179. package/dist/services/cache/cacheMetadata.d.ts +8 -0
  180. package/dist/services/cache/cacheMetadata.d.ts.map +1 -0
  181. package/dist/services/cache-integrity/alertStore.d.ts +24 -0
  182. package/dist/services/cache-integrity/alertStore.d.ts.map +1 -0
  183. package/dist/services/cache-integrity/backup.d.ts +8 -0
  184. package/dist/services/cache-integrity/backup.d.ts.map +1 -0
  185. package/dist/services/cache-integrity/cacheIntegrityMonitor.d.ts +71 -0
  186. package/dist/services/cache-integrity/cacheIntegrityMonitor.d.ts.map +1 -0
  187. package/dist/services/conversations/conversationWatcher.d.ts +99 -0
  188. package/dist/services/conversations/conversationWatcher.d.ts.map +1 -0
  189. package/dist/services/conversations/findSearchTarget.d.ts +30 -0
  190. package/dist/services/conversations/findSearchTarget.d.ts.map +1 -0
  191. package/dist/services/conversations/isAgentConversation.d.ts +8 -0
  192. package/dist/services/conversations/isAgentConversation.d.ts.map +1 -0
  193. package/dist/services/conversations/pruneAgentConversations.d.ts +8 -0
  194. package/dist/services/conversations/pruneAgentConversations.d.ts.map +1 -0
  195. package/dist/services/conversations/refreshConversationCache.d.ts +27 -0
  196. package/dist/services/conversations/refreshConversationCache.d.ts.map +1 -0
  197. package/dist/services/conversations/shouldRefreshProjectsFromHdd.d.ts +33 -0
  198. package/dist/services/conversations/shouldRefreshProjectsFromHdd.d.ts.map +1 -0
  199. package/dist/services/diagnostics/diagnostics.d.ts +66 -0
  200. package/dist/services/diagnostics/diagnostics.d.ts.map +1 -0
  201. package/dist/services/projectChats/deriveProjectChatTitle.d.ts +15 -0
  202. package/dist/services/projectChats/deriveProjectChatTitle.d.ts.map +1 -0
  203. package/dist/services/projects/ensureProjectsForConversations.d.ts +15 -0
  204. package/dist/services/projects/ensureProjectsForConversations.d.ts.map +1 -0
  205. package/dist/services/providers/capabilities.d.ts +105 -0
  206. package/dist/services/providers/capabilities.d.ts.map +1 -0
  207. package/dist/services/providers/providerHealth.d.ts +72 -0
  208. package/dist/services/providers/providerHealth.d.ts.map +1 -0
  209. package/dist/services/push/apnsClient.d.ts +105 -0
  210. package/dist/services/push/apnsClient.d.ts.map +1 -0
  211. package/dist/services/push/expoPushSender.d.ts +37 -0
  212. package/dist/services/push/expoPushSender.d.ts.map +1 -0
  213. package/dist/services/push/liveActivityContentState.d.ts +60 -0
  214. package/dist/services/push/liveActivityContentState.d.ts.map +1 -0
  215. package/dist/services/push/liveActivityNotifier.d.ts +49 -0
  216. package/dist/services/push/liveActivityNotifier.d.ts.map +1 -0
  217. package/dist/services/push/liveActivityRenewal.d.ts +63 -0
  218. package/dist/services/push/liveActivityRenewal.d.ts.map +1 -0
  219. package/dist/services/push/liveActivitySender.d.ts +88 -0
  220. package/dist/services/push/liveActivitySender.d.ts.map +1 -0
  221. package/dist/services/push/waitingInputNotifier.d.ts +41 -0
  222. package/dist/services/push/waitingInputNotifier.d.ts.map +1 -0
  223. package/dist/services/questions/answersToKeystrokes.d.ts +8 -0
  224. package/dist/services/questions/answersToKeystrokes.d.ts.map +1 -0
  225. package/dist/services/questions/codexGateAnswers.d.ts +14 -0
  226. package/dist/services/questions/codexGateAnswers.d.ts.map +1 -0
  227. package/dist/services/questions/codexScreen.d.ts +74 -0
  228. package/dist/services/questions/codexScreen.d.ts.map +1 -0
  229. package/dist/services/questions/detectAskUserQuestion.d.ts +6 -0
  230. package/dist/services/questions/detectAskUserQuestion.d.ts.map +1 -0
  231. package/dist/services/questions/detectPermissionGate.d.ts +62 -0
  232. package/dist/services/questions/detectPermissionGate.d.ts.map +1 -0
  233. package/dist/services/questions/detectQuestionFromScreen.d.ts +30 -0
  234. package/dist/services/questions/detectQuestionFromScreen.d.ts.map +1 -0
  235. package/dist/services/questions/detectShellPrompt.d.ts +18 -0
  236. package/dist/services/questions/detectShellPrompt.d.ts.map +1 -0
  237. package/dist/services/questions/parseAgentPhase.d.ts +12 -0
  238. package/dist/services/questions/parseAgentPhase.d.ts.map +1 -0
  239. package/dist/services/questions/parseStatusLine.d.ts +19 -0
  240. package/dist/services/questions/parseStatusLine.d.ts.map +1 -0
  241. package/dist/services/questions/questionBroadcast.d.ts +18 -0
  242. package/dist/services/questions/questionBroadcast.d.ts.map +1 -0
  243. package/dist/services/questions/resolveAnswer.d.ts +16 -0
  244. package/dist/services/questions/resolveAnswer.d.ts.map +1 -0
  245. package/dist/services/search/searchQuery.d.ts +78 -0
  246. package/dist/services/search/searchQuery.d.ts.map +1 -0
  247. package/dist/services/security/capabilities.d.ts +50 -0
  248. package/dist/services/security/capabilities.d.ts.map +1 -0
  249. package/dist/services/sessions/autoResumeOnBoot.d.ts +28 -0
  250. package/dist/services/sessions/autoResumeOnBoot.d.ts.map +1 -0
  251. package/dist/services/sessions/codexRolloutOwner.d.ts +55 -0
  252. package/dist/services/sessions/codexRolloutOwner.d.ts.map +1 -0
  253. package/dist/services/sessions/conversationBusy.d.ts +32 -0
  254. package/dist/services/sessions/conversationBusy.d.ts.map +1 -0
  255. package/dist/services/sessions/idempotency.d.ts +67 -0
  256. package/dist/services/sessions/idempotency.d.ts.map +1 -0
  257. package/dist/services/sessions/reconcileSessions.d.ts +63 -0
  258. package/dist/services/sessions/reconcileSessions.d.ts.map +1 -0
  259. package/dist/services/sessions/rehydrateSessions.d.ts +68 -0
  260. package/dist/services/sessions/rehydrateSessions.d.ts.map +1 -0
  261. package/dist/services/sessions/resumeIdentity.d.ts +16 -0
  262. package/dist/services/sessions/resumeIdentity.d.ts.map +1 -0
  263. package/dist/session-registry-boot.d.ts +142 -0
  264. package/dist/session-registry-boot.d.ts.map +1 -0
  265. package/dist/session-store.d.ts +32 -0
  266. package/dist/session-store.d.ts.map +1 -0
  267. package/dist/session-watchers.d.ts +60 -0
  268. package/dist/session-watchers.d.ts.map +1 -0
  269. package/dist/types.d.ts +616 -0
  270. package/dist/types.d.ts.map +1 -0
  271. package/dist/uploads.d.ts +16 -0
  272. package/dist/uploads.d.ts.map +1 -0
  273. package/dist/utils/bootToken.d.ts +3 -0
  274. package/dist/utils/bootToken.d.ts.map +1 -0
  275. package/dist/utils/canonicalizeFilePath.d.ts +75 -0
  276. package/dist/utils/canonicalizeFilePath.d.ts.map +1 -0
  277. package/dist/utils/canonicalizeProjectPath.d.ts +13 -0
  278. package/dist/utils/canonicalizeProjectPath.d.ts.map +1 -0
  279. package/dist/utils/codexConversationLine.d.ts +38 -0
  280. package/dist/utils/codexConversationLine.d.ts.map +1 -0
  281. package/dist/utils/conversationEtag.d.ts +19 -0
  282. package/dist/utils/conversationEtag.d.ts.map +1 -0
  283. package/dist/utils/dates.d.ts +12 -0
  284. package/dist/utils/dates.d.ts.map +1 -0
  285. package/dist/utils/debounce.d.ts +15 -0
  286. package/dist/utils/debounce.d.ts.map +1 -0
  287. package/dist/utils/deriveSessionName.d.ts +10 -0
  288. package/dist/utils/deriveSessionName.d.ts.map +1 -0
  289. package/dist/utils/fileIdentity.d.ts +36 -0
  290. package/dist/utils/fileIdentity.d.ts.map +1 -0
  291. package/dist/utils/isScannedSnapshotStale.d.ts +16 -0
  292. package/dist/utils/isScannedSnapshotStale.d.ts.map +1 -0
  293. package/dist/utils/scanProgressThrottle.d.ts +12 -0
  294. package/dist/utils/scanProgressThrottle.d.ts.map +1 -0
  295. package/dist/version.d.ts +3 -0
  296. package/dist/version.d.ts.map +1 -0
  297. package/dist/ws-hub.d.ts +15 -0
  298. package/dist/ws-hub.d.ts.map +1 -0
  299. package/package.json +3 -4
  300. package/dist/index.d.cts +0 -2571
@@ -0,0 +1,137 @@
1
+ import type Database from "better-sqlite3";
2
+ import { type Capability, type CapabilityPreset } from "../../services/security/capabilities";
3
+ /**
4
+ * Paired-device registry (C5).
5
+ * See docs/architecture/2026-07-24-device-identity-and-capabilities.md.
6
+ *
7
+ * Stores identity and authority for each paired device. Never stores a usable
8
+ * credential: only the SHA-256 of a device token, so reading this table cannot
9
+ * impersonate a device.
10
+ */
11
+ export interface DeviceRow {
12
+ device_id: string;
13
+ public_key: string;
14
+ token_hash: string;
15
+ name: string | null;
16
+ capabilities: string;
17
+ created_at: number;
18
+ last_seen_at: number | null;
19
+ revoked_at: number | null;
20
+ /** Noise static public key, base64. Null on every row that predates E2EE. */
21
+ e2ee_static_pub: string | null;
22
+ /** The downgrade lock. 1 once this device has completed a handshake. */
23
+ e2ee_required: number;
24
+ e2ee_version: number | null;
25
+ }
26
+ /** A device as reported over the API. Deliberately carries no credential. */
27
+ export interface DeviceView {
28
+ deviceId: string;
29
+ name: string | null;
30
+ capabilities: Capability[];
31
+ createdAt: number;
32
+ lastSeenAt: number | null;
33
+ revokedAt: number | null;
34
+ /**
35
+ * Whether this device is pinned to encryption.
36
+ *
37
+ * A boolean, never the key and never a hash of it: `GET /api/devices` exists
38
+ * so a user can spot a device they did not pair, and answering "is this one
39
+ * encrypted" needs no key material to do it. Publishing the static key would
40
+ * hand an attacker who reached this endpoint the value that identifies a
41
+ * device.
42
+ */
43
+ e2ee: boolean;
44
+ }
45
+ export interface RegisteredDevice {
46
+ deviceId: string;
47
+ /** Returned to the client exactly once, at pairing. Never persisted raw. */
48
+ deviceToken: string;
49
+ capabilities: Capability[];
50
+ }
51
+ /** Device tokens are opaque high-entropy strings; 32 bytes matches the API key. */
52
+ export declare function generateDeviceToken(): string;
53
+ export declare function hashDeviceToken(token: string): string;
54
+ /**
55
+ * Constant-time comparison of two token hashes, matching `validateApiKey`'s
56
+ * discipline. Both inputs are fixed-length hex digests, so a length mismatch
57
+ * means a malformed value rather than a secret-dependent branch.
58
+ */
59
+ export declare function safeHashEquals(a: string, b: string): boolean;
60
+ /**
61
+ * Parse the stored capability JSON, dropping anything this build does not
62
+ * recognize. A downgrade must never silently grant a capability it cannot
63
+ * enforce — unknown entries are discarded rather than trusted.
64
+ */
65
+ export declare function parseCapabilities(raw: string): Capability[];
66
+ export declare function toDeviceView(row: DeviceRow): DeviceView;
67
+ export declare class DevicesRepository {
68
+ private insertStmt;
69
+ private byTokenHashStmt;
70
+ private byIdStmt;
71
+ private listStmt;
72
+ private revokeStmt;
73
+ private touchStmt;
74
+ private deleteStmt;
75
+ private deleteRevokedStmt;
76
+ private byE2eeStaticPubStmt;
77
+ private repairStmt;
78
+ constructor(db: Database.Database);
79
+ /**
80
+ * Record a newly paired device and mint its token.
81
+ *
82
+ * The raw token is returned to the caller and never stored — this is the only
83
+ * moment it exists outside the client.
84
+ */
85
+ register(args: {
86
+ publicKey: string;
87
+ name?: string | null;
88
+ preset?: CapabilityPreset;
89
+ now?: number;
90
+ /**
91
+ * The device's Noise static public key, base64, when pairing completed a
92
+ * handshake. Absent on a plaintext pairing, which stays exactly as it is
93
+ * today: no key, no pin, no behaviour change.
94
+ */
95
+ e2eeStaticPub?: string;
96
+ e2eeVersion?: number;
97
+ }): RegisteredDevice;
98
+ /** The device that owns a Noise static key, or null. */
99
+ getByE2eeStaticPub(staticPub: string): DeviceRow | null;
100
+ /**
101
+ * Resolve a presented token to a device, or null.
102
+ *
103
+ * Returns null for a revoked device, so revocation takes effect on the very
104
+ * next request with no cache to go stale.
105
+ */
106
+ authenticate(token: string): DeviceRow | null;
107
+ get(deviceId: string): DeviceRow | null;
108
+ /** All devices, including revoked ones — an audit surface needs the history. */
109
+ list(): DeviceView[];
110
+ /** Revoke one device. Others are untouched — no key rotation, no collateral. */
111
+ revoke(deviceId: string, now?: number): boolean;
112
+ /**
113
+ * Erase one device's record outright.
114
+ *
115
+ * Deliberately separate from `revoke`, which is a soft delete that keeps the
116
+ * row so `list()` can show what happened. That audit trail is the right
117
+ * default — but it meant a `devices` row, including the user-supplied `name`
118
+ * ("Ronen's iPhone"), had no removal path at all once the registry moved to
119
+ * runtime.db, which no command deletes. This is that path.
120
+ *
121
+ * Erasure is NOT revocation: deleting a row frees its `token_hash`, so a
122
+ * device whose token is still on a phone somewhere stops being *known* rather
123
+ * than being *refused*. Revoke first, delete second, is the safe order, and
124
+ * `deleteRevoked()` exists so that is the easy thing to do.
125
+ */
126
+ delete(deviceId: string): boolean;
127
+ /**
128
+ * Erase every already-revoked device. The bulk companion to `delete`, and the
129
+ * one that is safe by construction: a revoked device is already refused, so
130
+ * removing its row cannot restore access to anything.
131
+ *
132
+ * Returns the number of rows removed.
133
+ */
134
+ deleteRevoked(): number;
135
+ touch(deviceId: string, now?: number): void;
136
+ }
137
+ //# sourceMappingURL=devices.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devices.repository.d.ts","sourceRoot":"","sources":["../../../src/db/repositories/devices.repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,127 @@
1
+ import type Database from "better-sqlite3";
2
+ import type { ManagedSession, SessionStatus } from "../../types";
3
+ /**
4
+ * Durable registry of managed sessions (C1 Phase 2).
5
+ * See docs/architecture/2026-07-24-durable-session-runtime.md.
6
+ *
7
+ * Distinct from SessionsRepository, which wraps the in-memory SessionStore for
8
+ * the live request path. This one exists so session identity and provenance
9
+ * outlive the streamer process: without it, a restart loses startedAt,
10
+ * promptCount, sessionName, the Codex rollout binding, and failureReason, and
11
+ * the boot reconciler has nothing to reconcile against.
12
+ *
13
+ * Deliberately not stored here: the PTY output ring buffer and xterm screen.
14
+ * Their authoritative copy is the provider's JSONL, and writing 64KiB of ANSI
15
+ * on every chunk to duplicate it would be a write storm for no gain.
16
+ */
17
+ /** How a persisted status was obtained — never inferred, always recorded. */
18
+ export type StatusSource = "spawn" | "transition" | "exit" | "shutdown" | "probe" | "reconcile";
19
+ export type { SessionLifecycle } from "../../types";
20
+ export interface ManagedSessionRow {
21
+ session_id: string;
22
+ provider: string;
23
+ pid: number | null;
24
+ cmdline: string | null;
25
+ project_path: string;
26
+ project_name: string;
27
+ branch: string;
28
+ status: string;
29
+ status_source: string;
30
+ status_updated_at: number;
31
+ started_at: number;
32
+ completed_at: number | null;
33
+ last_activity_at: number | null;
34
+ prompt_count: number;
35
+ session_name: string | null;
36
+ project_id: string | null;
37
+ bound_conversation_id: string | null;
38
+ resumed_from_conversation_id: string | null;
39
+ failure_reason: string | null;
40
+ streamer_instance_id: string;
41
+ /**
42
+ * Which machine boot `pid` was recorded during (migration 002). Optional
43
+ * because rows written before it exists read back as null/absent, which the
44
+ * reconciler treats exactly like a mismatch — never like a match.
45
+ */
46
+ boot_token?: string | null;
47
+ }
48
+ /** Most rows the boot reconciler will probe in one pass. */
49
+ export declare const PROBE_SET_MAX = 200;
50
+ /** Most rows one diagnostics report will carry. */
51
+ export declare const DIAGNOSTICS_MAX = 200;
52
+ /** How long a finished session stays in the registry as history. */
53
+ export declare const TERMINAL_RETENTION_MS: number;
54
+ export interface RecordSpawnInput {
55
+ session: ManagedSession;
56
+ pid: number | null;
57
+ cmdline: string | null;
58
+ streamerInstanceId: string;
59
+ }
60
+ export declare class ManagedSessionsRepository {
61
+ private upsertStmt;
62
+ private updateStatusStmt;
63
+ private bindStmt;
64
+ private getStmt;
65
+ private listNonTerminalStmt;
66
+ private listAllStmt;
67
+ private pruneTerminalStmt;
68
+ private listRecoverableStmt;
69
+ private deleteStmt;
70
+ constructor(db: Database.Database);
71
+ /** Record a session at spawn, or refresh every field of an existing row. */
72
+ recordSpawn({ session, pid, cmdline, streamerInstanceId }: RecordSpawnInput): void;
73
+ /**
74
+ * Persist a status transition. `source` is required rather than defaulted:
75
+ * a status whose provenance is unknown is the thing this table exists to
76
+ * prevent, and the reconciler reads it to decide how much to trust the value.
77
+ */
78
+ recordStatus(sessionId: string, status: SessionStatus, source: StatusSource, fields?: {
79
+ completedAt?: Date | null;
80
+ lastActivityAt?: Date | null;
81
+ promptCount?: number;
82
+ failureReason?: string | null;
83
+ /** Null/omitted keeps whatever is stored — it never clears a known name. */
84
+ sessionName?: string | null;
85
+ }): void;
86
+ /**
87
+ * Persist the Codex rollout id discovered after spawn.
88
+ *
89
+ * Its own statement rather than a `recordSpawn` re-run: the binding arrives
90
+ * while the session is live, and re-upserting would also rewrite `cmdline`
91
+ * with an id that is *not* in a fresh Codex process's argv, turning the
92
+ * reconciler's identity check into a false `orphaned`. Without this write the
93
+ * binding lives only in memory and dies with the streamer — which is the
94
+ * whole reason a restarted Codex session could not be resumed (G6).
95
+ */
96
+ recordBinding(sessionId: string, boundConversationId: string): void;
97
+ get(sessionId: string): ManagedSessionRow | null;
98
+ /**
99
+ * Rows with no recorded completion — the reconciler's probe set.
100
+ *
101
+ * Capped. Callers must compare the result length against the limit and say so
102
+ * when it clips: a silently truncated probe set reads as "we checked
103
+ * everything" when it did not.
104
+ */
105
+ listNonTerminal(limit?: number): ManagedSessionRow[];
106
+ /** Every row, most recently touched first, for the diagnostics surface. */
107
+ listAll(limit?: number): ManagedSessionRow[];
108
+ /**
109
+ * Delete terminal rows older than `olderThanMs`, returning how many went.
110
+ *
111
+ * Only rows carrying a `completed_at` are eligible, so nothing the reconciler
112
+ * or rehydrator might still want is reachable from here — a row without one
113
+ * is by definition unfinished business, however old it looks.
114
+ */
115
+ pruneTerminal(olderThanMs?: number): number;
116
+ /**
117
+ * Rows a restart could bring back: still open, or closed by our own shutdown,
118
+ * and touched no longer ago than `sinceMs`. Newest first, capped — the caller
119
+ * decides which of these actually deserve rehydrating (`shouldRehydrate`).
120
+ */
121
+ listRecoverable({ sinceMs, limit }: {
122
+ sinceMs: number;
123
+ limit: number;
124
+ }): ManagedSessionRow[];
125
+ delete(sessionId: string): void;
126
+ }
127
+ //# sourceMappingURL=managed-sessions.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"managed-sessions.repository.d.ts","sourceRoot":"","sources":["../../../src/db/repositories/managed-sessions.repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type Database from "better-sqlite3";
2
+ import type { Project } from "../../schemas/project.schema";
3
+ export interface UpsertProjectInput {
4
+ lastConversationId?: string | null;
5
+ lastConversationCreatedAt?: string | null;
6
+ latestMessageAt?: string | null;
7
+ latestMessageId?: string | null;
8
+ name?: string | null;
9
+ }
10
+ export declare class ProjectsRepository {
11
+ private getByPath;
12
+ private getById;
13
+ private listAll;
14
+ private insert;
15
+ private update;
16
+ constructor(db: Database.Database);
17
+ getProjectByPath(rawPath: string): Project | null;
18
+ getProjectById(id: string): Project | null;
19
+ listProjects(): Project[];
20
+ /**
21
+ * Insert a project at the given canonical path, or update its metadata
22
+ * if one already exists. Returns the persisted Project row.
23
+ *
24
+ * Idempotent: passing the same path twice returns the same project id.
25
+ */
26
+ upsertProjectByPath(rawPath: string, input?: UpsertProjectInput): Project;
27
+ }
28
+ //# sourceMappingURL=projects.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.repository.d.ts","sourceRoot":"","sources":["../../../src/db/repositories/projects.repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AA+B5D,MAAM,WAAW,kBAAkB;IACjC,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,yBAAyB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAqB;IAEnC,YAAY,EAAE,EAAE,QAAQ,CAAC,QAAQ,EA4BhC;IAED,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAIhD;IAED,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,CAGzC;IAED,YAAY,IAAI,OAAO,EAAE,CAExB;IAED;;;;;OAKG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,GAAE,kBAAuB,GAAG,OAAO,CAiC5E;CACF"}
@@ -0,0 +1,186 @@
1
+ import type Database from "better-sqlite3";
2
+ /**
3
+ * Push registration and delivery state (C7).
4
+ *
5
+ * `POST /api/push/register` was a no-op returning `{ ok: true }`. Mobile
6
+ * registered, received success, and nothing was stored — so no notification
7
+ * could ever be delivered, no failure could be observed, and the client had no
8
+ * way to discover that its successful registration meant nothing.
9
+ *
10
+ * This records tokens and what happened to them, which is the prerequisite for
11
+ * every other C7 requirement: token health, last success/failure, retries,
12
+ * revocation confirmation, and a test-notification endpoint all need somewhere
13
+ * to read state from.
14
+ */
15
+ /**
16
+ * Consecutive failures after which a token is treated as dead.
17
+ *
18
+ * A provider rejecting a token repeatedly means the app was uninstalled or the
19
+ * token rotated. Retrying forever wastes work and, worse, makes the health
20
+ * report read "failing" indefinitely instead of "this device is gone".
21
+ */
22
+ export declare const FAILURE_STREAK_LIMIT = 5;
23
+ /**
24
+ * Token kinds. A device supplies three non-interchangeable types, and
25
+ * conflating them fails only at send time with no signal at registration:
26
+ *
27
+ * - `expo` — Expo relay token, for ordinary push notifications.
28
+ * - `liveactivity_start` — ActivityKit push-to-start token. App-wide, one per
29
+ * device, long-lived. Starts an activity when none exists.
30
+ * - `liveactivity_update` — ActivityKit per-activity update token, issued by
31
+ * iOS after an activity starts, scoped to that one activity, short-lived.
32
+ */
33
+ export declare const PUSH_TOKEN_KINDS: readonly ["expo", "liveactivity_start", "liveactivity_update"];
34
+ export type PushTokenKind = (typeof PUSH_TOKEN_KINDS)[number];
35
+ /**
36
+ * The kind assumed when a client does not send one.
37
+ *
38
+ * tb-mobile is released and cannot be force-updated, so an older client posting
39
+ * `{ token, platform }` must keep working. Every such client is registering an
40
+ * Expo relay token, because that is the only kind that existed then.
41
+ */
42
+ export declare const DEFAULT_PUSH_TOKEN_KIND: PushTokenKind;
43
+ export declare function isPushTokenKind(value: unknown): value is PushTokenKind;
44
+ export interface PushTokenRow {
45
+ token: string;
46
+ platform: string;
47
+ device_id: string | null;
48
+ registered_at: number;
49
+ last_success_at: number | null;
50
+ last_failure_at: number | null;
51
+ last_failure_code: string | null;
52
+ failure_streak: number;
53
+ revoked_at: number | null;
54
+ kind: PushTokenKind;
55
+ activity_id: string | null;
56
+ session_id: string | null;
57
+ expires_at: number | null;
58
+ stale_date: number | null;
59
+ started_at: number | null;
60
+ renewed_at: number | null;
61
+ }
62
+ /**
63
+ * Health as reported to a client. Deliberately omits the token itself — a push
64
+ * token is a delivery credential, and a health endpoint has no reason to echo
65
+ * one back.
66
+ */
67
+ export interface PushTokenHealth {
68
+ platform: string;
69
+ deviceId: string | null;
70
+ registeredAt: number;
71
+ lastSuccessAt: number | null;
72
+ lastFailureAt: number | null;
73
+ lastFailureCode: string | null;
74
+ failureStreak: number;
75
+ revokedAt: number | null;
76
+ /**
77
+ * Never delivered vs delivering vs failing vs revoked vs expired. The
78
+ * distinction the user actually needs: "not yet" and "broken" look identical
79
+ * without it.
80
+ */
81
+ state: "never-delivered" | "healthy" | "failing" | "dead" | "revoked" | "expired";
82
+ kind: PushTokenKind;
83
+ /** Present only for per-activity Live Activity tokens. */
84
+ activityId: string | null;
85
+ sessionId: string | null;
86
+ expiresAt: number | null;
87
+ }
88
+ export declare function tokenState(row: PushTokenRow, now?: number): PushTokenHealth["state"];
89
+ export declare function toHealth(row: PushTokenRow, now?: number): PushTokenHealth;
90
+ export declare class PushRepository {
91
+ private upsertStmt;
92
+ private getStmt;
93
+ private listActiveStmt;
94
+ private listAllStmt;
95
+ private successStmt;
96
+ private failureStmt;
97
+ private revokeStmt;
98
+ private claimEventStmt;
99
+ private markDeliveredStmt;
100
+ private listByKindSessionStmt;
101
+ private listByKindStmt;
102
+ private listRenewableStmt;
103
+ private claimRenewalStmt;
104
+ private expireStmt;
105
+ private expireSessionActivitiesStmt;
106
+ constructor(db: Database.Database);
107
+ /**
108
+ * Register or refresh a token.
109
+ *
110
+ * `kind` defaults to Expo so a released client posting `{ token, platform }`
111
+ * keeps working — tb-mobile cannot be force-updated, and every client
112
+ * predating Live Activities is registering an Expo relay token.
113
+ *
114
+ * Several rows per device is normal and intended: a device runs one activity
115
+ * per live session, each with its own update token. The token itself is the
116
+ * primary key, so distinct activities never collide.
117
+ */
118
+ register(args: {
119
+ token: string;
120
+ platform: string;
121
+ deviceId?: string | null;
122
+ kind?: PushTokenKind;
123
+ activityId?: string | null;
124
+ sessionId?: string | null;
125
+ expiresAt?: number | null;
126
+ staleDate?: number | null;
127
+ startedAt?: number | null;
128
+ now?: number;
129
+ }): void;
130
+ get(token: string): PushTokenRow | null;
131
+ /**
132
+ * Expo tokens eligible for delivery — not revoked, not past the failure limit.
133
+ *
134
+ * Deliberately Expo-only. ActivityKit tokens go over direct APNs with a
135
+ * different topic and are rejected by Expo's relay, so the ordinary
136
+ * notification fan-out must not see them.
137
+ */
138
+ listDeliverable(): PushTokenRow[];
139
+ /** Live-activity tokens for one session, eligible for delivery. */
140
+ listForSession(kind: PushTokenKind, sessionId: string, now?: number): PushTokenRow[];
141
+ /**
142
+ * Every deliverable token of one kind.
143
+ *
144
+ * Used for push-to-start, which is app-wide rather than session-scoped: the
145
+ * activity does not exist yet, so there is no per-activity token to look up.
146
+ */
147
+ listByKind(kind: PushTokenKind, now?: number): PushTokenRow[];
148
+ /** Unrenewed activities with a renewal deadline, soonest first. */
149
+ listRenewable(): PushTokenRow[];
150
+ /**
151
+ * Claim a row for renewal.
152
+ *
153
+ * Returns true exactly once per row. A restart re-arms timers from the
154
+ * persisted deadline, so the same renewal can be attempted twice; the loser
155
+ * gets false and must not send. Doing this as a conditional UPDATE rather
156
+ * than read-then-write avoids the race where both attempts observe
157
+ * "not yet renewed".
158
+ */
159
+ claimRenewal(token: string, now?: number): boolean;
160
+ /** Mark one token expired, so it stops being a delivery target. */
161
+ expire(token: string, now?: number): void;
162
+ /**
163
+ * Expire every live activity for a session.
164
+ *
165
+ * Called when the session ends. Without this, a per-activity token outlives
166
+ * its session and a later renewal sweep would resurrect an activity for a
167
+ * session that is already gone.
168
+ */
169
+ expireSessionActivities(sessionId: string, now?: number): void;
170
+ /** Every token, including dead and revoked ones, for the health report. */
171
+ listHealth(now?: number): PushTokenHealth[];
172
+ recordSuccess(token: string, now?: number): void;
173
+ recordFailure(token: string, code: string, now?: number): void;
174
+ revoke(token: string, now?: number): boolean;
175
+ /**
176
+ * Claim an event id for delivery.
177
+ *
178
+ * Returns true exactly once per event id. A retry, a reconnect
179
+ * reconciliation, or two triggers firing for the same underlying event all
180
+ * get false and must not notify — the user should never be told twice about
181
+ * one thing.
182
+ */
183
+ claimEvent(eventId: string, sessionId: string | null, now?: number): boolean;
184
+ markDelivered(eventId: string, now?: number): void;
185
+ }
186
+ //# sourceMappingURL=push.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push.repository.d.ts","sourceRoot":"","sources":["../../../src/db/repositories/push.repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C;;;;;;;;;;;;GAYG;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,YAAI,MAAM,EAAE,oBAAoB,EAAE,qBAAqB,CAAU,CAAC;AAE/F,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE9D;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,EAAE,aAAsB,CAAC;AAE7D,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB;;;;OAIG;IACH,KAAK,EAAE,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IAClF,IAAI,EAAE,aAAa,CAAC;IACpB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe,CAAC,OAAO,CAAC,CAUhG;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe,CAgBrF;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,qBAAqB,CAAqB;IAClD,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,iBAAiB,CAAqB;IAC9C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,UAAU,CAAqB;IACvC,OAAO,CAAC,2BAA2B,CAAqB;IAExD,YAAY,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAkHhC;IAED;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,IAAI,EAAE;QACb,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,EAAE,aAAa,CAAC;QACrB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,GAAG,IAAI,CAaP;IAED,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAEtC;IAED;;;;;;OAMG;IACH,eAAe,IAAI,YAAY,EAAE,CAEhC;IAED,mEAAmE;IACnE,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,YAAY,EAAE,CAM/F;IAED;;;;;OAKG;IACH,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,GAAE,MAAmB,GAAG,YAAY,EAAE,CAExE;IAED,mEAAmE;IACnE,aAAa,IAAI,YAAY,EAAE,CAE9B;IAED;;;;;;;;OAQG;IACH,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAE7D;IAED,mEAAmE;IACnE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAEpD;IAED;;;;;;OAMG;IACH,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAEzE;IAED,2EAA2E;IAC3E,UAAU,CAAC,GAAG,GAAE,MAAmB,GAAG,eAAe,EAAE,CAEtD;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAE3D;IAED,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAEzE;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAEvD;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,GAAE,MAAmB,GAAG,OAAO,CAKvF;IAED,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,IAAI,CAE7D;CACF"}
@@ -0,0 +1,16 @@
1
+ import type { SessionStore } from "../../session-store";
2
+ /**
3
+ * Sessions live in-memory in SessionStore (Postgres-backed persistence
4
+ * was dropped per the SQLite-only direction). This repository wraps the
5
+ * store with a stable, project-id-aware API for the new services.
6
+ */
7
+ export declare class SessionsRepository {
8
+ private store;
9
+ constructor(store: SessionStore);
10
+ updateSessionProjectId(args: {
11
+ sessionId: string;
12
+ projectId: string;
13
+ }): void;
14
+ listManagedSessions(): import("../..").ManagedSession[];
15
+ }
16
+ //# sourceMappingURL=sessions.repository.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.repository.d.ts","sourceRoot":"","sources":["../../../src/db/repositories/sessions.repository.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAExD;;;;GAIG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,KAAK;IAAzB,YAAoB,KAAK,EAAE,YAAY,EAAI;IAE3C,sBAAsB,CAAC,IAAI,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAE3E;IAED,mBAAmB,qCAElB;CACF"}
@@ -0,0 +1,80 @@
1
+ import Database from "better-sqlite3";
2
+ /**
3
+ * Where runtime.db lives: explicit override, then the test hook, then a sibling
4
+ * of server.yaml — deliberately NOT under cache/, for the reasons below.
5
+ *
6
+ * Exported because both StreamerServer and the CLI's `devices` command need to
7
+ * agree on it, and a second hand-written copy of this precedence chain would
8
+ * drift the moment one of the three sources changed.
9
+ */
10
+ export declare function resolveRuntimeDbPath(override?: string): string;
11
+ /**
12
+ * `~/.threadbase/runtime.db` — the authoritative, non-derived half of the
13
+ * streamer's SQLite state.
14
+ *
15
+ * Deliberately a separate file from `cache/cache.db`, and deliberately not
16
+ * under `cache/`. The conversation cache is rebuildable from the provider
17
+ * JSONLs at any time, which is why "delete the cache and restart" is reasonable
18
+ * support advice and why the integrity monitor offers a reset-and-rescan
19
+ * action. The managed-session registry is not rebuildable from anything on
20
+ * disk, so it must not sit one plausible instruction away from deletion — nor
21
+ * share a handle whose failure (a better-sqlite3 ABI mismatch, most commonly)
22
+ * would silently disable session persistence along with the cache.
23
+ *
24
+ * Runs its own migrations from `src/db/runtime-migrations/`, tracked in this
25
+ * file's own `schema_migrations` table.
26
+ */
27
+ export declare class RuntimeStore {
28
+ private readonly db;
29
+ private constructor();
30
+ static open(dbPath: string, migrationsDir?: string): RuntimeStore;
31
+ getDatabase(): Database.Database;
32
+ /**
33
+ * One-time move of `managed_sessions` rows out of a pre-split `cache.db`.
34
+ *
35
+ * Returns the number of rows copied.
36
+ */
37
+ importLegacyManagedSessions(source: Database.Database): number;
38
+ /**
39
+ * One-time move of `devices` rows out of `cache.db`, where the registry used
40
+ * to live (migration `011_create_devices.sql`).
41
+ *
42
+ * Losing this table invalidates every device token ever issued, and cache.db
43
+ * is the file `tb-streamer cache clear` deletes and the integrity monitor
44
+ * rebuilds — see `runtime-migrations/003_create_devices.sql`.
45
+ *
46
+ * Unlike `managed_sessions`, this one MOVES rather than copies: the source
47
+ * rows are deleted once the copy is verified. A `devices` row carries a
48
+ * user-supplied label ("Ronen's iPhone"), and leaving a second copy of that
49
+ * on disk indefinitely — in the one file the user is told to delete when
50
+ * something goes wrong — is more retained personal data than the rollback
51
+ * path is worth. Recovering from a rollback is re-scanning a pairing QR.
52
+ *
53
+ * The delete is conditional on the copy being complete: `INSERT OR IGNORE`
54
+ * can silently skip a row, so the destination count must match what was read
55
+ * before anything is removed. A mismatch keeps the source and reports
56
+ * `purged: false` rather than throwing — the import itself still succeeded,
57
+ * and keeping data is the safe direction to fail in.
58
+ */
59
+ importLegacyDevices(source: Database.Database): {
60
+ copied: number;
61
+ purged: boolean;
62
+ };
63
+ /**
64
+ * Copy a whole table out of a pre-split `cache.db` into this file.
65
+ *
66
+ * The copy itself is non-destructive — the source is left in place, so an
67
+ * older streamer rolled back onto the same machine still finds its data.
68
+ * `importLegacyDevices` deletes the source afterwards for its own reasons;
69
+ * `managed_sessions` does not. Runs only when this file's table is empty, so
70
+ * a second boot is a no-op rather than a re-copy that would resurrect rows
71
+ * deleted since.
72
+ *
73
+ * The table name is interpolated into SQL, so it is typed as a closed union
74
+ * rather than `string` — the set of tables that can ever be lifted is known
75
+ * at compile time, and that is what keeps a caller from making this a hole.
76
+ */
77
+ private importLegacyTable;
78
+ close(): void;
79
+ }
80
+ //# sourceMappingURL=runtime-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-store.d.ts","sourceRoot":"","sources":["../../src/db/runtime-store.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAMtC;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAM9D;AAED;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAY;IACH,OAAO,CAAC,QAAQ,CAAC,EAAE;IAAvC,OAAO,eAAuD;IAE9D,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,YAAY,CAKhE;IAED,WAAW,IAAI,QAAQ,CAAC,QAAQ,CAE/B;IAED;;;;OAIG;IACH,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,GAAG,MAAM,CAE7D;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,QAAQ,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAalF;IAED;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,iBAAiB;IA8BzB,KAAK,IAAI,IAAI,CAEZ;CACF"}
@@ -0,0 +1,13 @@
1
+ import type Database from "better-sqlite3";
2
+ /**
3
+ * Resolve a migrations directory that sits next to this module in both the
4
+ * source tree (`src/db/<name>`) and the bundle (`dist/<name>`, populated by the
5
+ * build's copy step).
6
+ */
7
+ export declare function resolveMigrationsDir(name?: string): string;
8
+ export interface SqliteMigrationRunResult {
9
+ applied: string[];
10
+ skipped: string[];
11
+ }
12
+ export declare function runSqliteMigrations(db: Database.Database, migrationsDir?: string): SqliteMigrationRunResult;
13
+ //# sourceMappingURL=sqlite-migrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-migrate.d.ts","sourceRoot":"","sources":["../../src/db/sqlite-migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAY3C;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,SAAe,GAAG,MAAM,CAEhE;AASD,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,wBAAgB,mBAAmB,CACjC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,aAAa,CAAC,EAAE,MAAM,GACrB,wBAAwB,CA+B1B"}
@@ -0,0 +1,11 @@
1
+ import type pg from "pg";
2
+ export interface UploadRecord {
3
+ id: string;
4
+ sessionId: string;
5
+ filePath: string;
6
+ originalName: string;
7
+ mimeType: string;
8
+ sizeBytes: number;
9
+ }
10
+ export declare function recordUpload(pool: pg.Pool | null, instanceId: string | null, row: UploadRecord): Promise<void>;
11
+ //# sourceMappingURL=upload-records.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload-records.d.ts","sourceRoot":"","sources":["../../src/db/upload-records.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,IAAI,EACpB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,GAAG,EAAE,YAAY,GAChB,OAAO,CAAC,IAAI,CAAC,CAgBf"}