life-as-api 0.2.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 (303) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +377 -0
  3. package/dist/agent/finance-agent.d.ts +44 -0
  4. package/dist/agent/finance-agent.js +75 -0
  5. package/dist/agent/finance-agent.js.map +1 -0
  6. package/dist/agent/legal-agent.d.ts +44 -0
  7. package/dist/agent/legal-agent.js +76 -0
  8. package/dist/agent/legal-agent.js.map +1 -0
  9. package/dist/agent/medical-agent.d.ts +44 -0
  10. package/dist/agent/medical-agent.js +75 -0
  11. package/dist/agent/medical-agent.js.map +1 -0
  12. package/dist/agent/trusted-agent-registry.d.ts +53 -0
  13. package/dist/agent/trusted-agent-registry.js +57 -0
  14. package/dist/agent/trusted-agent-registry.js.map +1 -0
  15. package/dist/audit/audit-chain-verifier.d.ts +10 -0
  16. package/dist/audit/audit-chain-verifier.js +67 -0
  17. package/dist/audit/audit-chain-verifier.js.map +1 -0
  18. package/dist/audit/audit-log.d.ts +48 -0
  19. package/dist/audit/audit-log.js +74 -0
  20. package/dist/audit/audit-log.js.map +1 -0
  21. package/dist/audit/sqlite-audit-log.d.ts +29 -0
  22. package/dist/audit/sqlite-audit-log.js +142 -0
  23. package/dist/audit/sqlite-audit-log.js.map +1 -0
  24. package/dist/auth/access-context-issuer.d.ts +18 -0
  25. package/dist/auth/access-context-issuer.js +88 -0
  26. package/dist/auth/access-context-issuer.js.map +1 -0
  27. package/dist/auth/assert-authorized-for-subject.d.ts +2 -0
  28. package/dist/auth/assert-authorized-for-subject.js +20 -0
  29. package/dist/auth/assert-authorized-for-subject.js.map +1 -0
  30. package/dist/auth/backend-context-minting-boundary.d.ts +23 -0
  31. package/dist/auth/backend-context-minting-boundary.js +281 -0
  32. package/dist/auth/backend-context-minting-boundary.js.map +1 -0
  33. package/dist/auth/default-authorization-policy.d.ts +7 -0
  34. package/dist/auth/default-authorization-policy.js +64 -0
  35. package/dist/auth/default-authorization-policy.js.map +1 -0
  36. package/dist/auth/fake-auth-adapter.d.ts +7 -0
  37. package/dist/auth/fake-auth-adapter.js +27 -0
  38. package/dist/auth/fake-auth-adapter.js.map +1 -0
  39. package/dist/auth/http-client.d.ts +12 -0
  40. package/dist/auth/http-client.js +7 -0
  41. package/dist/auth/http-client.js.map +1 -0
  42. package/dist/auth/in-memory-grant-resolver.d.ts +21 -0
  43. package/dist/auth/in-memory-grant-resolver.js +73 -0
  44. package/dist/auth/in-memory-grant-resolver.js.map +1 -0
  45. package/dist/auth/in-memory-tenant-boundary.d.ts +16 -0
  46. package/dist/auth/in-memory-tenant-boundary.js +37 -0
  47. package/dist/auth/in-memory-tenant-boundary.js.map +1 -0
  48. package/dist/auth/jwks-key-ring-auth-adapter.d.ts +38 -0
  49. package/dist/auth/jwks-key-ring-auth-adapter.js +123 -0
  50. package/dist/auth/jwks-key-ring-auth-adapter.js.map +1 -0
  51. package/dist/auth/jwks-key-ring.d.ts +25 -0
  52. package/dist/auth/jwks-key-ring.js +111 -0
  53. package/dist/auth/jwks-key-ring.js.map +1 -0
  54. package/dist/auth/jwt-auth-adapter.d.ts +15 -0
  55. package/dist/auth/jwt-auth-adapter.js +59 -0
  56. package/dist/auth/jwt-auth-adapter.js.map +1 -0
  57. package/dist/auth/jwt-core.d.ts +32 -0
  58. package/dist/auth/jwt-core.js +226 -0
  59. package/dist/auth/jwt-core.js.map +1 -0
  60. package/dist/auth/jwt-key-ring-auth-adapter.d.ts +16 -0
  61. package/dist/auth/jwt-key-ring-auth-adapter.js +58 -0
  62. package/dist/auth/jwt-key-ring-auth-adapter.js.map +1 -0
  63. package/dist/auth/oidc-discovery.d.ts +15 -0
  64. package/dist/auth/oidc-discovery.js +46 -0
  65. package/dist/auth/oidc-discovery.js.map +1 -0
  66. package/dist/auth/production-scoped-life-api.d.ts +58 -0
  67. package/dist/auth/production-scoped-life-api.js +802 -0
  68. package/dist/auth/production-scoped-life-api.js.map +1 -0
  69. package/dist/auth/proposal-scope-inspector.d.ts +3 -0
  70. package/dist/auth/proposal-scope-inspector.js +42 -0
  71. package/dist/auth/proposal-scope-inspector.js.map +1 -0
  72. package/dist/auth/proposal-scoped-life-api.d.ts +21 -0
  73. package/dist/auth/proposal-scoped-life-api.js +168 -0
  74. package/dist/auth/proposal-scoped-life-api.js.map +1 -0
  75. package/dist/auth/rate-limited-context-minting-boundary.d.ts +27 -0
  76. package/dist/auth/rate-limited-context-minting-boundary.js +77 -0
  77. package/dist/auth/rate-limited-context-minting-boundary.js.map +1 -0
  78. package/dist/auth/revocation-aware-auth-adapter.d.ts +21 -0
  79. package/dist/auth/revocation-aware-auth-adapter.js +88 -0
  80. package/dist/auth/revocation-aware-auth-adapter.js.map +1 -0
  81. package/dist/auth/sqlite-grant-resolver.d.ts +8 -0
  82. package/dist/auth/sqlite-grant-resolver.js +78 -0
  83. package/dist/auth/sqlite-grant-resolver.js.map +1 -0
  84. package/dist/auth/sqlite-tenant-boundary.d.ts +7 -0
  85. package/dist/auth/sqlite-tenant-boundary.js +41 -0
  86. package/dist/auth/sqlite-tenant-boundary.js.map +1 -0
  87. package/dist/auth/static-jwt-key-ring.d.ts +13 -0
  88. package/dist/auth/static-jwt-key-ring.js +73 -0
  89. package/dist/auth/static-jwt-key-ring.js.map +1 -0
  90. package/dist/auth/subject-scoped-life-api.d.ts +14 -0
  91. package/dist/auth/subject-scoped-life-api.js +51 -0
  92. package/dist/auth/subject-scoped-life-api.js.map +1 -0
  93. package/dist/auth/test-context-minting-boundary.d.ts +13 -0
  94. package/dist/auth/test-context-minting-boundary.js +74 -0
  95. package/dist/auth/test-context-minting-boundary.js.map +1 -0
  96. package/dist/auth/types.d.ts +77 -0
  97. package/dist/auth/types.js +16 -0
  98. package/dist/auth/types.js.map +1 -0
  99. package/dist/compliance/subject-data-report.d.ts +43 -0
  100. package/dist/compliance/subject-data-report.js +155 -0
  101. package/dist/compliance/subject-data-report.js.map +1 -0
  102. package/dist/consent/consent-guard.d.ts +4 -0
  103. package/dist/consent/consent-guard.js +37 -0
  104. package/dist/consent/consent-guard.js.map +1 -0
  105. package/dist/consent/grant-registry.d.ts +7 -0
  106. package/dist/consent/grant-registry.js +13 -0
  107. package/dist/consent/grant-registry.js.map +1 -0
  108. package/dist/consent/intersect-selector.d.ts +3 -0
  109. package/dist/consent/intersect-selector.js +66 -0
  110. package/dist/consent/intersect-selector.js.map +1 -0
  111. package/dist/contract/diagnostics.d.ts +32 -0
  112. package/dist/contract/diagnostics.js +112 -0
  113. package/dist/contract/diagnostics.js.map +1 -0
  114. package/dist/contract/project-contracts.d.ts +5 -0
  115. package/dist/contract/project-contracts.js +159 -0
  116. package/dist/contract/project-contracts.js.map +1 -0
  117. package/dist/contract/types.d.ts +32 -0
  118. package/dist/contract/types.js +5 -0
  119. package/dist/contract/types.js.map +1 -0
  120. package/dist/crypto/aes-gcm.d.ts +11 -0
  121. package/dist/crypto/aes-gcm.js +78 -0
  122. package/dist/crypto/aes-gcm.js.map +1 -0
  123. package/dist/crypto/claim-serializer.d.ts +26 -0
  124. package/dist/crypto/claim-serializer.js +59 -0
  125. package/dist/crypto/claim-serializer.js.map +1 -0
  126. package/dist/crypto/sha256.d.ts +12 -0
  127. package/dist/crypto/sha256.js +40 -0
  128. package/dist/crypto/sha256.js.map +1 -0
  129. package/dist/crypto/static-key.d.ts +11 -0
  130. package/dist/crypto/static-key.js +60 -0
  131. package/dist/crypto/static-key.js.map +1 -0
  132. package/dist/crypto/types.d.ts +20 -0
  133. package/dist/crypto/types.js +8 -0
  134. package/dist/crypto/types.js.map +1 -0
  135. package/dist/datasource/trusted-data-source-registry.d.ts +51 -0
  136. package/dist/datasource/trusted-data-source-registry.js +57 -0
  137. package/dist/datasource/trusted-data-source-registry.js.map +1 -0
  138. package/dist/erasure/tombstone.d.ts +13 -0
  139. package/dist/erasure/tombstone.js +20 -0
  140. package/dist/erasure/tombstone.js.map +1 -0
  141. package/dist/evidence/evidence-backed-claim-creator.d.ts +48 -0
  142. package/dist/evidence/evidence-backed-claim-creator.js +107 -0
  143. package/dist/evidence/evidence-backed-claim-creator.js.map +1 -0
  144. package/dist/evidence/in-memory-raw-document-store.d.ts +26 -0
  145. package/dist/evidence/in-memory-raw-document-store.js +84 -0
  146. package/dist/evidence/in-memory-raw-document-store.js.map +1 -0
  147. package/dist/evidence/raw-document-store.d.ts +12 -0
  148. package/dist/evidence/raw-document-store.js +8 -0
  149. package/dist/evidence/raw-document-store.js.map +1 -0
  150. package/dist/evidence/source-evidence-validator.d.ts +4 -0
  151. package/dist/evidence/source-evidence-validator.js +14 -0
  152. package/dist/evidence/source-evidence-validator.js.map +1 -0
  153. package/dist/evidence/sqlite-raw-document-store.d.ts +19 -0
  154. package/dist/evidence/sqlite-raw-document-store.js +122 -0
  155. package/dist/evidence/sqlite-raw-document-store.js.map +1 -0
  156. package/dist/guardian/guardian-registry.d.ts +96 -0
  157. package/dist/guardian/guardian-registry.js +95 -0
  158. package/dist/guardian/guardian-registry.js.map +1 -0
  159. package/dist/index.d.ts +44 -0
  160. package/dist/index.js +72 -0
  161. package/dist/index.js.map +1 -0
  162. package/dist/observability/health.d.ts +12 -0
  163. package/dist/observability/health.js +16 -0
  164. package/dist/observability/health.js.map +1 -0
  165. package/dist/observability/logger.d.ts +21 -0
  166. package/dist/observability/logger.js +40 -0
  167. package/dist/observability/logger.js.map +1 -0
  168. package/dist/observability/metrics.d.ts +15 -0
  169. package/dist/observability/metrics.js +52 -0
  170. package/dist/observability/metrics.js.map +1 -0
  171. package/dist/persistence/backup.d.ts +24 -0
  172. package/dist/persistence/backup.js +251 -0
  173. package/dist/persistence/backup.js.map +1 -0
  174. package/dist/persistence/decryptability-scan.d.ts +10 -0
  175. package/dist/persistence/decryptability-scan.js +144 -0
  176. package/dist/persistence/decryptability-scan.js.map +1 -0
  177. package/dist/persistence/in-memory-unit-of-work.d.ts +11 -0
  178. package/dist/persistence/in-memory-unit-of-work.js +32 -0
  179. package/dist/persistence/in-memory-unit-of-work.js.map +1 -0
  180. package/dist/persistence/key-availability.d.ts +9 -0
  181. package/dist/persistence/key-availability.js +125 -0
  182. package/dist/persistence/key-availability.js.map +1 -0
  183. package/dist/persistence/sqlite/migrations.d.ts +9 -0
  184. package/dist/persistence/sqlite/migrations.js +535 -0
  185. package/dist/persistence/sqlite/migrations.js.map +1 -0
  186. package/dist/persistence/sqlite/schema.d.ts +10 -0
  187. package/dist/persistence/sqlite/schema.js +101 -0
  188. package/dist/persistence/sqlite/schema.js.map +1 -0
  189. package/dist/persistence/sqlite/sqlite-fact-store.d.ts +24 -0
  190. package/dist/persistence/sqlite/sqlite-fact-store.js +207 -0
  191. package/dist/persistence/sqlite/sqlite-fact-store.js.map +1 -0
  192. package/dist/persistence/sqlite/sqlite-source-registry.d.ts +17 -0
  193. package/dist/persistence/sqlite/sqlite-source-registry.js +132 -0
  194. package/dist/persistence/sqlite/sqlite-source-registry.js.map +1 -0
  195. package/dist/persistence/sqlite/sqlite-unit-of-work.d.ts +8 -0
  196. package/dist/persistence/sqlite/sqlite-unit-of-work.js +41 -0
  197. package/dist/persistence/sqlite/sqlite-unit-of-work.js.map +1 -0
  198. package/dist/persistence/sqlite/types.d.ts +24 -0
  199. package/dist/persistence/sqlite/types.js +28 -0
  200. package/dist/persistence/sqlite/types.js.map +1 -0
  201. package/dist/persistence/unit-of-work.d.ts +6 -0
  202. package/dist/persistence/unit-of-work.js +15 -0
  203. package/dist/persistence/unit-of-work.js.map +1 -0
  204. package/dist/proposal/accepted-claim-appender.d.ts +7 -0
  205. package/dist/proposal/accepted-claim-appender.js +16 -0
  206. package/dist/proposal/accepted-claim-appender.js.map +1 -0
  207. package/dist/proposal/in-memory-proposal-queue.d.ts +21 -0
  208. package/dist/proposal/in-memory-proposal-queue.js +218 -0
  209. package/dist/proposal/in-memory-proposal-queue.js.map +1 -0
  210. package/dist/proposal/policy-aware-proposal-queue.d.ts +23 -0
  211. package/dist/proposal/policy-aware-proposal-queue.js +162 -0
  212. package/dist/proposal/policy-aware-proposal-queue.js.map +1 -0
  213. package/dist/proposal/proposal-policy.d.ts +37 -0
  214. package/dist/proposal/proposal-policy.js +72 -0
  215. package/dist/proposal/proposal-policy.js.map +1 -0
  216. package/dist/proposal/proposal-queue.d.ts +13 -0
  217. package/dist/proposal/proposal-queue.js +15 -0
  218. package/dist/proposal/proposal-queue.js.map +1 -0
  219. package/dist/proposal/source-aware-claim-appender.d.ts +13 -0
  220. package/dist/proposal/source-aware-claim-appender.js +47 -0
  221. package/dist/proposal/source-aware-claim-appender.js.map +1 -0
  222. package/dist/proposal/sqlite-proposal-queue.d.ts +26 -0
  223. package/dist/proposal/sqlite-proposal-queue.js +282 -0
  224. package/dist/proposal/sqlite-proposal-queue.js.map +1 -0
  225. package/dist/resolution/resolve-claims.d.ts +4 -0
  226. package/dist/resolution/resolve-claims.js +101 -0
  227. package/dist/resolution/resolve-claims.js.map +1 -0
  228. package/dist/resolution/trust-profile.d.ts +12 -0
  229. package/dist/resolution/trust-profile.js +23 -0
  230. package/dist/resolution/trust-profile.js.map +1 -0
  231. package/dist/resolution/types.d.ts +15 -0
  232. package/dist/resolution/types.js +8 -0
  233. package/dist/resolution/types.js.map +1 -0
  234. package/dist/sdk/create-backend-integrated-life-api-for-test.d.ts +23 -0
  235. package/dist/sdk/create-backend-integrated-life-api-for-test.js +240 -0
  236. package/dist/sdk/create-backend-integrated-life-api-for-test.js.map +1 -0
  237. package/dist/sdk/create-life-api.d.ts +55 -0
  238. package/dist/sdk/create-life-api.js +251 -0
  239. package/dist/sdk/create-life-api.js.map +1 -0
  240. package/dist/sdk/create-sqlite-life-api.d.ts +33 -0
  241. package/dist/sdk/create-sqlite-life-api.js +654 -0
  242. package/dist/sdk/create-sqlite-life-api.js.map +1 -0
  243. package/dist/sdk/life-api.d.ts +27 -0
  244. package/dist/sdk/life-api.js +17 -0
  245. package/dist/sdk/life-api.js.map +1 -0
  246. package/dist/sdk/validation.d.ts +8 -0
  247. package/dist/sdk/validation.js +216 -0
  248. package/dist/sdk/validation.js.map +1 -0
  249. package/dist/source/in-memory-source-registry.d.ts +15 -0
  250. package/dist/source/in-memory-source-registry.js +104 -0
  251. package/dist/source/in-memory-source-registry.js.map +1 -0
  252. package/dist/source/source-aware-fact-store.d.ts +19 -0
  253. package/dist/source/source-aware-fact-store.js +40 -0
  254. package/dist/source/source-aware-fact-store.js.map +1 -0
  255. package/dist/source/source-kind-predicate-policy.d.ts +4 -0
  256. package/dist/source/source-kind-predicate-policy.js +62 -0
  257. package/dist/source/source-kind-predicate-policy.js.map +1 -0
  258. package/dist/source/source-registry.d.ts +11 -0
  259. package/dist/source/source-registry.js +12 -0
  260. package/dist/source/source-registry.js.map +1 -0
  261. package/dist/store/in-memory-fact-store.d.ts +25 -0
  262. package/dist/store/in-memory-fact-store.js +192 -0
  263. package/dist/store/in-memory-fact-store.js.map +1 -0
  264. package/dist/surface/context-query.d.ts +21 -0
  265. package/dist/surface/context-query.js +113 -0
  266. package/dist/surface/context-query.js.map +1 -0
  267. package/dist/surface/evidence-backed-context-query.d.ts +62 -0
  268. package/dist/surface/evidence-backed-context-query.js +240 -0
  269. package/dist/surface/evidence-backed-context-query.js.map +1 -0
  270. package/dist/types/access-context.d.ts +25 -0
  271. package/dist/types/access-context.js +6 -0
  272. package/dist/types/access-context.js.map +1 -0
  273. package/dist/types/claim.d.ts +48 -0
  274. package/dist/types/claim.js +5 -0
  275. package/dist/types/claim.js.map +1 -0
  276. package/dist/types/consent.d.ts +41 -0
  277. package/dist/types/consent.js +3 -0
  278. package/dist/types/consent.js.map +1 -0
  279. package/dist/types/crypto-boundary.d.ts +12 -0
  280. package/dist/types/crypto-boundary.js +15 -0
  281. package/dist/types/crypto-boundary.js.map +1 -0
  282. package/dist/types/evidence.d.ts +31 -0
  283. package/dist/types/evidence.js +8 -0
  284. package/dist/types/evidence.js.map +1 -0
  285. package/dist/types/fact-store.d.ts +24 -0
  286. package/dist/types/fact-store.js +12 -0
  287. package/dist/types/fact-store.js.map +1 -0
  288. package/dist/types/ids.d.ts +36 -0
  289. package/dist/types/ids.js +11 -0
  290. package/dist/types/ids.js.map +1 -0
  291. package/dist/types/proposal.d.ts +38 -0
  292. package/dist/types/proposal.js +7 -0
  293. package/dist/types/proposal.js.map +1 -0
  294. package/dist/types/source.d.ts +33 -0
  295. package/dist/types/source.js +6 -0
  296. package/dist/types/source.js.map +1 -0
  297. package/dist/types/trust.d.ts +24 -0
  298. package/dist/types/trust.js +5 -0
  299. package/dist/types/trust.js.map +1 -0
  300. package/dist/utilities/deep-freeze.d.ts +1 -0
  301. package/dist/utilities/deep-freeze.js +17 -0
  302. package/dist/utilities/deep-freeze.js.map +1 -0
  303. package/package.json +55 -0
@@ -0,0 +1,535 @@
1
+ // SQLite schema migration runner.
2
+ //
3
+ // SQLITE_MIGRATION_RUNNER_EXISTS_001: single authoritative source for schema history.
4
+ // initializeSchema() in schema.ts delegates here.
5
+ // SQLITE_SCHEMA_VERSION_TRACKED_001: 'migration_version' (numeric) in schema_meta tracks
6
+ // the last completed step; 'schema_version' (string) is preserved for legacy readers.
7
+ // SQLITE_MIGRATIONS_IDEMPOTENT_001: re-running on an up-to-date DB is a no-op.
8
+ // SQLITE_MIGRATIONS_RUN_IN_TRANSACTION_001: all pending steps are in one transaction.
9
+ // SQLITE_MIGRATION_FAILS_CLOSED_ON_UNKNOWN_FUTURE_VERSION_001: future version → throw.
10
+ // SQLITE_MIGRATION_DDL_NO_PAYLOAD_LEAK_001: DDL contains no crypto or payload material.
11
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_NOT_ASSUMED_CURRENT_001: absent migration_version never
12
+ // silently assumes fully migrated — structural verification is always required.
13
+ // SQLITE_MIGRATION_CURRENT_SCHEMA_STRUCTURAL_VERIFY_001: structural verification runs at
14
+ // the end of every runMigrations call, even when migration_version already equals current.
15
+ import { sha256hexSync } from "../../crypto/sha256.js";
16
+ import { buildChainCanonical } from "../../audit/sqlite-audit-log.js";
17
+ // SQLITE_MIGRATION_RUNNER_EXISTS_001
18
+ // PROPOSAL_QUEUE_SCHEMA_ENCRYPTED_PAYLOAD_001 ✅ Production-06a
19
+ // PRODUCTION_AUDIT_C4_HASH_CHAIN_SEQUENCE_001 ✅ Audit Hardening C4 (v9)
20
+ // GUARDIAN_AUDIT_MARKED_001 ✅ Platform-03 Guardianship (v10): acting_as_guardian, ward_id
21
+ export const CURRENT_SCHEMA_VERSION = 10;
22
+ // ─── Error codes ──────────────────────────────────────────────────────────────
23
+ const FAIL_CLOSED_CODE = "SQLITE_MIGRATION_FAILS_CLOSED_ON_UNKNOWN_FUTURE_VERSION_001";
24
+ const LEGACY_INCOMPLETE_CODE = "SQLITE_MIGRATION_LEGACY_SCHEMA_INCOMPLETE_001";
25
+ const VERIFY_FAILED_CODE = "SQLITE_MIGRATION_CURRENT_SCHEMA_VERIFY_FAILED_001";
26
+ // ─── Structural verification constants ───────────────────────────────────────
27
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_NOT_ASSUMED_CURRENT_001: these are the ground-truth
28
+ // requirements. A DB is only treated as current when it passes all of these checks.
29
+ const REQUIRED_TABLES = [
30
+ "schema_meta",
31
+ "claims",
32
+ "sources",
33
+ "raw_documents",
34
+ "audit_events",
35
+ "auth_tenant_memberships",
36
+ "auth_grants",
37
+ "proposals",
38
+ ];
39
+ const REQUIRED_COLUMNS = {
40
+ sources: [
41
+ "id", "kind", "label", "status", "created_at", "created_by",
42
+ "evidence_id", "evidence_uri", "evidence_hash", "evidence_mime", "evidence_enc",
43
+ "metadata",
44
+ ],
45
+ raw_documents: [
46
+ "id", "mime_type", "byte_length", "label",
47
+ "created_at", "created_by", "encrypted_blob", "metadata",
48
+ ],
49
+ audit_events: [
50
+ "id", "recorded_at", "actor", "grant_id", "purpose", "decision",
51
+ "reason_code", "selector_fingerprint", "result_count", "result_claim_ids",
52
+ "contract_ids",
53
+ // PRODUCTION_AUDIT_C4_HASH_CHAIN_SEQUENCE_001 (v9)
54
+ "sequence", "prev_hash", "event_hash",
55
+ // GUARDIAN_AUDIT_MARKED_001 (v10)
56
+ "acting_as_guardian", "ward_id",
57
+ ],
58
+ auth_tenant_memberships: [
59
+ "tenant_id", "person_id", "status", "created_at", "updated_at",
60
+ ],
61
+ auth_grants: [
62
+ "grant_id", "agent_id", "tenant_id", "status",
63
+ "not_before", "not_after", "person_id", "created_at", "updated_at",
64
+ ],
65
+ // PROPOSAL_QUEUE_SCHEMA_ENCRYPTED_PAYLOAD_001: candidateClaims stored as encrypted blob only.
66
+ // PROPOSAL_QUEUE_NO_PLAINTEXT_CANDIDATE_CLAIMS_001: no candidateClaims/rationale/reject_reason columns.
67
+ proposals: [
68
+ "proposal_id", "status", "proposed_by_agent", "under_grant",
69
+ "encrypted_payload", "payload_key_id",
70
+ "created_at", "updated_at", "decided_at",
71
+ ],
72
+ };
73
+ // Required indexes introduced in v7. Checked by verifyCurrentSchema.
74
+ const REQUIRED_INDEXES = [
75
+ "idx_proposals_status",
76
+ "idx_proposals_agent",
77
+ "idx_proposals_grant",
78
+ "idx_proposals_status_grant",
79
+ // PRODUCTION_AUDIT_C4_HASH_CHAIN_SEQUENCE_001 (v9): unique sequence index on audit_events.
80
+ "audit_events_sequence_unique",
81
+ ];
82
+ // ─── Historical DDL snapshots ─────────────────────────────────────────────────
83
+ // Each step preserves the schema state at that point in the project's history.
84
+ // Step v1→v2 creates sources WITHOUT evidence columns; those arrive in v3→v4.
85
+ const V1_SCHEMA_META_DDL = `
86
+ CREATE TABLE IF NOT EXISTS schema_meta (
87
+ key TEXT PRIMARY KEY,
88
+ value TEXT NOT NULL
89
+ ) STRICT;
90
+ `;
91
+ const V1_CLAIMS_DDL = `
92
+ CREATE TABLE IF NOT EXISTS claims (
93
+ id TEXT PRIMARY KEY,
94
+ source_id TEXT NOT NULL,
95
+ subject TEXT NOT NULL,
96
+ predicate TEXT NOT NULL,
97
+ valid_from TEXT NOT NULL,
98
+ valid_to TEXT,
99
+ recorded_at TEXT NOT NULL,
100
+ recorded_seq INTEGER NOT NULL UNIQUE,
101
+ retracts TEXT,
102
+ supersedes TEXT,
103
+ overrides TEXT,
104
+ contract_id TEXT,
105
+ confidence REAL,
106
+ serializer_version TEXT NOT NULL,
107
+ encrypted_payload TEXT NOT NULL
108
+ ) STRICT;
109
+ `;
110
+ // Sources without evidence link columns (added in step v3→v4).
111
+ const V2_SOURCES_BASE_DDL = `
112
+ CREATE TABLE IF NOT EXISTS sources (
113
+ id TEXT PRIMARY KEY,
114
+ kind TEXT NOT NULL,
115
+ label TEXT NOT NULL,
116
+ status TEXT NOT NULL DEFAULT 'active',
117
+ created_at TEXT NOT NULL,
118
+ created_by TEXT NOT NULL,
119
+ metadata TEXT
120
+ ) STRICT;
121
+ `;
122
+ const V3_RAW_DOCUMENTS_DDL = `
123
+ CREATE TABLE IF NOT EXISTS raw_documents (
124
+ id TEXT PRIMARY KEY,
125
+ mime_type TEXT NOT NULL,
126
+ byte_length INTEGER NOT NULL,
127
+ label TEXT,
128
+ created_at TEXT NOT NULL,
129
+ created_by TEXT NOT NULL,
130
+ encrypted_blob TEXT NOT NULL,
131
+ metadata TEXT
132
+ ) STRICT;
133
+ `;
134
+ // Evidence link columns added to sources in step v3→v4.
135
+ const V4_EVIDENCE_COLUMNS = [
136
+ "ALTER TABLE sources ADD COLUMN evidence_id TEXT",
137
+ "ALTER TABLE sources ADD COLUMN evidence_uri TEXT",
138
+ "ALTER TABLE sources ADD COLUMN evidence_hash TEXT",
139
+ "ALTER TABLE sources ADD COLUMN evidence_mime TEXT",
140
+ "ALTER TABLE sources ADD COLUMN evidence_enc INTEGER",
141
+ ];
142
+ const V5_AUDIT_EVENTS_DDL = `
143
+ CREATE TABLE IF NOT EXISTS audit_events (
144
+ id TEXT PRIMARY KEY,
145
+ recorded_at TEXT NOT NULL,
146
+ actor TEXT NOT NULL,
147
+ grant_id TEXT,
148
+ purpose TEXT,
149
+ decision TEXT NOT NULL,
150
+ reason_code TEXT NOT NULL,
151
+ selector_fingerprint TEXT NOT NULL,
152
+ result_count INTEGER NOT NULL,
153
+ result_claim_ids TEXT NOT NULL,
154
+ contract_ids TEXT
155
+ ) STRICT;
156
+ `;
157
+ // AUTH_SQLITE_TENANT_MEMBERSHIP_SCHEMA_001 ✅ Production-02d-a
158
+ const V6_AUTH_TENANT_MEMBERSHIPS_DDL = `
159
+ CREATE TABLE IF NOT EXISTS auth_tenant_memberships (
160
+ tenant_id TEXT NOT NULL,
161
+ person_id TEXT NOT NULL,
162
+ status TEXT NOT NULL CHECK (status IN ('active', 'suspended')),
163
+ created_at TEXT NOT NULL,
164
+ updated_at TEXT NOT NULL,
165
+ PRIMARY KEY (tenant_id, person_id)
166
+ ) STRICT;
167
+ `;
168
+ // AUTH_SQLITE_GRANT_SCHEMA_001 ✅ Production-02d-a
169
+ const V6_AUTH_GRANTS_DDL = `
170
+ CREATE TABLE IF NOT EXISTS auth_grants (
171
+ grant_id TEXT NOT NULL PRIMARY KEY,
172
+ agent_id TEXT NOT NULL,
173
+ tenant_id TEXT NOT NULL,
174
+ status TEXT NOT NULL CHECK (status IN ('active', 'revoked')),
175
+ not_before TEXT NOT NULL,
176
+ not_after TEXT NOT NULL,
177
+ created_at TEXT NOT NULL,
178
+ updated_at TEXT NOT NULL
179
+ ) STRICT;
180
+ `;
181
+ const V6_AUTH_GRANTS_INDEX = `
182
+ CREATE INDEX IF NOT EXISTS auth_grants_lookup
183
+ ON auth_grants (agent_id, tenant_id, grant_id);
184
+ `;
185
+ // PROPOSAL_QUEUE_SCHEMA_ENCRYPTED_PAYLOAD_001 ✅ Production-06a
186
+ // PROPOSAL_QUEUE_NO_PLAINTEXT_CANDIDATE_CLAIMS_001 ✅ Production-06a
187
+ // candidateClaims are stored as encrypted_payload (EncryptedBlob JSON).
188
+ // No plaintext candidateClaims, rationale, or reject_reason columns.
189
+ const V7_PROPOSALS_DDL = `
190
+ CREATE TABLE IF NOT EXISTS proposals (
191
+ proposal_id TEXT NOT NULL PRIMARY KEY,
192
+ status TEXT NOT NULL CHECK (status IN ('pending', 'accepted', 'rejected')),
193
+ proposed_by_agent TEXT NOT NULL,
194
+ under_grant TEXT NOT NULL,
195
+ encrypted_payload TEXT NOT NULL,
196
+ payload_key_id TEXT NOT NULL,
197
+ created_at TEXT NOT NULL,
198
+ updated_at TEXT NOT NULL,
199
+ decided_at TEXT
200
+ ) STRICT;
201
+ `;
202
+ const V7_PROPOSALS_IDX_STATUS = `
203
+ CREATE INDEX IF NOT EXISTS idx_proposals_status
204
+ ON proposals (status);
205
+ `;
206
+ const V7_PROPOSALS_IDX_AGENT = `
207
+ CREATE INDEX IF NOT EXISTS idx_proposals_agent
208
+ ON proposals (proposed_by_agent);
209
+ `;
210
+ const V7_PROPOSALS_IDX_GRANT = `
211
+ CREATE INDEX IF NOT EXISTS idx_proposals_grant
212
+ ON proposals (under_grant);
213
+ `;
214
+ const V7_PROPOSALS_IDX_STATUS_GRANT = `
215
+ CREATE INDEX IF NOT EXISTS idx_proposals_status_grant
216
+ ON proposals (status, under_grant);
217
+ `;
218
+ // PRODUCTION_AUTH_SCHEMA_V8_PERSON_SCOPE_001
219
+ const V8_AUTH_GRANTS_PERSON_ID = `
220
+ ALTER TABLE auth_grants ADD COLUMN person_id TEXT;
221
+ `;
222
+ // ─── v9: Audit Hardening C4 — Local Hash Chain ──────────────────────────────────
223
+ // PRODUCTION_AUDIT_C4_HASH_CHAIN_SEQUENCE_001 / PRODUCTION_AUDIT_C4_PREV_HASH_LINKAGE_001 /
224
+ // PRODUCTION_AUDIT_C4_BACKFILL_LEGACY_CHAIN_VALID_001
225
+ //
226
+ // DEFAULT 0 / DEFAULT '' are temporary scaffolding to satisfy NOT NULL during ALTER. The
227
+ // backfill loop replaces them for every existing row before the unique index is created, so
228
+ // no committed chain row ever carries the scaffold values.
229
+ const V9_AUDIT_ADD_SEQUENCE = `ALTER TABLE audit_events ADD COLUMN sequence INTEGER NOT NULL DEFAULT 0`;
230
+ const V9_AUDIT_ADD_PREV_HASH = `ALTER TABLE audit_events ADD COLUMN prev_hash TEXT`;
231
+ const V9_AUDIT_ADD_EVENT_HASH = `ALTER TABLE audit_events ADD COLUMN event_hash TEXT NOT NULL DEFAULT ''`;
232
+ const V9_AUDIT_SEQUENCE_INDEX = `CREATE UNIQUE INDEX audit_events_sequence_unique ON audit_events(sequence)`;
233
+ // PRODUCTION_AUDIT_C4_BACKFILL_LEGACY_CHAIN_VALID_001: build a valid chain from current DB
234
+ // state, ordered by rowid ASC (stable SQLite insertion order). Runs inside the migration
235
+ // transaction; synchronous (better-sqlite3) so it uses sha256hexSync.
236
+ function backfillAuditChain(db) {
237
+ const rows = db
238
+ .prepare(`SELECT id, recorded_at, actor, grant_id, purpose, decision, reason_code,
239
+ selector_fingerprint, result_count, result_claim_ids, contract_ids
240
+ FROM audit_events ORDER BY rowid ASC`)
241
+ .all();
242
+ const update = db.prepare(`UPDATE audit_events SET sequence = ?, prev_hash = ?, event_hash = ? WHERE id = ?`);
243
+ let prevEventHash = null;
244
+ for (let i = 0; i < rows.length; i++) {
245
+ const row = rows[i];
246
+ const seq = i + 1;
247
+ const canonical = buildChainCanonical({
248
+ actor: row.actor,
249
+ contract_ids: row.contract_ids,
250
+ decision: row.decision,
251
+ grant_id: row.grant_id,
252
+ id: row.id,
253
+ prev_hash: prevEventHash,
254
+ purpose: row.purpose,
255
+ reason_code: row.reason_code,
256
+ recorded_at: row.recorded_at,
257
+ result_claim_ids: row.result_claim_ids,
258
+ result_count: row.result_count,
259
+ selector_fingerprint: row.selector_fingerprint,
260
+ sequence: seq,
261
+ });
262
+ const eventHash = sha256hexSync(canonical);
263
+ update.run(seq, prevEventHash, eventHash, row.id);
264
+ prevEventHash = eventHash;
265
+ }
266
+ }
267
+ const MIGRATIONS = [
268
+ {
269
+ fromVersion: 0,
270
+ apply(db) {
271
+ db.exec(V1_SCHEMA_META_DDL);
272
+ db.exec(V1_CLAIMS_DDL);
273
+ // INSERT OR IGNORE never overwrites an existing schema_version string.
274
+ db.prepare("INSERT OR IGNORE INTO schema_meta (key, value) VALUES ('schema_version', 'sqlite-claims-v1')").run();
275
+ },
276
+ },
277
+ {
278
+ fromVersion: 1,
279
+ apply(db) {
280
+ db.exec(V2_SOURCES_BASE_DDL);
281
+ },
282
+ },
283
+ {
284
+ fromVersion: 2,
285
+ apply(db) {
286
+ db.exec(V3_RAW_DOCUMENTS_DDL);
287
+ },
288
+ },
289
+ {
290
+ fromVersion: 3,
291
+ apply(db) {
292
+ for (const sql of V4_EVIDENCE_COLUMNS) {
293
+ db.prepare(sql).run();
294
+ }
295
+ },
296
+ },
297
+ {
298
+ fromVersion: 4,
299
+ apply(db) {
300
+ db.exec(V5_AUDIT_EVENTS_DDL);
301
+ },
302
+ },
303
+ {
304
+ fromVersion: 5,
305
+ apply(db) {
306
+ db.exec(V6_AUTH_TENANT_MEMBERSHIPS_DDL);
307
+ db.exec(V6_AUTH_GRANTS_DDL);
308
+ db.exec(V6_AUTH_GRANTS_INDEX);
309
+ },
310
+ },
311
+ {
312
+ fromVersion: 6,
313
+ apply(db) {
314
+ db.exec(V7_PROPOSALS_DDL);
315
+ db.exec(V7_PROPOSALS_IDX_STATUS);
316
+ db.exec(V7_PROPOSALS_IDX_AGENT);
317
+ db.exec(V7_PROPOSALS_IDX_GRANT);
318
+ db.exec(V7_PROPOSALS_IDX_STATUS_GRANT);
319
+ },
320
+ },
321
+ {
322
+ fromVersion: 7,
323
+ apply(db) {
324
+ db.prepare(V8_AUTH_GRANTS_PERSON_ID.trim()).run();
325
+ },
326
+ },
327
+ {
328
+ // PRODUCTION_AUDIT_C4_HASH_CHAIN_SEQUENCE_001 (v9): add chain columns, backfill, unique index.
329
+ // PRODUCTION_AUDIT_C4_WRITE_ATOMIC_BEGIN_IMMEDIATE_001: runs within the single BEGIN IMMEDIATE
330
+ // migration transaction — no half-migrated chain is ever observable.
331
+ fromVersion: 8,
332
+ apply(db) {
333
+ db.prepare(V9_AUDIT_ADD_SEQUENCE).run();
334
+ db.prepare(V9_AUDIT_ADD_PREV_HASH).run();
335
+ db.prepare(V9_AUDIT_ADD_EVENT_HASH).run();
336
+ backfillAuditChain(db);
337
+ db.prepare(V9_AUDIT_SEQUENCE_INDEX).run();
338
+ },
339
+ },
340
+ {
341
+ // GUARDIAN_AUDIT_MARKED_001 (v10): add guardian audit columns to audit_events.
342
+ // Both columns are nullable — NULL = not a guardian action.
343
+ // GUARDIAN_AUDIT_HASH_CHAIN_BACKWARD_COMPATIBLE_001: pre-existing rows remain NULL; their
344
+ // chain hashes are computed without these fields (absent from canonical) → unchanged.
345
+ fromVersion: 9,
346
+ apply(db) {
347
+ db.prepare(`ALTER TABLE audit_events ADD COLUMN acting_as_guardian INTEGER`).run();
348
+ db.prepare(`ALTER TABLE audit_events ADD COLUMN ward_id TEXT`).run();
349
+ },
350
+ },
351
+ ];
352
+ // ─── Structural verification ──────────────────────────────────────────────────
353
+ // SQLITE_MIGRATION_CURRENT_SCHEMA_STRUCTURAL_VERIFY_001
354
+ export function verifyCurrentSchema(db) {
355
+ const missing = [];
356
+ const existingTables = new Set(db
357
+ .prepare("SELECT name FROM sqlite_master WHERE type='table'")
358
+ .all().map((r) => r.name));
359
+ for (const table of REQUIRED_TABLES) {
360
+ if (!existingTables.has(table))
361
+ missing.push(`table:${table}`);
362
+ }
363
+ // Only check columns and indexes once all required tables are confirmed present.
364
+ if (missing.length === 0) {
365
+ for (const [table, cols] of Object.entries(REQUIRED_COLUMNS)) {
366
+ const existingCols = new Set(db.pragma(`table_info(${table})`).map((r) => r.name));
367
+ for (const col of cols) {
368
+ if (!existingCols.has(col))
369
+ missing.push(`${table}.${col}`);
370
+ }
371
+ }
372
+ const existingIndexes = new Set(db
373
+ .prepare("SELECT name FROM sqlite_master WHERE type='index'")
374
+ .all().map((r) => r.name));
375
+ for (const idx of REQUIRED_INDEXES) {
376
+ if (!existingIndexes.has(idx))
377
+ missing.push(`index:${idx}`);
378
+ }
379
+ }
380
+ return missing.length === 0 ? { ok: true } : { ok: false, missing };
381
+ }
382
+ // SQLITE_MIGRATION_CURRENT_SCHEMA_STRUCTURAL_VERIFY_001
383
+ function assertCurrentSchema(db) {
384
+ const result = verifyCurrentSchema(db);
385
+ if (!result.ok) {
386
+ throw Object.assign(new Error(`[${VERIFY_FAILED_CODE}] Schema verification failed. ` +
387
+ `Missing: ${result.missing.join(", ")}.`), { code: VERIFY_FAILED_CODE, missing: result.missing });
388
+ }
389
+ }
390
+ // ─── Version inference ────────────────────────────────────────────────────────
391
+ // Used only when schema_meta exists but migration_version key is absent.
392
+ // Returns the highest migration step whose preconditions are met by the current schema.
393
+ function inferMigrationVersion(db) {
394
+ const tables = new Set(db
395
+ .prepare("SELECT name FROM sqlite_master WHERE type='table'")
396
+ .all().map((r) => r.name));
397
+ if (!tables.has("claims"))
398
+ return 0; // schema_meta-only DB — start from scratch
399
+ if (!tables.has("sources"))
400
+ return 1;
401
+ const sourceCols = new Set(db.pragma("table_info(sources)").map((r) => r.name));
402
+ if (!tables.has("raw_documents"))
403
+ return 2;
404
+ if (!sourceCols.has("evidence_id"))
405
+ return 3;
406
+ if (!tables.has("audit_events"))
407
+ return 4;
408
+ if (!tables.has("auth_tenant_memberships") || !tables.has("auth_grants"))
409
+ return 5;
410
+ if (!tables.has("proposals"))
411
+ return 6;
412
+ // v8 check: auth_grants must have person_id column
413
+ const grantCols = new Set(db.pragma("table_info(auth_grants)").map(r => r.name));
414
+ if (!grantCols.has("person_id"))
415
+ return 7;
416
+ // The audit_events table exists. Before deciding whether it is a v8-complete DB awaiting
417
+ // the v9 chain upgrade, confirm its pre-v9 columns are intact. A table missing pre-v9
418
+ // columns (e.g. selector_fingerprint) is a structurally-broken legacy DB — fail closed here
419
+ // rather than letting the destructive v9 ALTER + backfill run and surface a raw SQLITE_ERROR.
420
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_INCOMPLETE_001
421
+ const auditCols = new Set(db.pragma("table_info(audit_events)").map(r => r.name));
422
+ const PRE_V9_AUDIT_COLUMNS = [
423
+ "id", "recorded_at", "actor", "grant_id", "purpose", "decision",
424
+ "reason_code", "selector_fingerprint", "result_count", "result_claim_ids",
425
+ "contract_ids",
426
+ ];
427
+ const missingPreV9 = PRE_V9_AUDIT_COLUMNS.filter(c => !auditCols.has(c));
428
+ if (missingPreV9.length > 0) {
429
+ throw Object.assign(new Error(`[${LEGACY_INCOMPLETE_CODE}] Legacy database has all required tables but ` +
430
+ `audit_events is missing columns: ${missingPreV9.map(c => `audit_events.${c}`).join(", ")}. ` +
431
+ `Cannot determine a safe migration starting point.`), { code: LEGACY_INCOMPLETE_CODE, missing: missingPreV9.map(c => `audit_events.${c}`) });
432
+ }
433
+ // v9 check: audit_events must have the C4 hash-chain columns.
434
+ // PRODUCTION_AUDIT_C4_HASH_CHAIN_SEQUENCE_001
435
+ if (!auditCols.has("sequence") || !auditCols.has("event_hash"))
436
+ return 8;
437
+ // v10 check: audit_events must have the guardian columns.
438
+ // GUARDIAN_AUDIT_MARKED_001
439
+ if (!auditCols.has("acting_as_guardian") || !auditCols.has("ward_id"))
440
+ return 9;
441
+ // All tables and v10 columns present.
442
+ return 10;
443
+ }
444
+ // ─── Legacy DB handling ───────────────────────────────────────────────────────
445
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_NOT_ASSUMED_CURRENT_001
446
+ // SQLITE_MIGRATION_OLD_SCHEMA_META_HANDLED_001
447
+ function handleLegacyUnversioned(db) {
448
+ // schema_meta exists but migration_version key is absent.
449
+ // This DB was produced by the old flat initializeSchema() or is genuinely incomplete.
450
+ // We NEVER assume "fully migrated" without structural proof.
451
+ const inferred = inferMigrationVersion(db);
452
+ if (inferred === CURRENT_SCHEMA_VERSION) {
453
+ // All tables are present. Perform full column check before stamping.
454
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_NOT_ASSUMED_CURRENT_001
455
+ const verification = verifyCurrentSchema(db);
456
+ if (!verification.ok) {
457
+ // Tables all present but columns are missing — cannot infer which step to re-run.
458
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_INCOMPLETE_001
459
+ throw Object.assign(new Error(`[${LEGACY_INCOMPLETE_CODE}] Legacy database has all required tables but is ` +
460
+ `missing columns: ${verification.missing.join(", ")}. ` +
461
+ `Cannot determine a safe migration starting point.`), { code: LEGACY_INCOMPLETE_CODE, missing: verification.missing });
462
+ }
463
+ // Schema is structurally complete — stamp migration_version so future opens are fast.
464
+ writeMigrationVersion(db, CURRENT_SCHEMA_VERSION);
465
+ return CURRENT_SCHEMA_VERSION;
466
+ }
467
+ // inferred < CURRENT_SCHEMA_VERSION — run pending migrations from the inferred start.
468
+ return inferred;
469
+ }
470
+ // ─── Version read / write ─────────────────────────────────────────────────────
471
+ function writeMigrationVersion(db, version) {
472
+ db.prepare("INSERT OR REPLACE INTO schema_meta (key, value) VALUES ('migration_version', ?)").run(String(version));
473
+ }
474
+ // ─── Migration execution ──────────────────────────────────────────────────────
475
+ function applyPendingMigrations(db, fromVersion) {
476
+ const pending = MIGRATIONS.filter((m) => m.fromVersion >= fromVersion);
477
+ if (pending.length === 0)
478
+ return;
479
+ // SQLITE_MIGRATIONS_RUN_IN_TRANSACTION_001: all steps commit atomically.
480
+ // PRODUCTION_AUDIT_C4_WRITE_ATOMIC_BEGIN_IMMEDIATE_001: BEGIN IMMEDIATE reserves the write
481
+ // lock up front so schema changes + C4 backfill never leave a half-migrated chain.
482
+ db.prepare("BEGIN IMMEDIATE").run();
483
+ try {
484
+ for (const step of pending) {
485
+ step.apply(db);
486
+ }
487
+ writeMigrationVersion(db, CURRENT_SCHEMA_VERSION);
488
+ db.prepare("COMMIT").run();
489
+ }
490
+ catch (err) {
491
+ try {
492
+ db.prepare("ROLLBACK").run();
493
+ }
494
+ catch {
495
+ /* DB already closed or in bad state — original error is what matters */
496
+ }
497
+ throw err;
498
+ }
499
+ }
500
+ // ─── Public runner ────────────────────────────────────────────────────────────
501
+ export function runMigrations(db) {
502
+ // Resolve the current migration version, handling the legacy unversioned case.
503
+ const hasMeta = db
504
+ .prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='schema_meta'")
505
+ .get();
506
+ const current = (() => {
507
+ if (!hasMeta)
508
+ return 0; // completely empty DB
509
+ const row = db
510
+ .prepare("SELECT value FROM schema_meta WHERE key = 'migration_version'")
511
+ .get();
512
+ if (!row) {
513
+ // SQLITE_MIGRATION_LEGACY_SCHEMA_NOT_ASSUMED_CURRENT_001:
514
+ // schema_meta present but migration_version absent → do NOT assume current.
515
+ // SQLITE_MIGRATION_OLD_SCHEMA_META_HANDLED_001:
516
+ // old schema_version string and flat-initializeSchema DBs go through structural check.
517
+ return handleLegacyUnversioned(db);
518
+ }
519
+ return parseInt(row.value, 10);
520
+ })();
521
+ if (current > CURRENT_SCHEMA_VERSION) {
522
+ // SQLITE_MIGRATION_FAILS_CLOSED_ON_UNKNOWN_FUTURE_VERSION_001
523
+ throw Object.assign(new Error(`[${FAIL_CLOSED_CODE}] Database migration_version ${current} exceeds ` +
524
+ `runner ceiling ${CURRENT_SCHEMA_VERSION}. ` +
525
+ `Upgrade the Life-as-API package to open this database.`), { code: FAIL_CLOSED_CODE });
526
+ }
527
+ if (current < CURRENT_SCHEMA_VERSION) {
528
+ applyPendingMigrations(db, current);
529
+ }
530
+ // SQLITE_MIGRATION_CURRENT_SCHEMA_STRUCTURAL_VERIFY_001:
531
+ // Always verify structural completeness — even when migration_version claims current.
532
+ // This catches tampered version numbers and post-commit corruption.
533
+ assertCurrentSchema(db);
534
+ }
535
+ //# sourceMappingURL=migrations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../../src/persistence/sqlite/migrations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { Database } from "better-sqlite3";
2
+ export declare const SCHEMA_VERSION = "sqlite-claims-v1";
3
+ export declare const SERIALIZER_VERSION = "claim-serializer-v1";
4
+ export declare const CLAIMS_DDL = "\nCREATE TABLE IF NOT EXISTS claims (\n id TEXT PRIMARY KEY,\n source_id TEXT NOT NULL,\n subject TEXT NOT NULL,\n predicate TEXT NOT NULL,\n valid_from TEXT NOT NULL,\n valid_to TEXT,\n recorded_at TEXT NOT NULL,\n recorded_seq INTEGER NOT NULL UNIQUE,\n retracts TEXT,\n supersedes TEXT,\n overrides TEXT,\n contract_id TEXT,\n confidence REAL,\n serializer_version TEXT NOT NULL,\n encrypted_payload TEXT NOT NULL\n) STRICT;\n";
5
+ export declare const SCHEMA_META_DDL = "\nCREATE TABLE IF NOT EXISTS schema_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n) STRICT;\n";
6
+ export declare const SOURCES_DDL = "\nCREATE TABLE IF NOT EXISTS sources (\n id TEXT PRIMARY KEY,\n kind TEXT NOT NULL,\n label TEXT NOT NULL,\n status TEXT NOT NULL DEFAULT 'active',\n created_at TEXT NOT NULL,\n created_by TEXT NOT NULL,\n evidence_id TEXT,\n evidence_uri TEXT,\n evidence_hash TEXT,\n evidence_mime TEXT,\n evidence_enc INTEGER,\n metadata TEXT\n) STRICT;\n";
7
+ export declare const RAW_DOCUMENTS_DDL = "\nCREATE TABLE IF NOT EXISTS raw_documents (\n id TEXT PRIMARY KEY,\n mime_type TEXT NOT NULL,\n byte_length INTEGER NOT NULL,\n label TEXT,\n created_at TEXT NOT NULL,\n created_by TEXT NOT NULL,\n encrypted_blob TEXT NOT NULL,\n metadata TEXT\n) STRICT;\n";
8
+ export declare const AUDIT_EVENTS_DDL = "\nCREATE TABLE IF NOT EXISTS audit_events (\n id TEXT PRIMARY KEY,\n recorded_at TEXT NOT NULL,\n actor TEXT NOT NULL,\n grant_id TEXT,\n purpose TEXT,\n decision TEXT NOT NULL,\n reason_code TEXT NOT NULL,\n selector_fingerprint TEXT NOT NULL,\n result_count INTEGER NOT NULL,\n result_claim_ids TEXT NOT NULL,\n contract_ids TEXT\n) STRICT;\n";
9
+ export declare function initializeSchema(db: Database): void;
10
+ export declare function getSchemaVersion(db: Database): string | undefined;
@@ -0,0 +1,101 @@
1
+ // SQLite schema for the claims table.
2
+ //
3
+ // SQLITE_SCHEMA_VERSIONED_001: schema version tracked in schema_meta table.
4
+ // SQLITE_APPEND_ONLY_001: no UPDATE or DELETE statements anywhere in this module.
5
+ // SQLITE_PAYLOAD_ENCRYPTED_AT_REST_001: encrypted_payload column stores ciphertext only.
6
+ //
7
+ // Column layout:
8
+ // Metadata columns — plaintext (CRYPTO_METADATA_PLAINTEXT_ACCEPTED_001)
9
+ // encrypted_payload — JSON-serialized EncryptedBlob (AES-256-GCM ciphertext)
10
+ // serializer_version — "claim-serializer-v1" (SQLITE_SCHEMA_VERSIONED_001)
11
+ import { runMigrations } from "./migrations.js";
12
+ export const SCHEMA_VERSION = "sqlite-claims-v1";
13
+ export const SERIALIZER_VERSION = "claim-serializer-v1";
14
+ export const CLAIMS_DDL = `
15
+ CREATE TABLE IF NOT EXISTS claims (
16
+ id TEXT PRIMARY KEY,
17
+ source_id TEXT NOT NULL,
18
+ subject TEXT NOT NULL,
19
+ predicate TEXT NOT NULL,
20
+ valid_from TEXT NOT NULL,
21
+ valid_to TEXT,
22
+ recorded_at TEXT NOT NULL,
23
+ recorded_seq INTEGER NOT NULL UNIQUE,
24
+ retracts TEXT,
25
+ supersedes TEXT,
26
+ overrides TEXT,
27
+ contract_id TEXT,
28
+ confidence REAL,
29
+ serializer_version TEXT NOT NULL,
30
+ encrypted_payload TEXT NOT NULL
31
+ ) STRICT;
32
+ `;
33
+ export const SCHEMA_META_DDL = `
34
+ CREATE TABLE IF NOT EXISTS schema_meta (
35
+ key TEXT PRIMARY KEY,
36
+ value TEXT NOT NULL
37
+ ) STRICT;
38
+ `;
39
+ // SOURCE_REGISTRY_EXISTS_001: source records are plaintext (MVP accepted risk — no PII here).
40
+ export const SOURCES_DDL = `
41
+ CREATE TABLE IF NOT EXISTS sources (
42
+ id TEXT PRIMARY KEY,
43
+ kind TEXT NOT NULL,
44
+ label TEXT NOT NULL,
45
+ status TEXT NOT NULL DEFAULT 'active',
46
+ created_at TEXT NOT NULL,
47
+ created_by TEXT NOT NULL,
48
+ evidence_id TEXT,
49
+ evidence_uri TEXT,
50
+ evidence_hash TEXT,
51
+ evidence_mime TEXT,
52
+ evidence_enc INTEGER,
53
+ metadata TEXT
54
+ ) STRICT;
55
+ `;
56
+ // RAW_DOCUMENT_BYTES_ENCRYPTED_AT_REST_001: encrypted_blob holds JSON EncryptedBlob only.
57
+ // RAW_DOCUMENT_METADATA_PLAINTEXT_ACCEPTED_001: id/mime_type/byte_length/label/created_* are plaintext.
58
+ export const RAW_DOCUMENTS_DDL = `
59
+ CREATE TABLE IF NOT EXISTS raw_documents (
60
+ id TEXT PRIMARY KEY,
61
+ mime_type TEXT NOT NULL,
62
+ byte_length INTEGER NOT NULL,
63
+ label TEXT,
64
+ created_at TEXT NOT NULL,
65
+ created_by TEXT NOT NULL,
66
+ encrypted_blob TEXT NOT NULL,
67
+ metadata TEXT
68
+ ) STRICT;
69
+ `;
70
+ // AUDIT_DURABLE_SINK_EXISTS_001: audit_events table is append-only.
71
+ // AUDIT_EVENT_NO_PAYLOAD_VALUES_001: no payload or document-bytes column — safe metadata only.
72
+ // AUDIT_EVENT_NO_RAW_DOCUMENT_BYTES_001: encrypted_blob / plainBytes columns are absent by design.
73
+ // AUDIT_EVENT_SELECTOR_FINGERPRINT_ONLY_001: selector_fingerprint stores a string summary, not the full selector.
74
+ // AUDIT_EVENTS_APPEND_ONLY_001: INSERT only — no UPDATE or DELETE rows in schema or implementation.
75
+ export const AUDIT_EVENTS_DDL = `
76
+ CREATE TABLE IF NOT EXISTS audit_events (
77
+ id TEXT PRIMARY KEY,
78
+ recorded_at TEXT NOT NULL,
79
+ actor TEXT NOT NULL,
80
+ grant_id TEXT,
81
+ purpose TEXT,
82
+ decision TEXT NOT NULL,
83
+ reason_code TEXT NOT NULL,
84
+ selector_fingerprint TEXT NOT NULL,
85
+ result_count INTEGER NOT NULL,
86
+ result_claim_ids TEXT NOT NULL,
87
+ contract_ids TEXT
88
+ ) STRICT;
89
+ `;
90
+ export function initializeSchema(db) {
91
+ db.pragma("journal_mode = WAL");
92
+ db.pragma("foreign_keys = ON");
93
+ runMigrations(db); // SQLITE_MIGRATION_RUNNER_EXISTS_001
94
+ }
95
+ export function getSchemaVersion(db) {
96
+ const row = db
97
+ .prepare("SELECT value FROM schema_meta WHERE key = 'schema_version'")
98
+ .get();
99
+ return row?.value;
100
+ }
101
+ //# sourceMappingURL=schema.js.map