@opendatalabs/personal-server-ts-core 0.0.1-canary.01ca694 → 0.0.1-canary.052d47e

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 (322) hide show
  1. package/dist/api/index.d.ts +282 -9
  2. package/dist/api/index.d.ts.map +1 -1
  3. package/dist/api/index.js +867 -163
  4. package/dist/api/index.js.map +1 -1
  5. package/dist/auth/request.d.ts.map +1 -1
  6. package/dist/auth/request.js.map +1 -1
  7. package/dist/client.d.ts +8 -1
  8. package/dist/client.d.ts.map +1 -1
  9. package/dist/client.js +21 -3
  10. package/dist/client.js.map +1 -1
  11. package/dist/contracts/binary.d.ts +12 -0
  12. package/dist/contracts/binary.d.ts.map +1 -1
  13. package/dist/contracts/binary.js +31 -0
  14. package/dist/contracts/binary.js.map +1 -1
  15. package/dist/contracts/data.d.ts +51 -5
  16. package/dist/contracts/data.d.ts.map +1 -1
  17. package/dist/contracts/data.js +166 -30
  18. package/dist/contracts/data.js.map +1 -1
  19. package/dist/contracts/grants.d.ts +7 -5
  20. package/dist/contracts/grants.d.ts.map +1 -1
  21. package/dist/contracts/grants.js +60 -37
  22. package/dist/contracts/grants.js.map +1 -1
  23. package/dist/contracts/index.d.ts +1 -1
  24. package/dist/contracts/index.d.ts.map +1 -1
  25. package/dist/contracts/index.js +1 -1
  26. package/dist/contracts/index.js.map +1 -1
  27. package/dist/derivatives/api.d.ts +48 -0
  28. package/dist/derivatives/api.d.ts.map +1 -0
  29. package/dist/derivatives/api.js +366 -0
  30. package/dist/derivatives/api.js.map +1 -0
  31. package/dist/derivatives/compute.d.ts +106 -0
  32. package/dist/derivatives/compute.d.ts.map +1 -0
  33. package/dist/derivatives/compute.js +414 -0
  34. package/dist/derivatives/compute.js.map +1 -0
  35. package/dist/derivatives/e2ee/aad.d.ts +22 -0
  36. package/dist/derivatives/e2ee/aad.d.ts.map +1 -0
  37. package/dist/derivatives/e2ee/aad.js +32 -0
  38. package/dist/derivatives/e2ee/aad.js.map +1 -0
  39. package/dist/derivatives/e2ee/attestation.d.ts +134 -0
  40. package/dist/derivatives/e2ee/attestation.d.ts.map +1 -0
  41. package/dist/derivatives/e2ee/attestation.js +248 -0
  42. package/dist/derivatives/e2ee/attestation.js.map +1 -0
  43. package/dist/derivatives/e2ee/index.d.ts +6 -0
  44. package/dist/derivatives/e2ee/index.d.ts.map +1 -0
  45. package/dist/derivatives/e2ee/index.js +6 -0
  46. package/dist/derivatives/e2ee/index.js.map +1 -0
  47. package/dist/derivatives/e2ee/jcs.d.ts +17 -0
  48. package/dist/derivatives/e2ee/jcs.d.ts.map +1 -0
  49. package/dist/derivatives/e2ee/jcs.js +55 -0
  50. package/dist/derivatives/e2ee/jcs.js.map +1 -0
  51. package/dist/derivatives/e2ee/phala.d.ts +62 -0
  52. package/dist/derivatives/e2ee/phala.d.ts.map +1 -0
  53. package/dist/derivatives/e2ee/phala.js +168 -0
  54. package/dist/derivatives/e2ee/phala.js.map +1 -0
  55. package/dist/derivatives/e2ee/suite.d.ts +56 -0
  56. package/dist/derivatives/e2ee/suite.d.ts.map +1 -0
  57. package/dist/derivatives/e2ee/suite.js +164 -0
  58. package/dist/derivatives/e2ee/suite.js.map +1 -0
  59. package/dist/derivatives/index.d.ts +10 -0
  60. package/dist/derivatives/index.d.ts.map +1 -0
  61. package/dist/derivatives/index.js +10 -0
  62. package/dist/derivatives/index.js.map +1 -0
  63. package/dist/derivatives/inference.d.ts +151 -0
  64. package/dist/derivatives/inference.d.ts.map +1 -0
  65. package/dist/derivatives/inference.js +262 -0
  66. package/dist/derivatives/inference.js.map +1 -0
  67. package/dist/derivatives/prompt.d.ts +64 -0
  68. package/dist/derivatives/prompt.d.ts.map +1 -0
  69. package/dist/derivatives/prompt.js +193 -0
  70. package/dist/derivatives/prompt.js.map +1 -0
  71. package/dist/derivatives/registration.d.ts +54 -0
  72. package/dist/derivatives/registration.d.ts.map +1 -0
  73. package/dist/derivatives/registration.js +180 -0
  74. package/dist/derivatives/registration.js.map +1 -0
  75. package/dist/derivatives/scheduler.d.ts +84 -0
  76. package/dist/derivatives/scheduler.d.ts.map +1 -0
  77. package/dist/derivatives/scheduler.js +257 -0
  78. package/dist/derivatives/scheduler.js.map +1 -0
  79. package/dist/derivatives/store.d.ts +14 -0
  80. package/dist/derivatives/store.d.ts.map +1 -0
  81. package/dist/derivatives/store.js +77 -0
  82. package/dist/derivatives/store.js.map +1 -0
  83. package/dist/derivatives/types.d.ts +92 -0
  84. package/dist/derivatives/types.d.ts.map +1 -0
  85. package/dist/derivatives/types.js +27 -0
  86. package/dist/derivatives/types.js.map +1 -0
  87. package/dist/errors/catalog.d.ts +75 -0
  88. package/dist/errors/catalog.d.ts.map +1 -1
  89. package/dist/errors/catalog.js +104 -0
  90. package/dist/errors/catalog.js.map +1 -1
  91. package/dist/grants/index.d.ts +2 -1
  92. package/dist/grants/index.d.ts.map +1 -1
  93. package/dist/grants/index.js +1 -1
  94. package/dist/grants/index.js.map +1 -1
  95. package/dist/keys/index.d.ts +1 -0
  96. package/dist/keys/index.d.ts.map +1 -1
  97. package/dist/keys/index.js +1 -1
  98. package/dist/keys/index.js.map +1 -1
  99. package/dist/keys/public-only-account.d.ts +8 -0
  100. package/dist/keys/public-only-account.d.ts.map +1 -0
  101. package/dist/keys/public-only-account.js +21 -0
  102. package/dist/keys/public-only-account.js.map +1 -0
  103. package/dist/keys/server-account.d.ts +2 -2
  104. package/dist/keys/server-account.d.ts.map +1 -1
  105. package/dist/lineage/attestation.d.ts +42 -0
  106. package/dist/lineage/attestation.d.ts.map +1 -0
  107. package/dist/lineage/attestation.js +25 -0
  108. package/dist/lineage/attestation.js.map +1 -0
  109. package/dist/lineage/gateway.d.ts +105 -0
  110. package/dist/lineage/gateway.d.ts.map +1 -0
  111. package/dist/lineage/gateway.js +242 -0
  112. package/dist/lineage/gateway.js.map +1 -0
  113. package/dist/lineage/index.d.ts +5 -0
  114. package/dist/lineage/index.d.ts.map +1 -0
  115. package/dist/lineage/index.js +5 -0
  116. package/dist/lineage/index.js.map +1 -0
  117. package/dist/lineage/lineage.d.ts +141 -0
  118. package/dist/lineage/lineage.d.ts.map +1 -0
  119. package/dist/lineage/lineage.js +255 -0
  120. package/dist/lineage/lineage.js.map +1 -0
  121. package/dist/logging/access-log.d.ts +10 -1
  122. package/dist/logging/access-log.d.ts.map +1 -1
  123. package/dist/mcp/activity.d.ts.map +1 -1
  124. package/dist/mcp/activity.js.map +1 -1
  125. package/dist/mcp/connection-api.d.ts.map +1 -1
  126. package/dist/mcp/connection-api.js +0 -1
  127. package/dist/mcp/connection-api.js.map +1 -1
  128. package/dist/mcp/index.d.ts +1 -0
  129. package/dist/mcp/index.d.ts.map +1 -1
  130. package/dist/mcp/index.js +1 -0
  131. package/dist/mcp/index.js.map +1 -1
  132. package/dist/mcp/read-client.d.ts +61 -1
  133. package/dist/mcp/read-client.d.ts.map +1 -1
  134. package/dist/mcp/read-client.js +397 -42
  135. package/dist/mcp/read-client.js.map +1 -1
  136. package/dist/mcp/resources.d.ts +37 -0
  137. package/dist/mcp/resources.d.ts.map +1 -0
  138. package/dist/mcp/resources.js +114 -0
  139. package/dist/mcp/resources.js.map +1 -0
  140. package/dist/mcp/search/index.d.ts.map +1 -1
  141. package/dist/mcp/search/index.js +108 -21
  142. package/dist/mcp/search/index.js.map +1 -1
  143. package/dist/mcp/server.d.ts.map +1 -1
  144. package/dist/mcp/server.js +27 -9
  145. package/dist/mcp/server.js.map +1 -1
  146. package/dist/mcp/session.d.ts +160 -0
  147. package/dist/mcp/session.d.ts.map +1 -0
  148. package/dist/mcp/session.js +243 -0
  149. package/dist/mcp/session.js.map +1 -0
  150. package/dist/mcp/tools.d.ts +29 -3
  151. package/dist/mcp/tools.d.ts.map +1 -1
  152. package/dist/mcp/tools.js +515 -48
  153. package/dist/mcp/tools.js.map +1 -1
  154. package/dist/mcp/types.d.ts.map +1 -1
  155. package/dist/payment/index.d.ts +2 -0
  156. package/dist/payment/index.d.ts.map +1 -0
  157. package/dist/payment/index.js +2 -0
  158. package/dist/payment/index.js.map +1 -0
  159. package/dist/payment/x402.d.ts +155 -0
  160. package/dist/payment/x402.d.ts.map +1 -0
  161. package/dist/payment/x402.js +402 -0
  162. package/dist/payment/x402.js.map +1 -0
  163. package/dist/policy/data-read.d.ts +18 -2
  164. package/dist/policy/data-read.d.ts.map +1 -1
  165. package/dist/policy/data-read.js +80 -49
  166. package/dist/policy/data-read.js.map +1 -1
  167. package/dist/policy/data-write.d.ts +69 -0
  168. package/dist/policy/data-write.d.ts.map +1 -0
  169. package/dist/policy/data-write.js +131 -0
  170. package/dist/policy/data-write.js.map +1 -0
  171. package/dist/policy/index.d.ts +3 -1
  172. package/dist/policy/index.d.ts.map +1 -1
  173. package/dist/policy/index.js +3 -1
  174. package/dist/policy/index.js.map +1 -1
  175. package/dist/policy/signed-artifacts.d.ts +17 -0
  176. package/dist/policy/signed-artifacts.d.ts.map +1 -0
  177. package/dist/policy/signed-artifacts.js +110 -0
  178. package/dist/policy/signed-artifacts.js.map +1 -0
  179. package/dist/ports/index.d.ts +159 -32
  180. package/dist/ports/index.d.ts.map +1 -1
  181. package/dist/ports/index.js +6 -5
  182. package/dist/ports/index.js.map +1 -1
  183. package/dist/schemas/server-config.d.ts +49 -4
  184. package/dist/schemas/server-config.d.ts.map +1 -1
  185. package/dist/schemas/server-config.js +95 -13
  186. package/dist/schemas/server-config.js.map +1 -1
  187. package/dist/signing/index.d.ts +2 -2
  188. package/dist/signing/index.d.ts.map +1 -1
  189. package/dist/signing/index.js +1 -1
  190. package/dist/signing/index.js.map +1 -1
  191. package/dist/signing/request-signer.d.ts +2 -0
  192. package/dist/signing/request-signer.d.ts.map +1 -1
  193. package/dist/signing/request-signer.js +1 -0
  194. package/dist/signing/request-signer.js.map +1 -1
  195. package/dist/signing/signer.d.ts +27 -25
  196. package/dist/signing/signer.d.ts.map +1 -1
  197. package/dist/signing/signer.js +27 -51
  198. package/dist/signing/signer.js.map +1 -1
  199. package/dist/storage/adapters/index.d.ts +1 -1
  200. package/dist/storage/adapters/index.d.ts.map +1 -1
  201. package/dist/storage/adapters/index.js +1 -1
  202. package/dist/storage/adapters/index.js.map +1 -1
  203. package/dist/storage/adapters/interface.d.ts +10 -0
  204. package/dist/storage/adapters/interface.d.ts.map +1 -1
  205. package/dist/storage/adapters/sdk.d.ts +11 -1
  206. package/dist/storage/adapters/sdk.d.ts.map +1 -1
  207. package/dist/storage/adapters/sdk.js +38 -3
  208. package/dist/storage/adapters/sdk.js.map +1 -1
  209. package/dist/storage/adapters/vana.d.ts +3 -0
  210. package/dist/storage/adapters/vana.d.ts.map +1 -1
  211. package/dist/storage/adapters/vana.js +95 -2
  212. package/dist/storage/adapters/vana.js.map +1 -1
  213. package/dist/storage/blocks/errors.d.ts.map +1 -1
  214. package/dist/storage/blocks/errors.js.map +1 -1
  215. package/dist/storage/blocks/index.d.ts +2 -0
  216. package/dist/storage/blocks/index.d.ts.map +1 -1
  217. package/dist/storage/blocks/index.js +2 -0
  218. package/dist/storage/blocks/index.js.map +1 -1
  219. package/dist/storage/blocks/select.d.ts +29 -0
  220. package/dist/storage/blocks/select.d.ts.map +1 -0
  221. package/dist/storage/blocks/select.js +120 -0
  222. package/dist/storage/blocks/select.js.map +1 -0
  223. package/dist/storage/blocks/types.d.ts +7 -0
  224. package/dist/storage/blocks/types.d.ts.map +1 -1
  225. package/dist/storage/index/manager.d.ts +30 -2
  226. package/dist/storage/index/manager.d.ts.map +1 -1
  227. package/dist/storage/index/schema.d.ts +1 -1
  228. package/dist/storage/index/schema.js +1 -1
  229. package/dist/storage/index/types.d.ts +6 -1
  230. package/dist/storage/index/types.d.ts.map +1 -1
  231. package/dist/sync/data-point-feed.d.ts +35 -0
  232. package/dist/sync/data-point-feed.d.ts.map +1 -0
  233. package/dist/sync/data-point-feed.js +122 -0
  234. package/dist/sync/data-point-feed.js.map +1 -0
  235. package/dist/sync/data-point-id.d.ts +7 -0
  236. package/dist/sync/data-point-id.d.ts.map +1 -0
  237. package/dist/sync/data-point-id.js +16 -0
  238. package/dist/sync/data-point-id.js.map +1 -0
  239. package/dist/sync/delete-data-port.d.ts +50 -0
  240. package/dist/sync/delete-data-port.d.ts.map +1 -0
  241. package/dist/sync/delete-data-port.js +244 -0
  242. package/dist/sync/delete-data-port.js.map +1 -0
  243. package/dist/sync/engine/sync-manager.d.ts +16 -4
  244. package/dist/sync/engine/sync-manager.d.ts.map +1 -1
  245. package/dist/sync/engine/sync-manager.js +93 -32
  246. package/dist/sync/engine/sync-manager.js.map +1 -1
  247. package/dist/sync/index.d.ts +7 -0
  248. package/dist/sync/index.d.ts.map +1 -1
  249. package/dist/sync/index.js +7 -0
  250. package/dist/sync/index.js.map +1 -1
  251. package/dist/sync/issues.d.ts.map +1 -1
  252. package/dist/sync/issues.js +21 -3
  253. package/dist/sync/issues.js.map +1 -1
  254. package/dist/sync/pending-blob-deletions.d.ts +29 -0
  255. package/dist/sync/pending-blob-deletions.d.ts.map +1 -0
  256. package/dist/sync/pending-blob-deletions.js +116 -0
  257. package/dist/sync/pending-blob-deletions.js.map +1 -0
  258. package/dist/sync/retry-memory.d.ts +33 -0
  259. package/dist/sync/retry-memory.d.ts.map +1 -0
  260. package/dist/sync/retry-memory.js +68 -0
  261. package/dist/sync/retry-memory.js.map +1 -0
  262. package/dist/sync/scope-deletions.d.ts +155 -0
  263. package/dist/sync/scope-deletions.d.ts.map +1 -0
  264. package/dist/sync/scope-deletions.js +225 -0
  265. package/dist/sync/scope-deletions.js.map +1 -0
  266. package/dist/sync/tombstone.d.ts +27 -0
  267. package/dist/sync/tombstone.d.ts.map +1 -0
  268. package/dist/sync/tombstone.js +28 -0
  269. package/dist/sync/tombstone.js.map +1 -0
  270. package/dist/sync/workers/delete.d.ts +152 -31
  271. package/dist/sync/workers/delete.d.ts.map +1 -1
  272. package/dist/sync/workers/delete.js +457 -55
  273. package/dist/sync/workers/delete.js.map +1 -1
  274. package/dist/sync/workers/download.d.ts +108 -27
  275. package/dist/sync/workers/download.d.ts.map +1 -1
  276. package/dist/sync/workers/download.js +321 -126
  277. package/dist/sync/workers/download.js.map +1 -1
  278. package/dist/sync/workers/upload.d.ts +65 -10
  279. package/dist/sync/workers/upload.d.ts.map +1 -1
  280. package/dist/sync/workers/upload.js +371 -42
  281. package/dist/sync/workers/upload.js.map +1 -1
  282. package/dist/test-utils/e2ee-fixtures.d.ts +94 -0
  283. package/dist/test-utils/e2ee-fixtures.d.ts.map +1 -0
  284. package/dist/test-utils/e2ee-fixtures.js +116 -0
  285. package/dist/test-utils/e2ee-fixtures.js.map +1 -0
  286. package/dist/test-utils/e2ee-gateway.d.ts +61 -0
  287. package/dist/test-utils/e2ee-gateway.d.ts.map +1 -0
  288. package/dist/test-utils/e2ee-gateway.js +248 -0
  289. package/dist/test-utils/e2ee-gateway.js.map +1 -0
  290. package/dist/test-utils/index.d.ts +3 -0
  291. package/dist/test-utils/index.d.ts.map +1 -1
  292. package/dist/test-utils/index.js +3 -0
  293. package/dist/test-utils/index.js.map +1 -1
  294. package/dist/test-utils/memory-storage.d.ts +12 -0
  295. package/dist/test-utils/memory-storage.d.ts.map +1 -0
  296. package/dist/test-utils/memory-storage.js +146 -0
  297. package/dist/test-utils/memory-storage.js.map +1 -0
  298. package/dist/test-utils/wallet.d.ts +6 -0
  299. package/dist/test-utils/wallet.d.ts.map +1 -1
  300. package/dist/test-utils/wallet.js +46 -0
  301. package/dist/test-utils/wallet.js.map +1 -1
  302. package/dist/write/attribution.d.ts +185 -0
  303. package/dist/write/attribution.d.ts.map +1 -0
  304. package/dist/write/attribution.js +450 -0
  305. package/dist/write/attribution.js.map +1 -0
  306. package/dist/write/authorize.d.ts +77 -0
  307. package/dist/write/authorize.d.ts.map +1 -0
  308. package/dist/write/authorize.js +109 -0
  309. package/dist/write/authorize.js.map +1 -0
  310. package/dist/write/index.d.ts +5 -0
  311. package/dist/write/index.d.ts.map +1 -0
  312. package/dist/write/index.js +5 -0
  313. package/dist/write/index.js.map +1 -0
  314. package/dist/write/route.d.ts +61 -0
  315. package/dist/write/route.d.ts.map +1 -0
  316. package/dist/write/route.js +132 -0
  317. package/dist/write/route.js.map +1 -0
  318. package/dist/write/session.d.ts +96 -0
  319. package/dist/write/session.d.ts.map +1 -0
  320. package/dist/write/session.js +136 -0
  321. package/dist/write/session.js.map +1 -0
  322. package/package.json +19 -3
@@ -0,0 +1,450 @@
1
+ /**
2
+ * Builder attribution for delegated writes.
3
+ *
4
+ * The write-session token authorizes a write; it does not PROVE who authored
5
+ * the payload (a bearer token is not a signature). For cryptographic
6
+ * attribution the builder also signs the payload: a Web3Signed proof over the
7
+ * exact write request (aud / method / uri / bodyHash / iat / exp), carried in
8
+ * the `X-Vana-Write-Signature` header and signed by the builder key proven at
9
+ * handshake. The PS verifies the proof recovers to the session's builder and
10
+ * that its bodyHash commits to the received bytes, then stores the proof and
11
+ * the builder identity WITH the record — inside the envelope's `data` under
12
+ * the reserved `$writtenBy` key (same in-`data` marker idiom as `$binary`),
13
+ * so attribution travels through the unchanged encrypt / upload / register
14
+ * path and back out on read. The on-chain shape is untouched.
15
+ *
16
+ * The proof binds the write to its context, not just its bytes: the signed
17
+ * claims carry the request uri (path AND query, see canonicalSignedUri; the
18
+ * path's last segment is the scope on the ingest route), the method, the
19
+ * audience (this server's origin) and the session's grantId, which the PS
20
+ * requires to match the session at ingest. A stored `$writtenBy` therefore
21
+ * cannot be lifted onto another scope's record or relabelled with a
22
+ * different grant and still verify. A proof may also carry an optional
23
+ * `nonce` claim, which is what makes it unique: without one, two identical
24
+ * requests signed in the same second are byte-identical and the replay guard
25
+ * refuses the second.
26
+ *
27
+ * What the builder signs is the STORED representation, not the wire body:
28
+ * the compact JSON of the envelope `data` record the PS will write (minus
29
+ * `$writtenBy`). A third party holding the envelope can therefore verify
30
+ * authorship from the envelope ALONE (verifyStoredWriterAttribution): recover
31
+ * the signer over the stored proof's base64url payload (EIP-191), check the
32
+ * signed claims against the envelope's scope and stored grantId, and hash
33
+ * JSON.stringify(data minus the server-stamped keys `$writtenBy` and
34
+ * `$lineage`) against the signed bodyHash.
35
+ * - JSON writes: the body IS the stored record, so the builder signs the
36
+ * body bytes, which must be compact JSON (what JSON.stringify emits: no
37
+ * insignificant whitespace, keys in the order given). JSON.parse /
38
+ * JSON.stringify round-trips that byte-for-byte; a body that does not
39
+ * round-trip is rejected at write time (WRITE_BODY_NOT_CANONICAL) instead
40
+ * of being stored with an attribution nobody can check.
41
+ * - Binary writes: the stored record is the `$binary` envelope data (media
42
+ * type, filename, caller metadata, size, content hash, base64 content),
43
+ * so the builder signs its compact JSON (binaryWriteSignedBytes). That
44
+ * binds the caller-controlled representation headers (Content-Type,
45
+ * X-Filename / Content-Disposition, X-Vana-Metadata) to the signature and
46
+ * makes a JSON-vs-binary switch of the same bytes fail verification.
47
+ */
48
+ import { computeBodyHash, parseWeb3SignedHeader, verifyWeb3Signed, } from "@opendatalabs/vana-sdk/browser";
49
+ import { recoverMessageAddress } from "viem";
50
+ import { ProtocolError } from "../errors/catalog.js";
51
+ import { hashConnectionToken as sha256HexOf } from "../mcp/connection-api.js";
52
+ import { binaryFilename, binaryMimeType, buildBinaryEnvelopeData, isJsonContentType, normalizeBinaryMimeType, parseMetadataHeader, sha256Hex, } from "../contracts/binary.js";
53
+ import { LINEAGE_KEY, StoredLineageMalformedError, extractLineageField, readStoredLineage, } from "../lineage/lineage.js";
54
+ import { isBinaryEnvelope } from "../contracts/binary.js";
55
+ /** Header carrying the builder's signed-payload proof on a session write. */
56
+ export const WRITE_SIGNATURE_HEADER = "x-vana-write-signature";
57
+ /**
58
+ * Upper bound on the optional `nonce` claim (a uuid or a short random
59
+ * string is the intended shape). Bounded so a proof cannot smuggle bulk
60
+ * data into the replay store's keys.
61
+ */
62
+ export const MAX_PROOF_NONCE_LENGTH = 128;
63
+ /** HTTP methods that never carry a body on this API. */
64
+ function isBodylessMethod(method) {
65
+ const upper = method.toUpperCase();
66
+ return upper === "GET" || upper === "HEAD" || upper === "DELETE";
67
+ }
68
+ /**
69
+ * Canonical query string: parameters sorted by name and then value. The
70
+ * signed uri must commit to the query because a query parameter can decide
71
+ * authorization (`GET /v1/derivatives/questions?derivedScope=X` authorizes
72
+ * the caller against that scope), and a proof that does not cover it can be
73
+ * replayed against a different scope. Sorting makes the rule insensitive to
74
+ * the order a client happens to serialize its parameters in.
75
+ */
76
+ function canonicalQuery(search) {
77
+ const entries = [...new URLSearchParams(search).entries()].sort((a, b) => a[0] === b[0]
78
+ ? a[1] < b[1]
79
+ ? -1
80
+ : a[1] > b[1]
81
+ ? 1
82
+ : 0
83
+ : a[0] < b[0]
84
+ ? -1
85
+ : 1);
86
+ const canonical = new URLSearchParams();
87
+ for (const [name, value] of entries)
88
+ canonical.append(name, value);
89
+ return canonical.toString();
90
+ }
91
+ /**
92
+ * The uri a proof must commit to for a request: the path, plus the canonical
93
+ * query when the request carries one. A request with no query string signs
94
+ * the bare path exactly as before.
95
+ */
96
+ export function canonicalSignedUri(pathname, search) {
97
+ const query = canonicalQuery(search);
98
+ return query ? `${pathname}?${query}` : pathname;
99
+ }
100
+ /** The same canonical form applied to a signed `uri` claim. */
101
+ export function canonicalizeSignedUri(uri) {
102
+ const mark = uri.indexOf("?");
103
+ if (mark === -1)
104
+ return uri;
105
+ return canonicalSignedUri(uri.slice(0, mark), uri.slice(mark + 1));
106
+ }
107
+ function base64UrlDecode(value) {
108
+ const base64 = value.replace(/-/g, "+").replace(/_/g, "/");
109
+ const padded = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), "=");
110
+ const binary = atob(padded);
111
+ return new TextDecoder().decode(Uint8Array.from(binary, (char) => char.charCodeAt(0)));
112
+ }
113
+ /**
114
+ * The proof's optional `nonce` claim. Read from the raw signed payload, not
115
+ * from the verified claims: the SDK's parser keeps only the claims it knows,
116
+ * and the nonce is covered by the signature all the same (the signature is
117
+ * over the base64url payload string).
118
+ */
119
+ function signedNonce(payloadBase64) {
120
+ let raw;
121
+ try {
122
+ raw = JSON.parse(base64UrlDecode(payloadBase64));
123
+ }
124
+ catch {
125
+ // A payload that does not decode is rejected by verifyWeb3Signed.
126
+ return undefined;
127
+ }
128
+ if (typeof raw !== "object" || raw === null)
129
+ return undefined;
130
+ const nonce = raw.nonce;
131
+ if (nonce === undefined || nonce === null)
132
+ return undefined;
133
+ if (typeof nonce !== "string" ||
134
+ nonce.length === 0 ||
135
+ nonce.length > MAX_PROOF_NONCE_LENGTH) {
136
+ throw new ProtocolError(401, "WRITE_ATTRIBUTION_INVALID", `Payload proof nonce must be a string of 1 to ${MAX_PROOF_NONCE_LENGTH} characters`);
137
+ }
138
+ return nonce;
139
+ }
140
+ /**
141
+ * Reserved key inside the envelope's `data` record for builder attribution.
142
+ * Mirrors the `$binary` marker convention (contracts/binary.ts).
143
+ */
144
+ export const WRITER_ATTRIBUTION_KEY = "$writtenBy";
145
+ function resolveOrigin(origin) {
146
+ return typeof origin === "function" ? origin() : origin;
147
+ }
148
+ /**
149
+ * The bytes a builder signs (as the Web3Signed body) for a BINARY session
150
+ * write: the compact JSON of the `$binary` record the PS stores for these
151
+ * headers and bytes. Mirrors ingest exactly (same media-type normalization,
152
+ * metadata parsing and envelope builder), so the signature covers the stored
153
+ * representation and verifyStoredWriterAttribution can re-derive it.
154
+ */
155
+ export async function binaryWriteSignedBytes(input) {
156
+ const data = buildBinaryEnvelopeData({
157
+ bytes: input.bytes,
158
+ mimeType: normalizeBinaryMimeType(input.contentType),
159
+ filename: input.filename,
160
+ contentHash: await sha256Hex(input.bytes),
161
+ metadata: parseMetadataHeader(input.metadataHeader ?? null),
162
+ });
163
+ return new TextEncoder().encode(JSON.stringify(data));
164
+ }
165
+ /**
166
+ * The bytes the proof must commit to for this request: the body itself for
167
+ * a JSON write, the stored `$binary` representation for anything else.
168
+ */
169
+ async function signedBytesFor(request, bodyBytes) {
170
+ // A bodyless method has no stored representation to sign: the proof
171
+ // commits to the empty body, whatever Content-Type the caller sent.
172
+ if (isBodylessMethod(request.method))
173
+ return bodyBytes;
174
+ if (isJsonContentType(request))
175
+ return bodyBytes;
176
+ return binaryWriteSignedBytes({
177
+ bytes: bodyBytes,
178
+ contentType: binaryMimeType(request),
179
+ filename: binaryFilename(request),
180
+ metadataHeader: request.headers.get("x-vana-metadata") ?? undefined,
181
+ });
182
+ }
183
+ /**
184
+ * Verify the `X-Vana-Write-Signature` proof on a session write and produce
185
+ * the attribution record to store with the data. Throws ProtocolError(401)
186
+ * when the proof is missing, malformed, expired, fails EIP-191 recovery /
187
+ * bodyHash binding (the hash covers the stored representation, see
188
+ * signedBytesFor), recovers to a different key than the session builder, or
189
+ * does not carry the session's grantId as a signed claim.
190
+ */
191
+ export async function verifyWriterAttribution(input) {
192
+ const headerValue = input.request.headers.get(WRITE_SIGNATURE_HEADER) ?? undefined;
193
+ if (!headerValue) {
194
+ throw new ProtocolError(401, "WRITE_ATTRIBUTION_REQUIRED", `Session writes must carry a builder-signed payload proof in ${WRITE_SIGNATURE_HEADER}`);
195
+ }
196
+ const url = new URL(input.request.url);
197
+ const bodyBytes = new Uint8Array(await input.request.clone().arrayBuffer());
198
+ // The proof must commit to the whole request uri, query included. Any
199
+ // signed uri whose canonical form equals the request's canonical form is
200
+ // accepted, so parameter order is the client's business; anything else is
201
+ // handed to verifyWeb3Signed as a URI mismatch against the canonical form.
202
+ const expectedUri = canonicalSignedUri(url.pathname, url.search);
203
+ let expectedPath = expectedUri;
204
+ try {
205
+ const claimedUri = parseWeb3SignedHeader(headerValue).payload.uri;
206
+ if (canonicalizeSignedUri(claimedUri) === expectedUri) {
207
+ expectedPath = claimedUri;
208
+ }
209
+ }
210
+ catch {
211
+ // Unparseable header: verifyWeb3Signed reports it with its own error.
212
+ }
213
+ let verified;
214
+ try {
215
+ verified = await verifyWeb3Signed({
216
+ headerValue,
217
+ expectedOrigin: resolveOrigin(input.serverOrigin),
218
+ expectedMethod: input.request.method,
219
+ expectedPath,
220
+ bodyBytes: await signedBytesFor(input.request, bodyBytes),
221
+ });
222
+ }
223
+ catch (err) {
224
+ throw new ProtocolError(401, "WRITE_ATTRIBUTION_INVALID", err instanceof Error ? err.message : String(err));
225
+ }
226
+ if (verified.signer.toLowerCase() !== input.builderAddress.toLowerCase()) {
227
+ throw new ProtocolError(401, "WRITE_ATTRIBUTION_SIGNER_MISMATCH", "Payload proof is not signed by the session builder", { expected: input.builderAddress, actual: verified.signer });
228
+ }
229
+ // The grant is a signed claim, so the stored attribution's grantId is
230
+ // covered by the builder's signature rather than being a bare label.
231
+ if (verified.payload.grantId !== input.grantId) {
232
+ throw new ProtocolError(401, "WRITE_ATTRIBUTION_GRANT_MISMATCH", "Payload proof must carry the write session's grantId as a signed claim", { expected: input.grantId, actual: verified.payload.grantId ?? null });
233
+ }
234
+ // The compact `{payload}.{signature}` form (scheme prefix stripped) is what
235
+ // gets stored, so verifiers don't need to know the header framing; the raw
236
+ // payload is also where the optional `nonce` claim is read from.
237
+ const { payloadBase64, signature } = parseWeb3SignedHeader(headerValue);
238
+ const nonce = signedNonce(payloadBase64);
239
+ // Bodyless methods (the derivative read / delete routes) never carry a
240
+ // body: skip the canonical-JSON rule explicitly instead of running it over
241
+ // empty bytes, where isJsonContentType's missing-header default would send
242
+ // it into a swallowed JSON.parse throw.
243
+ if (!isBodylessMethod(input.request.method) &&
244
+ bodyBytes.byteLength > 0 &&
245
+ isJsonContentType(input.request)) {
246
+ assertCanonicalJsonBody(bodyBytes);
247
+ }
248
+ // Replay guard, last: only a proof that passed every check is consumed,
249
+ // so a rejected request never burns a proof.
250
+ //
251
+ // Without a `nonce` claim the key is the proof itself, so two identical
252
+ // requests signed in the same second (a naive poll of GET /questions/:id)
253
+ // produce byte-identical proofs and the second is refused. A proof that
254
+ // carries a nonce is keyed by (builder, nonce) instead: the builder makes
255
+ // each call distinct, and re-using a nonce is a replay even if the rest of
256
+ // the payload changed.
257
+ let releaseProof;
258
+ if (input.replayStore) {
259
+ const store = input.replayStore;
260
+ const proofId = await sha256HexOf(nonce === undefined
261
+ ? headerValue
262
+ : `nonce:${input.builderAddress.toLowerCase()}:${nonce}`);
263
+ const replayed = await store.consume(proofId, verified.payload.exp * 1000);
264
+ if (replayed) {
265
+ throw new ProtocolError(401, "WRITE_ATTRIBUTION_REPLAY", nonce === undefined
266
+ ? "Payload proof already used; sign a fresh proof for each call (or add a unique nonce claim so repeated reads stay distinct)"
267
+ : "Payload proof nonce already used; each nonce is single use");
268
+ }
269
+ releaseProof = async () => {
270
+ await store.release?.(proofId);
271
+ };
272
+ }
273
+ return {
274
+ builder: input.builderAddress,
275
+ grantId: input.grantId,
276
+ signature: `${payloadBase64}.${signature}`,
277
+ bodyHash: verified.payload.bodyHash,
278
+ writtenAt: (input.now?.() ?? new Date()).toISOString(),
279
+ ...(releaseProof ? { releaseProof } : {}),
280
+ };
281
+ }
282
+ /**
283
+ * Stamp attribution into an envelope `data` record. The reserved key must not
284
+ * appear in the caller's payload — a builder must not be able to forge (or
285
+ * shadow) its own attribution.
286
+ */
287
+ export function stampWriterAttribution(data, attribution) {
288
+ return { ...data, [WRITER_ATTRIBUTION_KEY]: attribution };
289
+ }
290
+ export function hasReservedWriterKey(data) {
291
+ return Object.prototype.hasOwnProperty.call(data, WRITER_ATTRIBUTION_KEY);
292
+ }
293
+ /**
294
+ * A JSON session write must be the compact serialization of its own parsed
295
+ * value, so the record stored after JSON.parse re-serializes to the signed
296
+ * bytes. Bodies that do not parse are left to the ingest path, which reports
297
+ * the parse error itself.
298
+ */
299
+ function assertCanonicalJsonBody(bodyBytes) {
300
+ const text = new TextDecoder().decode(bodyBytes);
301
+ let parsed;
302
+ try {
303
+ parsed = JSON.parse(text);
304
+ }
305
+ catch {
306
+ return;
307
+ }
308
+ if (JSON.stringify(parsed) !== text) {
309
+ throw new ProtocolError(400, "WRITE_BODY_NOT_CANONICAL", "Session writes must send compact JSON (the JSON.stringify form) so the stored record re-serializes to the signed bytes and the attribution bodyHash stays verifiable");
310
+ }
311
+ }
312
+ /** Proof scheme prefix the compact stored signature was stripped of. */
313
+ const WEB3_SIGNED_SCHEME = "Web3Signed";
314
+ export class WriterAttributionVerificationError extends Error {
315
+ reason;
316
+ constructor(reason, message) {
317
+ super(message);
318
+ this.reason = reason;
319
+ this.name = "WriterAttributionVerificationError";
320
+ }
321
+ }
322
+ function isWriterAttribution(value) {
323
+ if (typeof value !== "object" || value === null)
324
+ return false;
325
+ const v = value;
326
+ return (typeof v.builder === "string" &&
327
+ v.builder.startsWith("0x") &&
328
+ typeof v.grantId === "string" &&
329
+ typeof v.signature === "string" &&
330
+ typeof v.bodyHash === "string" &&
331
+ typeof v.writtenAt === "string");
332
+ }
333
+ /** Last path segment of the signed request uri, i.e. the scope written to. */
334
+ function signedScopeOf(uri) {
335
+ const path = uri.split("?")[0] ?? "";
336
+ const segment = path.slice(path.lastIndexOf("/") + 1);
337
+ if (!segment)
338
+ return null;
339
+ try {
340
+ return decodeURIComponent(segment);
341
+ }
342
+ catch {
343
+ return null;
344
+ }
345
+ }
346
+ /**
347
+ * Verify builder attribution from a stored envelope alone (no request, no
348
+ * server state, no expiry check: the proof is evidence of who wrote the
349
+ * record at the time, not a live credential). Checks, in order: the envelope
350
+ * carries an attribution; the stored representation (compact JSON of the
351
+ * data minus the server-stamped `$writtenBy` and `$lineage` keys, for JSON
352
+ * and `$binary` records alike) re-hashes
353
+ * to the signed bodyHash; the proof parses and recovers to the attributed
354
+ * builder; and the signed claims bind the proof to THIS record: a POST whose
355
+ * path names the envelope's scope, the stored grantId, and (when given) the
356
+ * server origin. Throws WriterAttributionVerificationError with the reason.
357
+ */
358
+ export async function verifyStoredWriterAttribution(envelope, options = {}) {
359
+ const data = envelope.data;
360
+ const attribution = data[WRITER_ATTRIBUTION_KEY];
361
+ if (!isWriterAttribution(attribution)) {
362
+ throw new WriterAttributionVerificationError("ATTRIBUTION_MISSING", `Record carries no ${WRITER_ATTRIBUTION_KEY} attribution`);
363
+ }
364
+ // Every server-stamped reserved key is stripped, not just the attribution:
365
+ // `$lineage` is the server's validated mirror of the caller's `lineage`
366
+ // field (the field itself stays inside the signed bytes), so a derivative
367
+ // record re-hashes to the same signed bodyHash as a root record.
368
+ const { [WRITER_ATTRIBUTION_KEY]: _attribution, [LINEAGE_KEY]: storedLineage, ...payloadData } = data;
369
+ const bodyHash = computeBodyHash(new TextEncoder().encode(JSON.stringify(payloadData)));
370
+ if (bodyHash !== attribution.bodyHash) {
371
+ throw new WriterAttributionVerificationError("BODY_HASH_MISMATCH", "Stored record does not hash to the attribution bodyHash");
372
+ }
373
+ let proof;
374
+ let signer;
375
+ try {
376
+ proof = parseWeb3SignedHeader(`${WEB3_SIGNED_SCHEME} ${attribution.signature}`);
377
+ signer = await recoverMessageAddress({
378
+ message: proof.payloadBase64,
379
+ signature: proof.signature,
380
+ });
381
+ }
382
+ catch (err) {
383
+ throw new WriterAttributionVerificationError("PROOF_INVALID", err instanceof Error ? err.message : String(err));
384
+ }
385
+ if (proof.payload.bodyHash !== bodyHash) {
386
+ throw new WriterAttributionVerificationError("BODY_HASH_MISMATCH", "Stored proof does not commit to the attribution bodyHash");
387
+ }
388
+ if (signer.toLowerCase() !== attribution.builder.toLowerCase()) {
389
+ throw new WriterAttributionVerificationError("SIGNER_MISMATCH", "Stored proof is not signed by the attributed builder");
390
+ }
391
+ // Context binding: the signed claims must describe a write of THIS record.
392
+ if (proof.payload.method !== "POST" ||
393
+ signedScopeOf(proof.payload.uri) !== envelope.scope) {
394
+ throw new WriterAttributionVerificationError("SCOPE_MISMATCH", `Stored proof is not a write to scope ${envelope.scope}`);
395
+ }
396
+ if (proof.payload.grantId !== attribution.grantId) {
397
+ throw new WriterAttributionVerificationError("GRANT_MISMATCH", "Stored grantId is not the grant the builder signed");
398
+ }
399
+ if (options.expectedOrigin !== undefined &&
400
+ proof.payload.aud !== options.expectedOrigin) {
401
+ throw new WriterAttributionVerificationError("AUDIENCE_MISMATCH", "Stored proof was not addressed to this server");
402
+ }
403
+ // The stripped mirror is not unauthenticated for that: it must restate
404
+ // the builder-signed `lineage` field (body top level, or the binary
405
+ // record's metadata object) in both directions, so a `$lineage` edited
406
+ // after the write, or one removed to hide a derivative's sources, is
407
+ // caught even though it is outside the hashed bytes. A signed list
408
+ // (empty included: an explicit root statement) must have its mirror; an
409
+ // absent signed field must have none.
410
+ const signedField = extractLineageField(isBinaryEnvelope({ data: payloadData })
411
+ ? payloadData.metadata
412
+ : payloadData);
413
+ // Absent or null means "no statement". Anything else that is not a list
414
+ // of strings is a malformed signed field: an independently constructed
415
+ // record must not pass verification just because its lineage claim is
416
+ // unreadable, so it is a mismatch, never "absent".
417
+ const signedAbsent = signedField === undefined || signedField === null;
418
+ const signedWellFormed = Array.isArray(signedField) &&
419
+ signedField.every((id) => typeof id === "string");
420
+ const signed = signedAbsent || !signedWellFormed
421
+ ? null
422
+ : signedField.map((id) => id.toLowerCase());
423
+ let mirror;
424
+ try {
425
+ mirror = storedLineage === undefined ? null : readStoredLineage(data);
426
+ }
427
+ catch (error) {
428
+ if (error instanceof StoredLineageMalformedError) {
429
+ throw new WriterAttributionVerificationError("LINEAGE_MISMATCH", `stored $lineage mirror is malformed: ${error.message}`);
430
+ }
431
+ throw error;
432
+ }
433
+ const consistent = !signedAbsent && !signedWellFormed
434
+ ? false
435
+ : signed === null
436
+ ? storedLineage === undefined
437
+ : mirror !== null &&
438
+ signed.length === mirror.sources.length &&
439
+ signed.every((id, i) => id === mirror.sources[i]);
440
+ if (!consistent) {
441
+ throw new WriterAttributionVerificationError("LINEAGE_MISMATCH", "Stored $lineage does not restate the builder-signed lineage field");
442
+ }
443
+ return {
444
+ builder: attribution.builder,
445
+ grantId: attribution.grantId,
446
+ bodyHash,
447
+ payload: proof.payload,
448
+ };
449
+ }
450
+ //# sourceMappingURL=attribution.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attribution.js","sourceRoot":"","sources":["../../src/write/attribution.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Delegated-write authorization, shared by every build.
3
+ *
4
+ * `authorizeWrite` / `authorizeWriteSession` are the two write-session halves
5
+ * of `PersonalServerApiAuthPort`. They were originally written inside the Node
6
+ * server's auth adapter (packages/server/src/api-auth.ts); the checks they run
7
+ * are pure protocol — a token hash, a live grant re-check, an EIP-191 payload
8
+ * proof and a replay reservation — with nothing Node-specific in them, so they
9
+ * live here and BOTH the Node server adapter and the browser (PS-Lite)
10
+ * adapters call the same code. There is exactly one implementation of the
11
+ * write policy; a browser build cannot drift into a weaker one.
12
+ *
13
+ * The two entry points differ in what they are allowed to decide:
14
+ *
15
+ * - `authorizeSessionWrite` authorizes a write to a NAMED scope. It
16
+ * re-runs `verifyDataWritePolicy` against the LIVE grant on every call,
17
+ * so revocation, expiry, grantee binding, owner binding and scope
18
+ * coverage stay authoritative per write rather than being frozen at
19
+ * handshake, and it verifies the builder's per-write payload proof.
20
+ * - `recognizeWriteSession` is identity only: the bearer must resolve to a
21
+ * live session and the request must carry that builder's valid proof, but
22
+ * NO grant policy runs (there is no scope to run one against). Callers use
23
+ * it only to choose between error shapes, never to release data.
24
+ *
25
+ * Both fail closed: an unknown bearer, an unknown session, a missing server
26
+ * owner, or any failing proof check returns/raises rather than falling back to
27
+ * a weaker credential. A request that is not a write-session request at all
28
+ * returns `undefined`, and the caller applies its own owner gate.
29
+ */
30
+ import { ProtocolError } from "../errors/catalog.js";
31
+ import { type DataWritePolicyPorts } from "../policy/data-write.js";
32
+ import type { PersonalServerWriteAuthInput, PersonalServerWriteAuthResult, PersonalServerWriteSessionResult } from "../api/index.js";
33
+ import { type WriteProofReplayStore, type WriteSessionStore } from "./session.js";
34
+ export interface WriteSessionAuthorizationDeps {
35
+ /**
36
+ * This server's origin. Every payload proof must name it as its audience,
37
+ * so a proof signed for another Personal Server cannot be relayed here.
38
+ */
39
+ serverOrigin: string | (() => string);
40
+ /**
41
+ * The owner every grant must have been issued by. Absent = fail closed:
42
+ * a delegated write cannot be bound to an owner we cannot name.
43
+ */
44
+ serverOwner?: `0x${string}`;
45
+ /**
46
+ * Live write sessions (minted by POST /v1/write/session). Absent = the host
47
+ * does not support delegated writes and every request falls through to the
48
+ * caller's owner gate.
49
+ */
50
+ sessionStore?: WriteSessionStore;
51
+ /** Replay guard for the per-write `X-Vana-Write-Signature` proofs. */
52
+ replayStore: WriteProofReplayStore;
53
+ /** Live builder/grant verification, re-run on every delegated write. */
54
+ policyPorts: DataWritePolicyPorts;
55
+ now?: () => Date;
56
+ }
57
+ export interface WriteSessionAuthorization {
58
+ /**
59
+ * Authorize a delegated write to `input.scope`, or `undefined` when the
60
+ * request carries no live write-session credential (the caller then applies
61
+ * its owner gate, exactly as before write sessions existed).
62
+ */
63
+ authorizeSessionWrite(input: PersonalServerWriteAuthInput): Promise<PersonalServerWriteAuthResult | undefined>;
64
+ /**
65
+ * Identity-only recognition of a write-session caller. Never releases data.
66
+ */
67
+ recognizeWriteSession(request: Request): Promise<PersonalServerWriteSessionResult | undefined>;
68
+ }
69
+ /** The bearer credential a write session is presented under. */
70
+ export declare function writeSessionBearerToken(request: Request): string | null;
71
+ /**
72
+ * Same shape and message as the auth layer's own missing-owner failure, so a
73
+ * host that never configured an owner reports one thing, not two.
74
+ */
75
+ export declare function writeServerNotConfigured(): ProtocolError;
76
+ export declare function createWriteSessionAuthorization(deps: WriteSessionAuthorizationDeps): WriteSessionAuthorization;
77
+ //# sourceMappingURL=authorize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorize.d.ts","sourceRoot":"","sources":["../../src/write/authorize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EACV,4BAA4B,EAC5B,6BAA6B,EAC7B,gCAAgC,EACjC,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAEL,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACvB,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,6BAA6B;IAC5C;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,CAAC,CAAC;IACtC;;;OAGG;IACH,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,iBAAiB,CAAC;IACjC,sEAAsE;IACtE,WAAW,EAAE,qBAAqB,CAAC;IACnC,wEAAwE;IACxE,WAAW,EAAE,oBAAoB,CAAC;IAClC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,qBAAqB,CACnB,KAAK,EAAE,4BAA4B,GAClC,OAAO,CAAC,6BAA6B,GAAG,SAAS,CAAC,CAAC;IACtD;;OAEG;IACH,qBAAqB,CACnB,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,gCAAgC,GAAG,SAAS,CAAC,CAAC;CAC1D;AAED,gEAAgE;AAChE,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAIvE;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,aAAa,CAMxD;AAED,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,6BAA6B,GAClC,yBAAyB,CA6D3B"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Delegated-write authorization, shared by every build.
3
+ *
4
+ * `authorizeWrite` / `authorizeWriteSession` are the two write-session halves
5
+ * of `PersonalServerApiAuthPort`. They were originally written inside the Node
6
+ * server's auth adapter (packages/server/src/api-auth.ts); the checks they run
7
+ * are pure protocol — a token hash, a live grant re-check, an EIP-191 payload
8
+ * proof and a replay reservation — with nothing Node-specific in them, so they
9
+ * live here and BOTH the Node server adapter and the browser (PS-Lite)
10
+ * adapters call the same code. There is exactly one implementation of the
11
+ * write policy; a browser build cannot drift into a weaker one.
12
+ *
13
+ * The two entry points differ in what they are allowed to decide:
14
+ *
15
+ * - `authorizeSessionWrite` authorizes a write to a NAMED scope. It
16
+ * re-runs `verifyDataWritePolicy` against the LIVE grant on every call,
17
+ * so revocation, expiry, grantee binding, owner binding and scope
18
+ * coverage stay authoritative per write rather than being frozen at
19
+ * handshake, and it verifies the builder's per-write payload proof.
20
+ * - `recognizeWriteSession` is identity only: the bearer must resolve to a
21
+ * live session and the request must carry that builder's valid proof, but
22
+ * NO grant policy runs (there is no scope to run one against). Callers use
23
+ * it only to choose between error shapes, never to release data.
24
+ *
25
+ * Both fail closed: an unknown bearer, an unknown session, a missing server
26
+ * owner, or any failing proof check returns/raises rather than falling back to
27
+ * a weaker credential. A request that is not a write-session request at all
28
+ * returns `undefined`, and the caller applies its own owner gate.
29
+ */
30
+ import { ProtocolError } from "../errors/catalog.js";
31
+ import { verifyDataWritePolicy, } from "../policy/data-write.js";
32
+ import { verifyWriterAttribution } from "./attribution.js";
33
+ import { hashWriteSessionToken, } from "./session.js";
34
+ /** The bearer credential a write session is presented under. */
35
+ export function writeSessionBearerToken(request) {
36
+ const header = request.headers.get("authorization");
37
+ if (!header?.startsWith("Bearer "))
38
+ return null;
39
+ return header.slice(7);
40
+ }
41
+ /**
42
+ * Same shape and message as the auth layer's own missing-owner failure, so a
43
+ * host that never configured an owner reports one thing, not two.
44
+ */
45
+ export function writeServerNotConfigured() {
46
+ return new ProtocolError(500, "SERVER_NOT_CONFIGURED", "Server owner address not configured. Set VANA_MASTER_KEY_SIGNATURE environment variable.");
47
+ }
48
+ export function createWriteSessionAuthorization(deps) {
49
+ async function liveSession(request) {
50
+ const token = writeSessionBearerToken(request);
51
+ if (!token || !deps.sessionStore)
52
+ return null;
53
+ return deps.sessionStore.getByTokenHash(await hashWriteSessionToken(token));
54
+ }
55
+ return {
56
+ async authorizeSessionWrite(input) {
57
+ const session = await liveSession(input.request);
58
+ if (!session)
59
+ return undefined;
60
+ if (!deps.serverOwner)
61
+ throw writeServerNotConfigured();
62
+ // The grant is re-checked live on EVERY write: a session token minted
63
+ // an hour ago against a grant that has since been revoked, narrowed or
64
+ // expired authorizes nothing.
65
+ const grant = await verifyDataWritePolicy({
66
+ signer: session.builderAddress,
67
+ grantId: session.grantId,
68
+ requestedScope: input.scope,
69
+ serverOwner: deps.serverOwner,
70
+ }, deps.policyPorts);
71
+ // releaseProof is a rollback hook for the handler, never part of the
72
+ // stored attribution record.
73
+ const { releaseProof, ...attribution } = await verifyWriterAttribution({
74
+ request: input.request,
75
+ builderAddress: session.builderAddress,
76
+ grantId: grant.id,
77
+ serverOrigin: deps.serverOrigin,
78
+ replayStore: deps.replayStore,
79
+ now: deps.now,
80
+ });
81
+ return {
82
+ builder: session.builderAddress,
83
+ grantId: grant.id,
84
+ grantScopes: grant.scopes ?? [],
85
+ attribution,
86
+ releaseProof,
87
+ };
88
+ },
89
+ async recognizeWriteSession(request) {
90
+ const session = await liveSession(request);
91
+ if (!session)
92
+ return undefined;
93
+ const { releaseProof } = await verifyWriterAttribution({
94
+ request,
95
+ builderAddress: session.builderAddress,
96
+ grantId: session.grantId,
97
+ serverOrigin: deps.serverOrigin,
98
+ replayStore: deps.replayStore,
99
+ now: deps.now,
100
+ });
101
+ return {
102
+ builder: session.builderAddress,
103
+ grantId: session.grantId,
104
+ releaseProof,
105
+ };
106
+ },
107
+ };
108
+ }
109
+ //# sourceMappingURL=authorize.js.map