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 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/persistence/sqlite/schema.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,4EAA4E;AAC5E,kFAAkF;AAClF,yFAAyF;AACzF,EAAE;AACF,iBAAiB;AACjB,2EAA2E;AAC3E,+EAA+E;AAC/E,6EAA6E;AAG7E,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,CAAC,MAAM,cAAc,GAAG,kBAAkB,CAAC;AACjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,qBAAqB,CAAC;AAExD,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;CAkBzB,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;CAK9B,CAAC;AAEF,8FAA8F;AAC9F,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;CAe1B,CAAC;AAEF,0FAA0F;AAC1F,wGAAwG;AACxG,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;CAWhC,CAAC;AAEF,oEAAoE;AACpE,+FAA+F;AAC/F,mGAAmG;AACnG,kHAAkH;AAClH,oGAAoG;AACpG,MAAM,CAAC,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;CAc/B,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,EAAY;IAC3C,EAAE,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChC,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC/B,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,qCAAqC;AAC1D,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAY;IAC3C,MAAM,GAAG,GAAG,EAAE;SACX,OAAO,CAAC,4DAA4D,CAAC;SACrE,GAAG,EAAmC,CAAC;IAC1C,OAAO,GAAG,EAAE,KAAK,CAAC;AACpB,CAAC"}
@@ -0,0 +1,24 @@
1
+ import Database from "better-sqlite3";
2
+ import type { ClaimId } from "../../types/ids.js";
3
+ import type { AppendClaimInput, ClaimMeta, StoredClaim } from "../../types/claim.js";
4
+ import type { AccessContext } from "../../types/access-context.js";
5
+ import type { BitemporalQuery, ClaimSelector, FactStore } from "../../types/fact-store.js";
6
+ import type { ClaimSerializer } from "../../crypto/claim-serializer.js";
7
+ export declare class SQLiteFactStore implements FactStore {
8
+ private readonly _serializer;
9
+ private readonly _db;
10
+ private readonly _ownsConnection;
11
+ private _seq;
12
+ constructor(dbPathOrDb: string | Database.Database, _serializer: ClaimSerializer);
13
+ close(): void;
14
+ append(input: AppendClaimInput, ctx: AccessContext): Promise<{
15
+ claimId: ClaimId;
16
+ recordedSeq: number;
17
+ }>;
18
+ readAll(ctx: AccessContext): Promise<ReadonlyArray<ClaimMeta>>;
19
+ readSince(seq: number, ctx: AccessContext): Promise<ReadonlyArray<ClaimMeta>>;
20
+ readAt(params: BitemporalQuery, ctx: AccessContext): Promise<ReadonlyArray<ClaimMeta>>;
21
+ readClaims(ctx: AccessContext, selector: ClaimSelector): Promise<ReadonlyArray<ClaimMeta>>;
22
+ readStoredClaims(ctx: AccessContext, selector: ClaimSelector): Promise<ReadonlyArray<StoredClaim>>;
23
+ getRawEncryptedPayload(claimId: ClaimId): string | undefined;
24
+ }
@@ -0,0 +1,207 @@
1
+ // SQLiteFactStore — durable FactStore backed by SQLite.
2
+ //
3
+ // Invariants (see docs/INVARIANTS.md):
4
+ // SQLITE_FACTSTORE_PARITY_001 — same behavioral guarantees as InMemoryFactStore
5
+ // SQLITE_APPEND_ONLY_001 — no UPDATE or DELETE on the claims table, ever
6
+ // SQLITE_RECORDED_SEQ_MONOTONIC_001 — recorded_seq UNIQUE constraint + autoincrement via store
7
+ // SQLITE_PAYLOAD_ENCRYPTED_AT_REST_001 — encrypted_payload stored; no plaintext column
8
+ // SQLITE_USES_CLAIM_SERIALIZER_001 — payload encrypt/decrypt delegated to ClaimSerializer
9
+ // SQLITE_ACCESS_CONTEXT_REQUIRED_001 — every method requires AccessContext
10
+ // SQLITE_AGENT_NO_DIRECT_APPEND_001 — AgentConsentContext cannot append
11
+ // SQLITE_SELECTOR_READ_001 — readClaims() supports ClaimSelector filtering
12
+ // SQLITE_NO_UPDATE_DELETE_001 — no UPDATE/DELETE SQL anywhere in this file
13
+ // SQLITE_REOPEN_ROUND_TRIP_001 — closing + reopening the DB restores all claims
14
+ // SQLITE_WRONG_KEY_FAIL_CLOSED_001 — wrong key during readStoredClaims → throws, no partial data
15
+ // SQLITE_SCHEMA_VERSIONED_001 — schema_meta table tracks schema version
16
+ //
17
+ // CRYPTO_BOUNDARY_ONLY_001: all encryption delegated to ClaimSerializer — no WebCrypto usage here.
18
+ import Database from "better-sqlite3";
19
+ import { asClaimId, asISOTime } from "../../types/ids.js";
20
+ import { deepFreeze } from "../../utilities/deep-freeze.js";
21
+ import { initializeSchema } from "./schema.js";
22
+ import { rowToClaimMeta, rowToEncryptedBlob } from "./types.js";
23
+ const SERIALIZER_VERSION = "claim-serializer-v1";
24
+ export class SQLiteFactStore {
25
+ _serializer;
26
+ _db;
27
+ _ownsConnection;
28
+ _seq;
29
+ // Accepts a file path (opens own connection) or a shared Database instance
30
+ // (e.g., for SQLiteUnitOfWork transactions — UNIT_OF_WORK_SQLITE_TRANSACTION_001).
31
+ constructor(dbPathOrDb, _serializer) {
32
+ this._serializer = _serializer;
33
+ if (typeof dbPathOrDb === "string") {
34
+ this._db = new Database(dbPathOrDb);
35
+ this._ownsConnection = true;
36
+ initializeSchema(this._db);
37
+ }
38
+ else {
39
+ this._db = dbPathOrDb;
40
+ this._ownsConnection = false;
41
+ }
42
+ // Resume seq from what's already in the database (supports reopen).
43
+ const maxRow = this._db
44
+ .prepare("SELECT MAX(recorded_seq) AS max_seq FROM claims")
45
+ .get();
46
+ this._seq = maxRow.max_seq ?? 0;
47
+ }
48
+ close() {
49
+ if (this._ownsConnection)
50
+ this._db.close();
51
+ }
52
+ // ── FactStore interface ───────────────────────────────────────────────────
53
+ async append(input, ctx) {
54
+ // SQLITE_ACCESS_CONTEXT_REQUIRED_001
55
+ if (ctx == null)
56
+ throw new TypeError("AccessContext is required — no implicit store access");
57
+ // SQLITE_AGENT_NO_DIRECT_APPEND_001
58
+ if (ctx.kind === "agent") {
59
+ throw new Error("AgentConsentContext cannot append claims directly. " +
60
+ "Use context.propose() instead. (SQLITE_AGENT_NO_DIRECT_APPEND_001)");
61
+ }
62
+ if (!input.sourceId) {
63
+ throw new Error("sourceId is required for all claims — provenance is mandatory (CLAIM_PROVENANCE_001)");
64
+ }
65
+ // CONTRACT_IDENTITY_LINK_META_PAYLOAD_MATCH_001
66
+ if (input.predicate === "contract.identity.link" && input.payload.type === "identity_link") {
67
+ const idPayload = input.payload;
68
+ if (input.contractId !== undefined && idPayload.contractId !== input.contractId) {
69
+ throw new Error(`CONTRACT_IDENTITY_LINK_META_PAYLOAD_MATCH_001: meta.contractId "${input.contractId}" ` +
70
+ `must match payload.contractId "${idPayload.contractId}"`);
71
+ }
72
+ }
73
+ const claimId = asClaimId(globalThis.crypto.randomUUID()); // WebCrypto only — CRYPTO_BOUNDARY_ONLY_001
74
+ const recordedAt = asISOTime(new Date().toISOString());
75
+ const recordedSeq = ++this._seq;
76
+ // Reconstruct a StoredClaim for serialization.
77
+ const stored = deepFreeze({
78
+ id: claimId, recordedAt, recordedSeq,
79
+ subject: input.subject,
80
+ sourceId: input.sourceId,
81
+ predicate: input.predicate,
82
+ validFrom: input.validFrom,
83
+ payload: input.payload,
84
+ ...(input.validTo !== undefined ? { validTo: input.validTo } : {}),
85
+ ...(input.retracts !== undefined ? { retracts: input.retracts } : {}),
86
+ ...(input.supersedes !== undefined ? { supersedes: input.supersedes } : {}),
87
+ ...(input.overrides !== undefined ? { overrides: input.overrides } : {}),
88
+ ...(input.confidence !== undefined ? { confidence: input.confidence } : {}),
89
+ ...(input.contractId !== undefined ? { contractId: input.contractId } : {}),
90
+ });
91
+ // SQLITE_USES_CLAIM_SERIALIZER_001: encrypt payload before writing.
92
+ const serialized = await this._serializer.serializeClaimForPersistence(stored);
93
+ // SQLITE_APPEND_ONLY_001: INSERT only, no UPDATE/DELETE.
94
+ this._db.prepare(`
95
+ INSERT INTO claims (
96
+ id, source_id, subject, predicate, valid_from, valid_to,
97
+ recorded_at, recorded_seq, retracts, supersedes, overrides,
98
+ contract_id, confidence, serializer_version, encrypted_payload
99
+ ) VALUES (
100
+ ?, ?, ?, ?, ?, ?,
101
+ ?, ?, ?, ?, ?,
102
+ ?, ?, ?, ?
103
+ )
104
+ `).run(serialized.id, serialized.sourceId, serialized.subject, serialized.predicate, serialized.validFrom, serialized.validTo ?? null, serialized.recordedAt, serialized.recordedSeq, serialized.retracts ?? null, serialized.supersedes ?? null, serialized.overrides ?? null, serialized.contractId ?? null, serialized.confidence ?? null, SERIALIZER_VERSION, JSON.stringify(serialized.encryptedPayload));
105
+ return { claimId, recordedSeq };
106
+ }
107
+ async readAll(ctx) {
108
+ if (ctx == null)
109
+ throw new TypeError("AccessContext is required");
110
+ const rows = this._db
111
+ .prepare("SELECT * FROM claims ORDER BY recorded_seq")
112
+ .all();
113
+ return rows.map(rowToClaimMeta);
114
+ }
115
+ async readSince(seq, ctx) {
116
+ if (ctx == null)
117
+ throw new TypeError("AccessContext is required");
118
+ const rows = this._db
119
+ .prepare("SELECT * FROM claims WHERE recorded_seq > ? ORDER BY recorded_seq")
120
+ .all(seq);
121
+ return rows.map(rowToClaimMeta);
122
+ }
123
+ async readAt(params, ctx) {
124
+ if (ctx == null)
125
+ throw new TypeError("AccessContext is required");
126
+ let claims = await this.readAll(ctx);
127
+ if (params.knownAsOf !== undefined) {
128
+ const knownAsOf = params.knownAsOf;
129
+ claims = claims.filter((c) => c.recordedAt <= knownAsOf);
130
+ }
131
+ if (params.validAsOf !== undefined) {
132
+ const validAsOf = params.validAsOf;
133
+ claims = claims.filter((c) => {
134
+ if (c.validFrom > validAsOf)
135
+ return false;
136
+ if (c.validTo !== undefined && c.validTo <= validAsOf)
137
+ return false;
138
+ return true;
139
+ });
140
+ }
141
+ return claims;
142
+ }
143
+ async readClaims(ctx, selector) {
144
+ if (ctx == null)
145
+ throw new TypeError("AccessContext is required");
146
+ let claims = await this.readAll(ctx);
147
+ if (selector.subject !== undefined) {
148
+ const subj = selector.subject;
149
+ claims = claims.filter((c) => c.subject === subj);
150
+ }
151
+ if (selector.predicates !== undefined) {
152
+ if (selector.predicates.length === 0)
153
+ return [];
154
+ const predSet = new Set(selector.predicates);
155
+ claims = claims.filter((c) => predSet.has(c.predicate));
156
+ }
157
+ if (selector.sinceRecordedSeq !== undefined) {
158
+ const since = selector.sinceRecordedSeq;
159
+ claims = claims.filter((c) => c.recordedSeq > since);
160
+ }
161
+ if (selector.includeRetracted === false) {
162
+ const allRows = this._db
163
+ .prepare("SELECT retracts FROM claims WHERE retracts IS NOT NULL")
164
+ .all();
165
+ const retractedIds = new Set(allRows.map((r) => r.retracts));
166
+ claims = claims.filter((c) => !retractedIds.has(c.id));
167
+ }
168
+ return claims;
169
+ }
170
+ // ── FACTSTORE_HYDRATED_READ_001: interface-defined payload-bearing read ──────
171
+ // FACTSTORE_HYDRATED_READ_ACCESS_BOUND_001: denied for AgentConsentContext + AuditContext.
172
+ // SQLITE_HYDRATED_WRONG_KEY_FAIL_CLOSED_001: propagates ClaimSerializer decryption errors.
173
+ async readStoredClaims(ctx, selector) {
174
+ if (ctx == null)
175
+ throw new TypeError("AccessContext is required");
176
+ if (ctx.kind === "agent" || ctx.kind === "audit") {
177
+ throw new Error("FACTSTORE_AGENT_NO_HYDRATED_READ_001: payload-bearing reads are denied for " +
178
+ `${ctx.kind} context — use readClaims() for metadata-only access`);
179
+ }
180
+ // Read metadata rows, apply selector filters (same logic as readClaims).
181
+ let meta = await this.readClaims(ctx, selector);
182
+ const ids = new Set(meta.map((c) => c.id));
183
+ // Fetch only the rows we need (matching selector) and decrypt.
184
+ const allRows = this._db
185
+ .prepare("SELECT * FROM claims ORDER BY recorded_seq")
186
+ .all();
187
+ const matchingRows = allRows.filter((r) => ids.has(r.id));
188
+ return Promise.all(matchingRows.map(async (row) => {
189
+ const claimMeta = rowToClaimMeta(row);
190
+ const blob = rowToEncryptedBlob(row);
191
+ const serialized = {
192
+ ...claimMeta,
193
+ serializerVersion: row.serializer_version,
194
+ encryptedPayload: blob,
195
+ };
196
+ return this._serializer.deserializeClaimFromPersistence(serialized);
197
+ }));
198
+ }
199
+ // Return the raw encrypted_payload column for a given claim (for at-rest verification).
200
+ getRawEncryptedPayload(claimId) {
201
+ const row = this._db
202
+ .prepare("SELECT encrypted_payload FROM claims WHERE id = ?")
203
+ .get(claimId);
204
+ return row?.encrypted_payload;
205
+ }
206
+ }
207
+ //# sourceMappingURL=sqlite-fact-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-fact-store.js","sourceRoot":"","sources":["../../../src/persistence/sqlite/sqlite-fact-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import Database from "better-sqlite3";
2
+ import type { SourceId } from "../../types/ids.js";
3
+ import type { AccessContext } from "../../types/access-context.js";
4
+ import type { AppendClaimInput } from "../../types/claim.js";
5
+ import type { Source, SourceFilter, SourceInput } from "../../types/source.js";
6
+ import type { SourceRegistry } from "../../source/source-registry.js";
7
+ export declare class SQLiteSourceRegistry implements SourceRegistry {
8
+ private readonly _db;
9
+ private readonly _ownsConnection;
10
+ constructor(dbPathOrDb: string | Database.Database);
11
+ close(): void;
12
+ registerSource(ctx: AccessContext, input: SourceInput): Source;
13
+ getSource(ctx: AccessContext, sourceId: SourceId): Source | undefined;
14
+ listSources(ctx: AccessContext, filter?: SourceFilter): Source[];
15
+ deactivateSource(ctx: AccessContext, sourceId: SourceId, reason: string): Source;
16
+ assertCanAppend(input: AppendClaimInput): void;
17
+ }
@@ -0,0 +1,132 @@
1
+ // SQLiteSourceRegistry — Slice-07.
2
+ //
3
+ // Persists Source records to SQLite. Source metadata is plaintext (MVP accepted risk —
4
+ // source identifiers and labels contain no claim payload data).
5
+ //
6
+ // SOURCE_SQLITE_REOPEN_ROUND_TRIP_001: sources survive a close + reopen cycle.
7
+ // SOURCE_REGISTRY_IMMUTABLE_001: only status column is ever updated; all other columns are INSERT-only.
8
+ // All methods synchronous (better-sqlite3 + no crypto = no async needed).
9
+ import Database from "better-sqlite3";
10
+ import { asISOTime, asSourceId, asEvidenceId } from "../../types/ids.js";
11
+ import { initializeSchema } from "./schema.js";
12
+ import { isPredicateAllowed, allowedPredicateDescription } from "../../source/source-kind-predicate-policy.js";
13
+ function rowToSource(row) {
14
+ const creator = JSON.parse(row.created_by);
15
+ return Object.freeze({
16
+ id: asSourceId(row.id),
17
+ kind: row.kind,
18
+ label: row.label,
19
+ status: row.status,
20
+ createdAt: row.created_at,
21
+ createdBy: Object.freeze(creator),
22
+ ...(row.evidence_uri != null ? {
23
+ evidenceRef: Object.freeze({
24
+ ...(row.evidence_id != null ? { id: asEvidenceId(row.evidence_id) } : {}),
25
+ uri: row.evidence_uri,
26
+ ...(row.evidence_hash != null ? { contentHash: row.evidence_hash } : {}),
27
+ ...(row.evidence_mime != null ? { mimeType: row.evidence_mime } : {}),
28
+ ...(row.evidence_enc != null ? { encrypted: row.evidence_enc === 1 } : {}),
29
+ }),
30
+ } : {}),
31
+ ...(row.metadata != null ? { metadata: Object.freeze(JSON.parse(row.metadata)) } : {}),
32
+ });
33
+ }
34
+ export class SQLiteSourceRegistry {
35
+ _db;
36
+ _ownsConnection;
37
+ // Accepts a file path (opens own connection) or a shared Database instance
38
+ // (e.g., for SQLiteUnitOfWork transactions — UNIT_OF_WORK_SQLITE_TRANSACTION_001).
39
+ constructor(dbPathOrDb) {
40
+ if (typeof dbPathOrDb === "string") {
41
+ this._db = new Database(dbPathOrDb);
42
+ this._ownsConnection = true;
43
+ initializeSchema(this._db);
44
+ }
45
+ else {
46
+ this._db = dbPathOrDb;
47
+ this._ownsConnection = false;
48
+ }
49
+ }
50
+ close() {
51
+ if (this._ownsConnection)
52
+ this._db.close();
53
+ }
54
+ registerSource(ctx, input) {
55
+ if (ctx.kind === "agent" || ctx.kind === "audit") {
56
+ throw new Error("SOURCE_AGENT_CANNOT_SELF_REGISTER_001: AgentConsentContext and AuditContext cannot register sources");
57
+ }
58
+ if (ctx.kind === "owner" && input.kind !== "user_manual") {
59
+ throw new Error(`SOURCE_OWNER_CAN_REGISTER_MANUAL_001: OwnerContext may only register "user_manual" sources, not "${input.kind}"`);
60
+ }
61
+ const existing = this._db.prepare("SELECT id FROM sources WHERE id = ?").get(input.id);
62
+ if (existing !== undefined) {
63
+ throw new Error(`SOURCE_REGISTRY_EXISTS_001: source "${input.id}" is already registered`);
64
+ }
65
+ const creator = ctx.kind === "owner" ? { kind: "owner", personId: ctx.personId } :
66
+ ctx.kind === "system_projection" ? { kind: "system_projection" } :
67
+ { kind: "test", label: ctx.label ?? "unknown" };
68
+ const createdAt = asISOTime(new Date().toISOString());
69
+ this._db.prepare(`
70
+ INSERT INTO sources (id, kind, label, status, created_at, created_by,
71
+ evidence_id, evidence_uri, evidence_hash, evidence_mime, evidence_enc, metadata)
72
+ VALUES (?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?, ?)
73
+ `).run(input.id, input.kind, input.label, createdAt, JSON.stringify(creator), input.evidenceRef?.id ?? null, input.evidenceRef?.uri ?? null, input.evidenceRef?.contentHash ?? null, input.evidenceRef?.mimeType ?? null, input.evidenceRef?.encrypted != null ? (input.evidenceRef.encrypted ? 1 : 0) : null, input.metadata != null ? JSON.stringify(input.metadata) : null);
74
+ return rowToSource(this._db.prepare("SELECT * FROM sources WHERE id = ?").get(input.id));
75
+ }
76
+ getSource(ctx, sourceId) {
77
+ if (ctx == null)
78
+ throw new TypeError("AccessContext is required");
79
+ const row = this._db.prepare("SELECT * FROM sources WHERE id = ?").get(sourceId);
80
+ return row !== undefined ? rowToSource(row) : undefined;
81
+ }
82
+ listSources(ctx, filter) {
83
+ if (ctx == null)
84
+ throw new TypeError("AccessContext is required");
85
+ let sql = "SELECT * FROM sources";
86
+ const params = [];
87
+ const clauses = [];
88
+ if (filter?.kind !== undefined) {
89
+ clauses.push("kind = ?");
90
+ params.push(filter.kind);
91
+ }
92
+ if (filter?.status !== undefined) {
93
+ clauses.push("status = ?");
94
+ params.push(filter.status);
95
+ }
96
+ if (clauses.length > 0)
97
+ sql += " WHERE " + clauses.join(" AND ");
98
+ const rows = this._db.prepare(sql).all(...params);
99
+ return rows.map(rowToSource);
100
+ }
101
+ deactivateSource(ctx, sourceId, reason) {
102
+ if (ctx.kind === "agent" || ctx.kind === "audit") {
103
+ throw new Error("SOURCE_AGENT_CANNOT_SELF_REGISTER_001: agents and audit cannot deactivate sources");
104
+ }
105
+ const existing = this._db.prepare("SELECT * FROM sources WHERE id = ?").get(sourceId);
106
+ if (existing === undefined) {
107
+ throw new Error(`SOURCE_UNKNOWN_REJECTED_001: source "${sourceId}" not found for deactivation`);
108
+ }
109
+ if (existing.status === "inactive") {
110
+ return rowToSource(existing); // idempotent
111
+ }
112
+ // SOURCE_REGISTRY_IMMUTABLE_001: only status column updated.
113
+ this._db.prepare("UPDATE sources SET status = 'inactive' WHERE id = ?").run(sourceId);
114
+ return rowToSource(this._db.prepare("SELECT * FROM sources WHERE id = ?").get(sourceId));
115
+ }
116
+ assertCanAppend(input) {
117
+ const row = this._db
118
+ .prepare("SELECT kind, status FROM sources WHERE id = ?")
119
+ .get(input.sourceId);
120
+ if (row === undefined) {
121
+ throw new Error(`SOURCE_UNKNOWN_REJECTED_001: sourceId "${input.sourceId}" is not registered`);
122
+ }
123
+ if (row.status === "inactive") {
124
+ throw new Error(`SOURCE_INACTIVE_REJECTED_001: sourceId "${input.sourceId}" is inactive`);
125
+ }
126
+ if (!isPredicateAllowed(row.kind, input.predicate)) {
127
+ throw new Error(`SOURCE_KIND_ALLOWED_PREDICATE_001: source kind "${row.kind}" may not produce ` +
128
+ `predicate "${input.predicate}". Allowed: ${allowedPredicateDescription(row.kind)}`);
129
+ }
130
+ }
131
+ }
132
+ //# sourceMappingURL=sqlite-source-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-source-registry.js","sourceRoot":"","sources":["../../../src/persistence/sqlite/sqlite-source-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import Database from "better-sqlite3";
2
+ import type { UnitOfWork } from "../unit-of-work.js";
3
+ export declare class SQLiteUnitOfWork implements UnitOfWork {
4
+ private readonly _db;
5
+ private _spCount;
6
+ constructor(_db: Database.Database);
7
+ run<T>(fn: () => Promise<T>): Promise<T>;
8
+ }
@@ -0,0 +1,41 @@
1
+ // SQLiteUnitOfWork — Slice-18 / Audit Hardening C2a.
2
+ //
3
+ // UNIT_OF_WORK_SQLITE_TRANSACTION_001: wraps fn in SAVEPOINT / RELEASE SAVEPOINT / ROLLBACK TO
4
+ // SAVEPOINT on a shared better-sqlite3 Database instance. All stores passed the same Database
5
+ // object participate in one ACID transaction — either all writes commit or none do.
6
+ //
7
+ // UNIT_OF_WORK_SAVEPOINT_REENTRANT_001: SAVEPOINT-based transactions are re-entrant. At top
8
+ // level a SAVEPOINT behaves like BEGIN; a nested run() opens a nested SAVEPOINT that participates
9
+ // in the outer transaction scope instead of failing ("cannot start a transaction within a
10
+ // transaction"). When the outermost scope rolls back, all nested writes roll back with it.
11
+ // Per-instance _spCount yields unique savepoint names (sp_0, sp_1, …).
12
+ //
13
+ // UNIT_OF_WORK_NO_RAW_PAYLOAD_LOGGING_001: errors are re-thrown as-is; no payload logging.
14
+ export class SQLiteUnitOfWork {
15
+ _db;
16
+ _spCount = 0;
17
+ constructor(_db) {
18
+ this._db = _db;
19
+ }
20
+ async run(fn) {
21
+ const sp = `sp_${this._spCount++}`;
22
+ this._db.prepare(`SAVEPOINT ${sp}`).run();
23
+ try {
24
+ const result = await fn();
25
+ this._db.prepare(`RELEASE SAVEPOINT ${sp}`).run();
26
+ return result;
27
+ }
28
+ catch (err) {
29
+ try {
30
+ this._db.prepare(`ROLLBACK TO SAVEPOINT ${sp}`).run();
31
+ }
32
+ catch { /* already rolled back or closed */ }
33
+ try {
34
+ this._db.prepare(`RELEASE SAVEPOINT ${sp}`).run();
35
+ }
36
+ catch { /* already released or closed */ }
37
+ throw err;
38
+ }
39
+ }
40
+ }
41
+ //# sourceMappingURL=sqlite-unit-of-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sqlite-unit-of-work.js","sourceRoot":"","sources":["../../../src/persistence/sqlite/sqlite-unit-of-work.ts"],"names":[],"mappings":"AAAA,qDAAqD;AACrD,EAAE;AACF,+FAA+F;AAC/F,8FAA8F;AAC9F,oFAAoF;AACpF,EAAE;AACF,4FAA4F;AAC5F,kGAAkG;AAClG,0FAA0F;AAC1F,2FAA2F;AAC3F,uEAAuE;AACvE,EAAE;AACF,2FAA2F;AAK3F,MAAM,OAAO,gBAAgB;IAEE;IADrB,QAAQ,GAAG,CAAC,CAAC;IACrB,YAA6B,GAAsB;QAAtB,QAAG,GAAH,GAAG,CAAmB;IAAG,CAAC;IAEvD,KAAK,CAAC,GAAG,CAAI,EAAoB;QAC/B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;QACnC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;QAC1C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAClD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC;gBAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,mCAAmC,CAAC,CAAC;YAC5G,IAAI,CAAC;gBAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,gCAAgC,CAAC,CAAC;YACrG,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,24 @@
1
+ import type { ClaimMeta } from "../../types/claim.js";
2
+ import type { EncryptedBlob } from "../../crypto/types.js";
3
+ export interface SQLiteFactStoreOptions {
4
+ readonly dbPath: string;
5
+ }
6
+ export interface SQLiteRow {
7
+ readonly id: string;
8
+ readonly source_id: string;
9
+ readonly subject: string;
10
+ readonly predicate: string;
11
+ readonly valid_from: string;
12
+ readonly valid_to: string | null;
13
+ readonly recorded_at: string;
14
+ readonly recorded_seq: number;
15
+ readonly retracts: string | null;
16
+ readonly supersedes: string | null;
17
+ readonly overrides: string | null;
18
+ readonly contract_id: string | null;
19
+ readonly confidence: number | null;
20
+ readonly serializer_version: string;
21
+ readonly encrypted_payload: string;
22
+ }
23
+ export declare function rowToClaimMeta(row: SQLiteRow): ClaimMeta;
24
+ export declare function rowToEncryptedBlob(row: SQLiteRow): EncryptedBlob;
@@ -0,0 +1,28 @@
1
+ // Internal types for SQLiteFactStore.
2
+ //
3
+ // SQLiteRow is the raw DB row shape (snake_case column names).
4
+ // It is NEVER exposed outside src/persistence/sqlite/.
5
+ // Convert a raw SQLite row to a ClaimMeta (metadata only, no payload).
6
+ // CRYPTO_METADATA_PLAINTEXT_ACCEPTED_001: metadata is read directly from columns.
7
+ export function rowToClaimMeta(row) {
8
+ return Object.freeze({
9
+ id: row.id,
10
+ sourceId: row.source_id,
11
+ subject: row.subject,
12
+ predicate: row.predicate,
13
+ validFrom: row.valid_from,
14
+ recordedAt: row.recorded_at,
15
+ recordedSeq: row.recorded_seq,
16
+ ...(row.valid_to != null ? { validTo: row.valid_to } : {}),
17
+ ...(row.retracts != null ? { retracts: row.retracts } : {}),
18
+ ...(row.supersedes != null ? { supersedes: row.supersedes } : {}),
19
+ ...(row.overrides != null ? { overrides: row.overrides } : {}),
20
+ ...(row.contract_id != null ? { contractId: row.contract_id } : {}),
21
+ ...(row.confidence != null ? { confidence: row.confidence } : {}),
22
+ });
23
+ }
24
+ // Parse the encrypted_payload column back to EncryptedBlob.
25
+ export function rowToEncryptedBlob(row) {
26
+ return JSON.parse(row.encrypted_payload);
27
+ }
28
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/persistence/sqlite/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,+DAA+D;AAC/D,uDAAuD;AAgCvD,uEAAuE;AACvE,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,GAAc;IAC3C,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,EAAE,EAAW,GAAG,CAAC,EAAsB;QACvC,QAAQ,EAAK,GAAG,CAAC,SAAuB;QACxC,OAAO,EAAM,GAAG,CAAC,OAAuB;QACxC,SAAS,EAAI,GAAG,CAAC,SAA6B;QAC9C,SAAS,EAAI,GAAG,CAAC,UAAsB;QACvC,UAAU,EAAG,GAAG,CAAC,WAAsB;QACvC,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAO,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAK,GAAG,CAAC,QAAsB,EAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,GAAG,CAAC,QAAQ,IAAO,IAAI,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAI,GAAG,CAAC,QAAsB,EAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,GAAG,CAAC,UAAU,IAAK,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAsB,EAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,GAAG,CAAC,SAAS,IAAM,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAG,GAAG,CAAC,SAAsB,EAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,WAAyB,EAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAClF,GAAG,CAAC,GAAG,CAAC,UAAU,IAAK,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;KACnF,CAAC,CAAC;AACL,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,kBAAkB,CAAC,GAAc;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAkB,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface UnitOfWork {
2
+ run<T>(fn: () => Promise<T>): Promise<T>;
3
+ }
4
+ export declare class NoopUnitOfWork implements UnitOfWork {
5
+ run<T>(fn: () => Promise<T>): Promise<T>;
6
+ }
@@ -0,0 +1,15 @@
1
+ // UnitOfWork — Slice-18.
2
+ //
3
+ // UNIT_OF_WORK_EXISTS_001: this interface is the sole coordination point for multi-write atomicity.
4
+ // UNIT_OF_WORK_COMMIT_ALL_OR_NONE_001: fn completes → all writes committed; fn throws → all writes rolled back.
5
+ // UNIT_OF_WORK_ROLLBACK_ON_FAILURE_001: error propagated to caller after rollback; no silent swallow.
6
+ // UNIT_OF_WORK_NO_RAW_PAYLOAD_LOGGING_001: UoW implementations must not log payload values on failure.
7
+ //
8
+ // NoopUnitOfWork: default (backward-compatible); used when no atomicity is required
9
+ // (e.g., single-store writes, tests that don't probe failure paths).
10
+ export class NoopUnitOfWork {
11
+ async run(fn) {
12
+ return fn();
13
+ }
14
+ }
15
+ //# sourceMappingURL=unit-of-work.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unit-of-work.js","sourceRoot":"","sources":["../../src/persistence/unit-of-work.ts"],"names":[],"mappings":"AAAA,yBAAyB;AACzB,EAAE;AACF,oGAAoG;AACpG,gHAAgH;AAChH,sGAAsG;AACtG,uGAAuG;AACvG,EAAE;AACF,oFAAoF;AACpF,qEAAqE;AAMrE,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,GAAG,CAAI,EAAoB;QAC/B,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ import type { ClaimId } from "../types/ids.js";
2
+ import type { AppendClaimInput } from "../types/claim.js";
3
+ import type { OwnerContext, SystemProjectionContext, TestContext } from "../types/access-context.js";
4
+ export type AppendDecider = OwnerContext | SystemProjectionContext | TestContext;
5
+ export interface AcceptedClaimAppender {
6
+ appendAll(ctx: AppendDecider, claims: ReadonlyArray<AppendClaimInput>): Promise<ReadonlyArray<ClaimId>>;
7
+ }
@@ -0,0 +1,16 @@
1
+ // AcceptedClaimAppender — Slice-08b.
2
+ //
3
+ // PROPOSAL_ACCEPT_NO_RAW_FACTSTORE_001: InMemoryProposalQueue must never hold a reference
4
+ // to a raw FactStore (InMemoryFactStore / SQLiteFactStore). All acceptance writes go through
5
+ // this typed interface, which is only implemented by source-validated adapters.
6
+ //
7
+ // PROPOSAL_ACCEPT_ATOMIC_ROLLBACK_001: appendAll() is an "all or nothing" contract.
8
+ // - If any claim fails SourceRegistry validation (pre-validation phase), no claims are written.
9
+ // - If any claim fails during the write phase, implementations must document their atomicity
10
+ // guarantee (transaction for SQLite; best-effort pre-validation for InMemory).
11
+ // - Callers (InMemoryProposalQueue) must NOT update proposal status until appendAll succeeds.
12
+ //
13
+ // appendAll() must not be called with a raw FactStore — it requires SourceAwareFactStore
14
+ // or equivalent to enforce PROPOSAL_ACCEPT_USES_SOURCE_AWARE_FACTSTORE_001.
15
+ export {};
16
+ //# sourceMappingURL=accepted-claim-appender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"accepted-claim-appender.js","sourceRoot":"","sources":["../../src/proposal/accepted-claim-appender.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,EAAE;AACF,0FAA0F;AAC1F,6FAA6F;AAC7F,gFAAgF;AAChF,EAAE;AACF,oFAAoF;AACpF,kGAAkG;AAClG,+FAA+F;AAC/F,mFAAmF;AACnF,gGAAgG;AAChG,EAAE;AACF,yFAAyF;AACzF,4EAA4E"}
@@ -0,0 +1,21 @@
1
+ import type { ProposalId } from "../types/ids.js";
2
+ import type { AgentConsentContext, AccessContext } from "../types/access-context.js";
3
+ import type { AcceptOptions, Proposal, ProposalDecider, ProposalFilter, ProposalInput } from "../types/proposal.js";
4
+ import type { ProposalQueue } from "./proposal-queue.js";
5
+ import type { AcceptedClaimAppender } from "./accepted-claim-appender.js";
6
+ import type { SourceRegistry } from "../source/source-registry.js";
7
+ import { GrantRegistry } from "../consent/grant-registry.js";
8
+ export declare class InMemoryProposalQueue implements ProposalQueue {
9
+ private readonly _appender;
10
+ private readonly _grantRegistry;
11
+ private readonly _sourceRegistry;
12
+ private readonly _proposals;
13
+ constructor(_appender: AcceptedClaimAppender, _grantRegistry: GrantRegistry, _sourceRegistry: SourceRegistry);
14
+ createProposal(ctx: AgentConsentContext, input: ProposalInput): Promise<Proposal>;
15
+ getProposal(ctx: AccessContext, proposalId: ProposalId): Proposal | undefined;
16
+ listProposals(ctx: AccessContext, filter?: ProposalFilter): Proposal[];
17
+ acceptProposal(ctx: ProposalDecider, proposalId: ProposalId, options: AcceptOptions): Promise<Proposal>;
18
+ rejectProposal(ctx: ProposalDecider, proposalId: ProposalId, reason: string): Promise<Proposal>;
19
+ private _getExistingPending;
20
+ private _spreadProposal;
21
+ }