@opendatalabs/personal-server-ts-core 1.33.7 → 1.34.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 (341) hide show
  1. package/dist/additions/budget.d.ts +28 -0
  2. package/dist/additions/budget.d.ts.map +1 -0
  3. package/dist/additions/budget.js +119 -0
  4. package/dist/additions/budget.js.map +1 -0
  5. package/dist/additions/durable.d.ts +64 -0
  6. package/dist/additions/durable.d.ts.map +1 -0
  7. package/dist/additions/durable.js +591 -0
  8. package/dist/additions/durable.js.map +1 -0
  9. package/dist/additions/first-added.d.ts +32 -48
  10. package/dist/additions/first-added.d.ts.map +1 -1
  11. package/dist/additions/first-added.js +68 -123
  12. package/dist/additions/first-added.js.map +1 -1
  13. package/dist/additions/index.d.ts +3 -0
  14. package/dist/additions/index.d.ts.map +1 -1
  15. package/dist/additions/index.js +3 -0
  16. package/dist/additions/index.js.map +1 -1
  17. package/dist/additions/ledger-store.js +1 -1
  18. package/dist/additions/record-rules.d.ts.map +1 -1
  19. package/dist/additions/record-rules.js +7 -0
  20. package/dist/additions/record-rules.js.map +1 -1
  21. package/dist/additions/summary.d.ts +88 -1
  22. package/dist/additions/summary.d.ts.map +1 -1
  23. package/dist/additions/summary.js +173 -8
  24. package/dist/additions/summary.js.map +1 -1
  25. package/dist/additions/version-inventory.d.ts +80 -0
  26. package/dist/additions/version-inventory.d.ts.map +1 -0
  27. package/dist/additions/version-inventory.js +232 -0
  28. package/dist/additions/version-inventory.js.map +1 -0
  29. package/dist/api/index.d.ts +70 -2
  30. package/dist/api/index.d.ts.map +1 -1
  31. package/dist/api/index.js +506 -79
  32. package/dist/api/index.js.map +1 -1
  33. package/dist/auth/index.d.ts +1 -1
  34. package/dist/auth/index.d.ts.map +1 -1
  35. package/dist/auth/index.js +1 -1
  36. package/dist/auth/index.js.map +1 -1
  37. package/dist/auth/request.d.ts +6 -0
  38. package/dist/auth/request.d.ts.map +1 -1
  39. package/dist/auth/request.js +66 -4
  40. package/dist/auth/request.js.map +1 -1
  41. package/dist/contracts/data.d.ts +54 -8
  42. package/dist/contracts/data.d.ts.map +1 -1
  43. package/dist/contracts/data.js +178 -35
  44. package/dist/contracts/data.js.map +1 -1
  45. package/dist/contracts/index.d.ts +1 -1
  46. package/dist/contracts/index.d.ts.map +1 -1
  47. package/dist/derivatives/registration.d.ts +0 -5
  48. package/dist/derivatives/registration.d.ts.map +1 -1
  49. package/dist/derivatives/registration.js +2 -1
  50. package/dist/derivatives/registration.js.map +1 -1
  51. package/dist/errors/pdpp-catalog.d.ts +36 -0
  52. package/dist/errors/pdpp-catalog.d.ts.map +1 -0
  53. package/dist/errors/pdpp-catalog.js +86 -0
  54. package/dist/errors/pdpp-catalog.js.map +1 -0
  55. package/dist/grants/index.d.ts +2 -0
  56. package/dist/grants/index.d.ts.map +1 -1
  57. package/dist/grants/index.js +4 -0
  58. package/dist/grants/index.js.map +1 -1
  59. package/dist/grants/pdpp-binding-store.d.ts +89 -0
  60. package/dist/grants/pdpp-binding-store.d.ts.map +1 -0
  61. package/dist/grants/pdpp-binding-store.js +112 -0
  62. package/dist/grants/pdpp-binding-store.js.map +1 -0
  63. package/dist/grants/pdpp-binding.d.ts +169 -0
  64. package/dist/grants/pdpp-binding.d.ts.map +1 -0
  65. package/dist/grants/pdpp-binding.js +236 -0
  66. package/dist/grants/pdpp-binding.js.map +1 -0
  67. package/dist/legacy-projection/bindings.d.ts +28 -1
  68. package/dist/legacy-projection/bindings.d.ts.map +1 -1
  69. package/dist/legacy-projection/bindings.js +622 -189
  70. package/dist/legacy-projection/bindings.js.map +1 -1
  71. package/dist/legacy-projection/claude-source-record.d.ts +22 -0
  72. package/dist/legacy-projection/claude-source-record.d.ts.map +1 -0
  73. package/dist/legacy-projection/claude-source-record.js +360 -0
  74. package/dist/legacy-projection/claude-source-record.js.map +1 -0
  75. package/dist/legacy-projection/declared-text.d.ts +41 -0
  76. package/dist/legacy-projection/declared-text.d.ts.map +1 -0
  77. package/dist/legacy-projection/declared-text.js +199 -0
  78. package/dist/legacy-projection/declared-text.js.map +1 -0
  79. package/dist/legacy-projection/github-browser-bindings.d.ts.map +1 -1
  80. package/dist/legacy-projection/github-browser-bindings.js +89 -5
  81. package/dist/legacy-projection/github-browser-bindings.js.map +1 -1
  82. package/dist/legacy-projection/github-legacy-fields.d.ts +6 -0
  83. package/dist/legacy-projection/github-legacy-fields.d.ts.map +1 -0
  84. package/dist/legacy-projection/github-legacy-fields.js +202 -0
  85. package/dist/legacy-projection/github-legacy-fields.js.map +1 -0
  86. package/dist/legacy-projection/index.d.ts +3 -1
  87. package/dist/legacy-projection/index.d.ts.map +1 -1
  88. package/dist/legacy-projection/index.js +49 -1
  89. package/dist/legacy-projection/index.js.map +1 -1
  90. package/dist/legacy-projection/oura-browser-bindings.d.ts.map +1 -1
  91. package/dist/legacy-projection/oura-browser-bindings.js +43 -41
  92. package/dist/legacy-projection/oura-browser-bindings.js.map +1 -1
  93. package/dist/legacy-projection/types.d.ts +38 -2
  94. package/dist/legacy-projection/types.d.ts.map +1 -1
  95. package/dist/mcp/connection-api.d.ts.map +1 -1
  96. package/dist/mcp/connection-api.js +4 -0
  97. package/dist/mcp/connection-api.js.map +1 -1
  98. package/dist/mcp/index.d.ts +1 -0
  99. package/dist/mcp/index.d.ts.map +1 -1
  100. package/dist/mcp/index.js +1 -0
  101. package/dist/mcp/index.js.map +1 -1
  102. package/dist/mcp/oauth-redirect.d.ts +14 -0
  103. package/dist/mcp/oauth-redirect.d.ts.map +1 -0
  104. package/dist/mcp/oauth-redirect.js +51 -0
  105. package/dist/mcp/oauth-redirect.js.map +1 -0
  106. package/dist/mcp/resources.d.ts.map +1 -1
  107. package/dist/mcp/resources.js +3 -0
  108. package/dist/mcp/resources.js.map +1 -1
  109. package/dist/mcp/tools.d.ts.map +1 -1
  110. package/dist/mcp/tools.js +11 -2
  111. package/dist/mcp/tools.js.map +1 -1
  112. package/dist/pdpp/approval.d.ts +271 -0
  113. package/dist/pdpp/approval.d.ts.map +1 -0
  114. package/dist/pdpp/approval.js +467 -0
  115. package/dist/pdpp/approval.js.map +1 -0
  116. package/dist/pdpp/client-identity.d.ts +88 -0
  117. package/dist/pdpp/client-identity.d.ts.map +1 -0
  118. package/dist/pdpp/client-identity.js +196 -0
  119. package/dist/pdpp/client-identity.js.map +1 -0
  120. package/dist/pdpp/client-metadata.d.ts +95 -0
  121. package/dist/pdpp/client-metadata.d.ts.map +1 -0
  122. package/dist/pdpp/client-metadata.js +96 -0
  123. package/dist/pdpp/client-metadata.js.map +1 -0
  124. package/dist/pdpp/commitments.d.ts +75 -0
  125. package/dist/pdpp/commitments.d.ts.map +1 -0
  126. package/dist/pdpp/commitments.js +113 -0
  127. package/dist/pdpp/commitments.js.map +1 -0
  128. package/dist/pdpp/declaration.d.ts +118 -0
  129. package/dist/pdpp/declaration.d.ts.map +1 -0
  130. package/dist/pdpp/declaration.js +836 -0
  131. package/dist/pdpp/declaration.js.map +1 -0
  132. package/dist/pdpp/index.d.ts +37 -0
  133. package/dist/pdpp/index.d.ts.map +1 -0
  134. package/dist/pdpp/index.js +23 -0
  135. package/dist/pdpp/index.js.map +1 -0
  136. package/dist/pdpp/issuance.d.ts +126 -0
  137. package/dist/pdpp/issuance.d.ts.map +1 -0
  138. package/dist/pdpp/issuance.js +180 -0
  139. package/dist/pdpp/issuance.js.map +1 -0
  140. package/dist/pdpp/pkce.d.ts +53 -0
  141. package/dist/pdpp/pkce.d.ts.map +1 -0
  142. package/dist/pdpp/pkce.js +109 -0
  143. package/dist/pdpp/pkce.js.map +1 -0
  144. package/dist/pdpp/redirect.d.ts +60 -0
  145. package/dist/pdpp/redirect.d.ts.map +1 -0
  146. package/dist/pdpp/redirect.js +125 -0
  147. package/dist/pdpp/redirect.js.map +1 -0
  148. package/dist/pdpp/resolve.d.ts +109 -0
  149. package/dist/pdpp/resolve.d.ts.map +1 -0
  150. package/dist/pdpp/resolve.js +393 -0
  151. package/dist/pdpp/resolve.js.map +1 -0
  152. package/dist/pdpp/review.d.ts +280 -0
  153. package/dist/pdpp/review.d.ts.map +1 -0
  154. package/dist/pdpp/review.js +205 -0
  155. package/dist/pdpp/review.js.map +1 -0
  156. package/dist/pdpp/selection.d.ts +50 -0
  157. package/dist/pdpp/selection.d.ts.map +1 -0
  158. package/dist/pdpp/selection.js +442 -0
  159. package/dist/pdpp/selection.js.map +1 -0
  160. package/dist/pdpp/store.d.ts +228 -0
  161. package/dist/pdpp/store.d.ts.map +1 -0
  162. package/dist/pdpp/store.js +542 -0
  163. package/dist/pdpp/store.js.map +1 -0
  164. package/dist/pdpp/tokens.d.ts +181 -0
  165. package/dist/pdpp/tokens.d.ts.map +1 -0
  166. package/dist/pdpp/tokens.js +419 -0
  167. package/dist/pdpp/tokens.js.map +1 -0
  168. package/dist/pdpp/types.d.ts +441 -0
  169. package/dist/pdpp/types.d.ts.map +1 -0
  170. package/dist/pdpp/types.js +61 -0
  171. package/dist/pdpp/types.js.map +1 -0
  172. package/dist/pdpp-version.d.ts +28 -0
  173. package/dist/pdpp-version.d.ts.map +1 -0
  174. package/dist/pdpp-version.js +28 -0
  175. package/dist/pdpp-version.js.map +1 -0
  176. package/dist/policy/data-read.d.ts +24 -0
  177. package/dist/policy/data-read.d.ts.map +1 -1
  178. package/dist/policy/data-read.js +60 -3
  179. package/dist/policy/data-read.js.map +1 -1
  180. package/dist/policy/data-write.d.ts.map +1 -1
  181. package/dist/policy/data-write.js +3 -0
  182. package/dist/policy/data-write.js.map +1 -1
  183. package/dist/policy/index.d.ts +1 -0
  184. package/dist/policy/index.d.ts.map +1 -1
  185. package/dist/policy/index.js +1 -0
  186. package/dist/policy/index.js.map +1 -1
  187. package/dist/policy/reserved-scopes.d.ts +3 -0
  188. package/dist/policy/reserved-scopes.d.ts.map +1 -0
  189. package/dist/policy/reserved-scopes.js +5 -0
  190. package/dist/policy/reserved-scopes.js.map +1 -0
  191. package/dist/ports/index.d.ts +63 -0
  192. package/dist/ports/index.d.ts.map +1 -1
  193. package/dist/ports/index.js.map +1 -1
  194. package/dist/ports/pdpp-auth.d.ts +129 -0
  195. package/dist/ports/pdpp-auth.d.ts.map +1 -0
  196. package/dist/ports/pdpp-auth.js +60 -0
  197. package/dist/ports/pdpp-auth.js.map +1 -0
  198. package/dist/ports/pdpp-auth.test-utils.d.ts +9 -0
  199. package/dist/ports/pdpp-auth.test-utils.d.ts.map +1 -0
  200. package/dist/ports/pdpp-auth.test-utils.js +18 -0
  201. package/dist/ports/pdpp-auth.test-utils.js.map +1 -0
  202. package/dist/schemas/server-config.d.ts +44 -0
  203. package/dist/schemas/server-config.d.ts.map +1 -1
  204. package/dist/schemas/server-config.js +91 -0
  205. package/dist/schemas/server-config.js.map +1 -1
  206. package/dist/signing/request-signer.d.ts +2 -0
  207. package/dist/signing/request-signer.d.ts.map +1 -1
  208. package/dist/signing/request-signer.js +1 -0
  209. package/dist/signing/request-signer.js.map +1 -1
  210. package/dist/storage/adapters/interface.d.ts +3 -0
  211. package/dist/storage/adapters/interface.d.ts.map +1 -1
  212. package/dist/storage/adapters/vana-audience.d.ts +12 -0
  213. package/dist/storage/adapters/vana-audience.d.ts.map +1 -0
  214. package/dist/storage/adapters/vana-audience.js +72 -0
  215. package/dist/storage/adapters/vana-audience.js.map +1 -0
  216. package/dist/storage/adapters/vana.d.ts +2 -0
  217. package/dist/storage/adapters/vana.d.ts.map +1 -1
  218. package/dist/storage/adapters/vana.js +53 -20
  219. package/dist/storage/adapters/vana.js.map +1 -1
  220. package/dist/storage/canonical-legacy-projection.d.ts +262 -0
  221. package/dist/storage/canonical-legacy-projection.d.ts.map +1 -0
  222. package/dist/storage/canonical-legacy-projection.js +761 -0
  223. package/dist/storage/canonical-legacy-projection.js.map +1 -0
  224. package/dist/storage/index/manager.d.ts +29 -2
  225. package/dist/storage/index/manager.d.ts.map +1 -1
  226. package/dist/storage/index/schema.d.ts +1 -1
  227. package/dist/storage/index/schema.js +1 -1
  228. package/dist/storage/index/types.d.ts +7 -1
  229. package/dist/storage/index/types.d.ts.map +1 -1
  230. package/dist/storage/legacy-projection.d.ts +4 -3
  231. package/dist/storage/legacy-projection.d.ts.map +1 -1
  232. package/dist/storage/legacy-projection.js +145 -42
  233. package/dist/storage/legacy-projection.js.map +1 -1
  234. package/dist/storage/legacy-scope-coverage-exceptions.d.ts +8 -0
  235. package/dist/storage/legacy-scope-coverage-exceptions.d.ts.map +1 -0
  236. package/dist/storage/legacy-scope-coverage-exceptions.js +10 -0
  237. package/dist/storage/legacy-scope-coverage-exceptions.js.map +1 -0
  238. package/dist/storage/legacy-scope-coverage.d.ts +53 -0
  239. package/dist/storage/legacy-scope-coverage.d.ts.map +1 -0
  240. package/dist/storage/legacy-scope-coverage.js +403 -0
  241. package/dist/storage/legacy-scope-coverage.js.map +1 -0
  242. package/dist/storage/legacy-scope-entity-keys.d.ts +4 -0
  243. package/dist/storage/legacy-scope-entity-keys.d.ts.map +1 -0
  244. package/dist/storage/legacy-scope-entity-keys.js +92 -0
  245. package/dist/storage/legacy-scope-entity-keys.js.map +1 -0
  246. package/dist/storage/legacy-scope-view.d.ts +154 -0
  247. package/dist/storage/legacy-scope-view.d.ts.map +1 -0
  248. package/dist/storage/legacy-scope-view.js +735 -0
  249. package/dist/storage/legacy-scope-view.js.map +1 -0
  250. package/dist/storage/pdpp-records/completion.d.ts +91 -0
  251. package/dist/storage/pdpp-records/completion.d.ts.map +1 -0
  252. package/dist/storage/pdpp-records/completion.js +170 -0
  253. package/dist/storage/pdpp-records/completion.js.map +1 -0
  254. package/dist/storage/pdpp-records/cursor.d.ts +41 -0
  255. package/dist/storage/pdpp-records/cursor.d.ts.map +1 -0
  256. package/dist/storage/pdpp-records/cursor.js +49 -0
  257. package/dist/storage/pdpp-records/cursor.js.map +1 -0
  258. package/dist/storage/pdpp-records/declaration-witness.d.ts +58 -0
  259. package/dist/storage/pdpp-records/declaration-witness.d.ts.map +1 -0
  260. package/dist/storage/pdpp-records/declaration-witness.js +230 -0
  261. package/dist/storage/pdpp-records/declaration-witness.js.map +1 -0
  262. package/dist/storage/pdpp-records/enforcement.d.ts +52 -0
  263. package/dist/storage/pdpp-records/enforcement.d.ts.map +1 -0
  264. package/dist/storage/pdpp-records/enforcement.js +116 -0
  265. package/dist/storage/pdpp-records/enforcement.js.map +1 -0
  266. package/dist/storage/pdpp-records/index.d.ts +5 -0
  267. package/dist/storage/pdpp-records/index.d.ts.map +1 -0
  268. package/dist/storage/pdpp-records/index.js +5 -0
  269. package/dist/storage/pdpp-records/index.js.map +1 -0
  270. package/dist/storage/pdpp-records/ingest-plan.d.ts +39 -0
  271. package/dist/storage/pdpp-records/ingest-plan.d.ts.map +1 -0
  272. package/dist/storage/pdpp-records/ingest-plan.js +103 -0
  273. package/dist/storage/pdpp-records/ingest-plan.js.map +1 -0
  274. package/dist/storage/pdpp-records/interface.d.ts +104 -0
  275. package/dist/storage/pdpp-records/interface.d.ts.map +1 -0
  276. package/dist/storage/pdpp-records/interface.js +2 -0
  277. package/dist/storage/pdpp-records/interface.js.map +1 -0
  278. package/dist/storage/pdpp-records/memory-store.d.ts +9 -0
  279. package/dist/storage/pdpp-records/memory-store.d.ts.map +1 -0
  280. package/dist/storage/pdpp-records/memory-store.js +466 -0
  281. package/dist/storage/pdpp-records/memory-store.js.map +1 -0
  282. package/dist/storage/pdpp-records/portable.d.ts +9 -0
  283. package/dist/storage/pdpp-records/portable.d.ts.map +1 -0
  284. package/dist/storage/pdpp-records/portable.js +8 -0
  285. package/dist/storage/pdpp-records/portable.js.map +1 -0
  286. package/dist/storage/pdpp-records/read-port.d.ts +44 -0
  287. package/dist/storage/pdpp-records/read-port.d.ts.map +1 -0
  288. package/dist/storage/pdpp-records/read-port.js +22 -0
  289. package/dist/storage/pdpp-records/read-port.js.map +1 -0
  290. package/dist/storage/pdpp-records/record-key.d.ts +52 -0
  291. package/dist/storage/pdpp-records/record-key.d.ts.map +1 -0
  292. package/dist/storage/pdpp-records/record-key.js +97 -0
  293. package/dist/storage/pdpp-records/record-key.js.map +1 -0
  294. package/dist/storage/pdpp-records/schema.d.ts +41 -0
  295. package/dist/storage/pdpp-records/schema.d.ts.map +1 -0
  296. package/dist/storage/pdpp-records/schema.js +153 -0
  297. package/dist/storage/pdpp-records/schema.js.map +1 -0
  298. package/dist/storage/pdpp-records/stream-declaration.d.ts +88 -0
  299. package/dist/storage/pdpp-records/stream-declaration.d.ts.map +1 -0
  300. package/dist/storage/pdpp-records/stream-declaration.js +57 -0
  301. package/dist/storage/pdpp-records/stream-declaration.js.map +1 -0
  302. package/dist/storage/pdpp-records/types.d.ts +138 -0
  303. package/dist/storage/pdpp-records/types.d.ts.map +1 -0
  304. package/dist/storage/pdpp-records/types.js +38 -0
  305. package/dist/storage/pdpp-records/types.js.map +1 -0
  306. package/dist/sync/data-point-feed.d.ts +3 -0
  307. package/dist/sync/data-point-feed.d.ts.map +1 -1
  308. package/dist/sync/data-point-feed.js +17 -1
  309. package/dist/sync/data-point-feed.js.map +1 -1
  310. package/dist/sync/delete-data-port.d.ts +2 -0
  311. package/dist/sync/delete-data-port.d.ts.map +1 -1
  312. package/dist/sync/delete-data-port.js +1 -1
  313. package/dist/sync/delete-data-port.js.map +1 -1
  314. package/dist/sync/engine/sync-manager.d.ts.map +1 -1
  315. package/dist/sync/engine/sync-manager.js +5 -2
  316. package/dist/sync/engine/sync-manager.js.map +1 -1
  317. package/dist/sync/index.d.ts +3 -1
  318. package/dist/sync/index.d.ts.map +1 -1
  319. package/dist/sync/index.js +4 -0
  320. package/dist/sync/index.js.map +1 -1
  321. package/dist/sync/pdpp-import.d.ts +192 -0
  322. package/dist/sync/pdpp-import.d.ts.map +1 -0
  323. package/dist/sync/pdpp-import.js +441 -0
  324. package/dist/sync/pdpp-import.js.map +1 -0
  325. package/dist/sync/scope-deletions.d.ts +10 -0
  326. package/dist/sync/scope-deletions.d.ts.map +1 -1
  327. package/dist/sync/scope-deletions.js +40 -7
  328. package/dist/sync/scope-deletions.js.map +1 -1
  329. package/dist/sync/workers/download.d.ts +14 -0
  330. package/dist/sync/workers/download.d.ts.map +1 -1
  331. package/dist/sync/workers/download.js +149 -13
  332. package/dist/sync/workers/download.js.map +1 -1
  333. package/dist/sync/workers/upload.d.ts +2 -0
  334. package/dist/sync/workers/upload.d.ts.map +1 -1
  335. package/dist/sync/workers/upload.js +7 -0
  336. package/dist/sync/workers/upload.js.map +1 -1
  337. package/dist/test-utils/memory-storage.d.ts +1 -1
  338. package/dist/test-utils/memory-storage.d.ts.map +1 -1
  339. package/dist/test-utils/memory-storage.js +11 -5
  340. package/dist/test-utils/memory-storage.js.map +1 -1
  341. package/package.json +54 -4
@@ -0,0 +1,280 @@
1
+ /**
2
+ * PDPP Core §6/§7 consent review model and immutable review digest.
3
+ *
4
+ * Two jobs here, and they are related:
5
+ *
6
+ * 1. Build the review model Account/Web renders. §6 forbids flattening the
7
+ * consent surface: requester identity, declaration-authored data
8
+ * descriptions, structured policy declarations, and attributed client
9
+ * claims are four distinct categories, and a client claim must never be
10
+ * rendered in the same register as a protocol-enforced term. The model
11
+ * below keeps them in four separate fields so a renderer cannot
12
+ * accidentally merge them.
13
+ *
14
+ * 2. Compute a digest over the decision fields. §7 requires the approval
15
+ * mutation to bind to an immutable review revision or digest, and to reject
16
+ * approval if eligibility or the reviewed revision changed in the meantime.
17
+ * That is what stops a resolved-then-widened race: the owner approves a
18
+ * digest, and issuance re-derives the digest from what it is about to issue.
19
+ * If they differ, the approval is stale and dies.
20
+ *
21
+ * The digest covers exactly the decision fields §7 enumerates, plus the
22
+ * normalized client claims when they were rendered. It deliberately does NOT
23
+ * cover `issued_at` or `grant_id`, which do not exist yet at review time.
24
+ */
25
+ import { type ResolvedCommitments } from "./commitments.js";
26
+ import { type ClientClaims, type ClientDisplay, type DeclarationSnapshot, type OwnerConditions, type RecipientTerms, type RequestedStream, type Retention, type SelectionRequest, type StreamGrant } from "./types.js";
27
+ /** How the AS resolved requester identity, and how much it actually knows. */
28
+ export interface RequesterIdentity {
29
+ client_id: string;
30
+ /** Resolved per §6 precedence. Falls back to `client_id` when nothing else exists. */
31
+ display_name: string;
32
+ display?: ClientDisplay;
33
+ /**
34
+ * §6 obligation 5: verified domain control is named, never presented as an
35
+ * unqualified "verified app". Absent means no positive trust signal, and the
36
+ * surface must show an unverified indicator.
37
+ */
38
+ verified_domain?: string;
39
+ /** True only for a local registration or trust-registry admission decision. */
40
+ app_approved: boolean;
41
+ }
42
+ /** One stream row as the owner reviews it, with declaration-authored copy. */
43
+ export interface ReviewStream {
44
+ name: string;
45
+ /** Declaration-authored description. Its own category — not a client claim. */
46
+ description?: string;
47
+ /**
48
+ * §5 stream `display.label` — the short consent-card name for this stream,
49
+ * e.g. "Who you follow" rather than `following_accounts`.
50
+ *
51
+ * Read from the retained declaration snapshot, never from the request. §5
52
+ * forbids the requesting client from authoring or supplementing it, and the
53
+ * AS is the only role that can hold that line, because the renderer cannot
54
+ * tell from one payload which member the client wrote.
55
+ */
56
+ display_label?: string;
57
+ /**
58
+ * §5 stream `display.detail` — what the data includes and, where relevant,
59
+ * what it EXCLUDES. Same provenance rule as `display_label`.
60
+ */
61
+ display_detail?: string;
62
+ instance_ids: string[];
63
+ fields: string[];
64
+ time_constraint?: {
65
+ field: string;
66
+ since?: string;
67
+ until?: string;
68
+ };
69
+ resources?: string[];
70
+ /**
71
+ * v0.2 consent-flow control. `optional` means the owner may remove this
72
+ * stream; the surface must not present it as compulsory.
73
+ */
74
+ necessity?: "required" | "optional";
75
+ /**
76
+ * v0.2: the fields and window the client asked for, before the owner's
77
+ * narrowing. The surface needs both ends to render a narrowing control at
78
+ * all — `fields` above is the current proposal, this is its ceiling.
79
+ */
80
+ requested_fields?: string[];
81
+ requested_time_range?: {
82
+ since?: string;
83
+ until?: string;
84
+ };
85
+ /**
86
+ * v0.2: the floor. A surface that lets the owner narrow below this is
87
+ * offering a choice that will refuse issuance, so it needs to know where
88
+ * the floor is in order to stop short of it — or to say why it cannot.
89
+ */
90
+ minimum?: {
91
+ fields?: string[];
92
+ time_range?: {
93
+ since: string;
94
+ until: string;
95
+ };
96
+ };
97
+ }
98
+ /**
99
+ * An already-active grant this same client holds for this owner, so the
100
+ * consent surface can say what is already shared. Deliberately excludes
101
+ * tokens, consent evidence, and the review digest — informational only, never
102
+ * an authority the RS or AS re-derives from.
103
+ */
104
+ export interface ExistingGrant {
105
+ grant_id: string;
106
+ issued_at: string;
107
+ expires_at?: string;
108
+ access_mode: "single_use" | "continuous";
109
+ purpose_code: string;
110
+ streams: Array<{
111
+ name: string;
112
+ fields: string[];
113
+ }>;
114
+ }
115
+ /**
116
+ * The four semantic categories §6 requires a conformant consent surface to
117
+ * keep distinct. A renderer that wants to flatten them has to do so
118
+ * deliberately; it cannot do so by accident.
119
+ */
120
+ export interface ConsentReviewModel {
121
+ /** Category 1: who is asking. */
122
+ requester: RequesterIdentity;
123
+ /** Category 2: declaration-authored data descriptions + protocol-enforced terms. */
124
+ data: {
125
+ /**
126
+ * `display_name` is §5's top-level `display.name` — the human name for the
127
+ * source. It accompanies `id` rather than replacing it: `id` is the
128
+ * protocol-enforced fact and the one 6.1-5 requires the owner to be able
129
+ * to see, so a surface that showed only the friendly name would hide which
130
+ * source was actually resolved.
131
+ */
132
+ source: {
133
+ kind: string;
134
+ id: string;
135
+ display_name?: string;
136
+ };
137
+ source_declaration_version: string;
138
+ access_mode: "single_use" | "continuous";
139
+ streams: ReviewStream[];
140
+ /**
141
+ * v0.2: optional streams the owner's current choices have removed, so the
142
+ * surface can keep showing them as declined rather than making them
143
+ * vanish. v0.2 forbids presenting optional selections as compulsory; a
144
+ * declined stream that disappears from the review is the mirror failure —
145
+ * the owner cannot see what they turned off, or turn it back on.
146
+ */
147
+ omitted_streams?: string[];
148
+ expires_at?: string;
149
+ };
150
+ /** Category 3: structured policy declarations. */
151
+ policy: {
152
+ purpose_code: string;
153
+ purpose_description?: string;
154
+ /**
155
+ * True when the code is absent from the PDPP registry. §9 AS item 6:
156
+ * this drives *rendering* (show the description or raw URI), never
157
+ * rejection.
158
+ */
159
+ purpose_unregistered: boolean;
160
+ retention?: Retention;
161
+ /**
162
+ * §6: the sole purpose code with a protocol-level consent requirement.
163
+ * The surface must collect explicit affirmative consent when this is set.
164
+ */
165
+ requires_explicit_ai_training_consent: boolean;
166
+ };
167
+ /** Category 4: attributed, unverifiable, non-enforceable client claims. */
168
+ client_claims?: {
169
+ /** Always rendered as "<name> says:" — never as a protocol term. */
170
+ attributed_to: string;
171
+ commitments: string[];
172
+ };
173
+ /** Digest over the decision fields. The approval must carry this back. */
174
+ review_digest: string;
175
+ /**
176
+ * This client's other active grants for this owner, newest first. Absent
177
+ * when there are none — kept out of the digest since it is informational,
178
+ * not a decision field, and can change between requests without staling
179
+ * the review.
180
+ */
181
+ existing_grants?: ExistingGrant[];
182
+ }
183
+ export declare function isRegisteredPurposeCode(code: string): boolean;
184
+ /**
185
+ * Normalize client claims before binding. §6 requires the *normalized exact*
186
+ * claims to be bound into the approval artifact, so the digest has to be
187
+ * computed over a canonical form — otherwise re-rendering with different
188
+ * whitespace would spuriously invalidate an approval.
189
+ */
190
+ export declare function normalizeClientClaims(claims: ClientClaims | undefined): string[] | undefined;
191
+ /**
192
+ * The exact set of fields the digest covers. Kept as its own type so that
193
+ * adding a decision field to the grant without adding it here is a visible
194
+ * omission rather than a silent hole in the binding.
195
+ */
196
+ interface ReviewDecisionFields {
197
+ subject_id: string;
198
+ client_id: string;
199
+ source_id: string;
200
+ source_kind: string;
201
+ source_declaration_version: string;
202
+ /** The digest of the retained snapshot, so a re-fetched declaration cannot pass. */
203
+ declaration_digest: string;
204
+ purpose_code: string;
205
+ purpose_description?: string;
206
+ access_mode: string;
207
+ streams: StreamGrant[];
208
+ /**
209
+ * v0.2: optional streams the owner's choices removed.
210
+ *
211
+ * This has to be a decision field, not just presentation. Two owners
212
+ * narrowing the same request to the same retained streams by different
213
+ * routes — one declining an optional stream, one narrowing it below its
214
+ * minimum — reach the same `streams` but reviewed different screens. More
215
+ * importantly, without it an approval could carry a narrowing the owner
216
+ * never saw whenever that narrowing only *removed* a stream, since removal
217
+ * leaves the surviving streams byte-identical.
218
+ */
219
+ omitted_streams?: string[];
220
+ retention?: Retention;
221
+ expires_at?: string;
222
+ /** Bound with attribution when rendered; stays outside the grant regardless. */
223
+ client_claims?: {
224
+ attributed_to: string;
225
+ commitments: string[];
226
+ };
227
+ }
228
+ export declare function computeReviewDigest(fields: ReviewDecisionFields): string;
229
+ export interface BuildReviewInput {
230
+ subjectId: string;
231
+ request: SelectionRequest;
232
+ snapshot: DeclarationSnapshot;
233
+ /** The output of `resolveSelection` — fully concrete. */
234
+ resolvedStreams: StreamGrant[];
235
+ /** v0.2: `resolveSelection`'s `omittedStreams`, bound into the digest. */
236
+ omittedStreams?: string[];
237
+ /**
238
+ * v0.2: `resolveSelection`'s `requestedStreams`, the ceiling each retained
239
+ * stream was narrowed from. Rendering only — the resolved streams stay
240
+ * authoritative, and this stays out of the digest since it is a restatement
241
+ * of the request the session already pins, not a decision the owner makes.
242
+ */
243
+ requestedStreams?: RequestedStream[];
244
+ /**
245
+ * v0.2: conditions the owner attached beyond narrowing the data, and the
246
+ * standing terms that may cover them.
247
+ *
248
+ * Resolution happens here rather than in the caller so the review and the
249
+ * digest cannot disagree about which commitments were shown. A condition
250
+ * outside the recipient's authority makes the whole review unavailable —
251
+ * there is nothing valid to show the owner — so `buildConsentReview` throws
252
+ * the same `CommitmentsFailure` the issuance path reports. Callers that can
253
+ * present a failure to the owner call `resolveCommitments` first.
254
+ */
255
+ ownerConditions?: OwnerConditions;
256
+ standingTerms?: RecipientTerms;
257
+ /**
258
+ * Pre-resolved commitments, when the caller already ran
259
+ * `resolveCommitments` (issuance does, so it can report a refusal rather
260
+ * than throw). Takes precedence over the two members above.
261
+ */
262
+ commitments?: ResolvedCommitments;
263
+ requester: RequesterIdentity;
264
+ /** AS-policy grant expiry, when the deployment sets one. */
265
+ expiresAt?: string;
266
+ /** Declaration-authored stream descriptions, keyed by stream name. */
267
+ streamDescriptions?: Record<string, string>;
268
+ /** This client's other active grants for this owner, newest first. */
269
+ existingGrants?: ExistingGrant[];
270
+ }
271
+ /**
272
+ * Build the review model and its binding digest.
273
+ *
274
+ * The digest is computed from the same resolved streams that will be issued.
275
+ * `issueGrant` recomputes it and refuses to issue if it moved — see
276
+ * `issuance.ts`.
277
+ */
278
+ export declare function buildConsentReview(input: BuildReviewInput): ConsentReviewModel;
279
+ export {};
280
+ //# sourceMappingURL=review.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.ts","sourceRoot":"","sources":["../../src/pdpp/review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ /**
2
+ * PDPP Core §6/§7 consent review model and immutable review digest.
3
+ *
4
+ * Two jobs here, and they are related:
5
+ *
6
+ * 1. Build the review model Account/Web renders. §6 forbids flattening the
7
+ * consent surface: requester identity, declaration-authored data
8
+ * descriptions, structured policy declarations, and attributed client
9
+ * claims are four distinct categories, and a client claim must never be
10
+ * rendered in the same register as a protocol-enforced term. The model
11
+ * below keeps them in four separate fields so a renderer cannot
12
+ * accidentally merge them.
13
+ *
14
+ * 2. Compute a digest over the decision fields. §7 requires the approval
15
+ * mutation to bind to an immutable review revision or digest, and to reject
16
+ * approval if eligibility or the reviewed revision changed in the meantime.
17
+ * That is what stops a resolved-then-widened race: the owner approves a
18
+ * digest, and issuance re-derives the digest from what it is about to issue.
19
+ * If they differ, the approval is stale and dies.
20
+ *
21
+ * The digest covers exactly the decision fields §7 enumerates, plus the
22
+ * normalized client claims when they were rendered. It deliberately does NOT
23
+ * cover `issued_at` or `grant_id`, which do not exist yet at review time.
24
+ */
25
+ import { createHash } from "node:crypto";
26
+ import { resolveCommitments } from "./commitments.js";
27
+ import { AI_TRAINING_PURPOSE, } from "./types.js";
28
+ /**
29
+ * Purpose codes in the Appendix A initial registry. Membership drives display
30
+ * only. An unrecognized code is displayed from its description or raw URI and
31
+ * is never a rejection reason on its own (§9 AS item 6).
32
+ */
33
+ const REGISTERED_PURPOSE_CODES = new Set([
34
+ "https://pdpp.dev/purpose/personalization",
35
+ "https://pdpp.dev/purpose/analytics",
36
+ "https://pdpp.dev/purpose/research",
37
+ "https://pdpp.dev/purpose/portability",
38
+ "https://pdpp.dev/purpose/ai_training",
39
+ ]);
40
+ export function isRegisteredPurposeCode(code) {
41
+ return REGISTERED_PURPOSE_CODES.has(code);
42
+ }
43
+ /**
44
+ * Normalize client claims before binding. §6 requires the *normalized exact*
45
+ * claims to be bound into the approval artifact, so the digest has to be
46
+ * computed over a canonical form — otherwise re-rendering with different
47
+ * whitespace would spuriously invalidate an approval.
48
+ */
49
+ export function normalizeClientClaims(claims) {
50
+ const commitments = claims?.commitments;
51
+ if (!commitments || commitments.length === 0)
52
+ return undefined;
53
+ const normalized = commitments
54
+ .map((c) => c.trim().replace(/\s+/g, " "))
55
+ .filter((c) => c.length > 0);
56
+ return normalized.length > 0 ? normalized : undefined;
57
+ }
58
+ /**
59
+ * Deterministic serialization. `JSON.stringify` preserves insertion order, so
60
+ * we sort keys explicitly — two structurally identical decisions must produce
61
+ * one digest regardless of how the objects were built.
62
+ */
63
+ function canonicalize(value) {
64
+ if (value === null || typeof value !== "object") {
65
+ return JSON.stringify(value) ?? "null";
66
+ }
67
+ if (Array.isArray(value)) {
68
+ // Array order is meaningful (a field list's order is part of the decision
69
+ // the owner saw), so we do not sort array members.
70
+ return `[${value.map(canonicalize).join(",")}]`;
71
+ }
72
+ const entries = Object.entries(value)
73
+ .filter(([, v]) => v !== undefined)
74
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0));
75
+ return `{${entries
76
+ .map(([k, v]) => `${JSON.stringify(k)}:${canonicalize(v)}`)
77
+ .join(",")}}`;
78
+ }
79
+ export function computeReviewDigest(fields) {
80
+ return createHash("sha256")
81
+ .update(canonicalize(fields), "utf8")
82
+ .digest("hex");
83
+ }
84
+ /**
85
+ * Build the review model and its binding digest.
86
+ *
87
+ * The digest is computed from the same resolved streams that will be issued.
88
+ * `issueGrant` recomputes it and refuses to issue if it moved — see
89
+ * `issuance.ts`.
90
+ */
91
+ export function buildConsentReview(input) {
92
+ const { request, snapshot, resolvedStreams, requester } = input;
93
+ const normalizedClaims = normalizeClientClaims(request.client_claims);
94
+ const boundClaims = normalizedClaims
95
+ ? { attributed_to: requester.display_name, commitments: normalizedClaims }
96
+ : undefined;
97
+ // The commitments the owner will see, resolved from the request or the
98
+ // recipient's standing terms. These are decision fields: a commitment the
99
+ // owner never reviewed must not be issuable, so they go into the digest.
100
+ const commitments = input.commitments ?? resolveOrThrowCommitments(input);
101
+ const review_digest = computeReviewDigest({
102
+ subject_id: input.subjectId,
103
+ client_id: requester.client_id,
104
+ source_id: snapshot.source_id,
105
+ source_kind: snapshot.source_kind,
106
+ source_declaration_version: snapshot.version,
107
+ declaration_digest: snapshot.digest,
108
+ purpose_code: commitments.purpose_code,
109
+ purpose_description: commitments.purpose_description,
110
+ access_mode: request.access_mode,
111
+ streams: resolvedStreams,
112
+ ...(input.omittedStreams &&
113
+ input.omittedStreams.length > 0 && {
114
+ omitted_streams: input.omittedStreams,
115
+ }),
116
+ retention: commitments.retention,
117
+ expires_at: input.expiresAt,
118
+ client_claims: boundClaims,
119
+ });
120
+ return {
121
+ requester,
122
+ data: {
123
+ source: {
124
+ kind: snapshot.source_kind,
125
+ id: snapshot.source_id,
126
+ ...(snapshot.display?.name && {
127
+ display_name: snapshot.display.name,
128
+ }),
129
+ },
130
+ source_declaration_version: snapshot.version,
131
+ access_mode: request.access_mode,
132
+ streams: resolvedStreams.map((s) => {
133
+ const asked = input.requestedStreams?.find((r) => r.name === s.name);
134
+ // §5 consent copy, read from the RETAINED SNAPSHOT. `request` is
135
+ // deliberately not consulted: that is the whole provenance guarantee.
136
+ const declared = snapshot.streams.find((d) => d.name === s.name);
137
+ return {
138
+ name: s.name,
139
+ // The deployment-supplied map still wins where a caller set it, so
140
+ // this adds a source of copy without removing the existing one.
141
+ ...((input.streamDescriptions?.[s.name] ?? declared?.description) && {
142
+ description: input.streamDescriptions?.[s.name] ?? declared?.description,
143
+ }),
144
+ ...(declared?.display?.label && {
145
+ display_label: declared.display.label,
146
+ }),
147
+ ...(declared?.display?.detail && {
148
+ display_detail: declared.display.detail,
149
+ }),
150
+ instance_ids: s.instance_ids,
151
+ fields: s.fields,
152
+ ...(s.time_constraint && { time_constraint: s.time_constraint }),
153
+ ...(s.resources && { resources: s.resources }),
154
+ ...(asked && {
155
+ necessity: asked.necessity,
156
+ requested_fields: asked.fields,
157
+ ...(asked.time_range && { requested_time_range: asked.time_range }),
158
+ ...(asked.minimum && { minimum: asked.minimum }),
159
+ }),
160
+ };
161
+ }),
162
+ ...(input.omittedStreams &&
163
+ input.omittedStreams.length > 0 && {
164
+ omitted_streams: input.omittedStreams,
165
+ }),
166
+ ...(input.expiresAt && { expires_at: input.expiresAt }),
167
+ },
168
+ policy: {
169
+ purpose_code: commitments.purpose_code,
170
+ ...(commitments.purpose_description && {
171
+ purpose_description: commitments.purpose_description,
172
+ }),
173
+ purpose_unregistered: !isRegisteredPurposeCode(commitments.purpose_code),
174
+ ...(commitments.retention && { retention: commitments.retention }),
175
+ requires_explicit_ai_training_consent: commitments.purpose_code === AI_TRAINING_PURPOSE,
176
+ },
177
+ ...(boundClaims && { client_claims: boundClaims }),
178
+ review_digest,
179
+ ...(input.existingGrants &&
180
+ input.existingGrants.length > 0 && {
181
+ existing_grants: input.existingGrants,
182
+ }),
183
+ };
184
+ }
185
+ /**
186
+ * Resolve commitments for a caller that cannot present a refusal.
187
+ *
188
+ * A condition outside the recipient's authority means there is no valid review
189
+ * to build — showing the owner the *unrefused* terms would be showing them a
190
+ * decision they cannot make. Throwing rather than silently falling back is
191
+ * what stops that: the issuance path resolves first and reports a refusal, and
192
+ * anything else fails loudly instead of rendering a lie.
193
+ */
194
+ function resolveOrThrowCommitments(input) {
195
+ const resolved = resolveCommitments({
196
+ request: input.request,
197
+ ownerConditions: input.ownerConditions,
198
+ standingTerms: input.standingTerms,
199
+ declarationVersion: input.snapshot.version,
200
+ });
201
+ if (!resolved.ok)
202
+ throw new Error(resolved.failure.message);
203
+ return resolved.commitments;
204
+ }
205
+ //# sourceMappingURL=review.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.js","sourceRoot":"","sources":["../../src/pdpp/review.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * PDPP Core §6 selection-request validation.
3
+ *
4
+ * This is the shape gate that runs before consent. It answers one question:
5
+ * is this request expressible against the retained declaration snapshot? It
6
+ * does not resolve anything — `resolve.ts` does that, and only against the
7
+ * same snapshot this module validated against.
8
+ *
9
+ * "Fails neutrally" in §6 means the both/neither `streams`/`selection_preset`
10
+ * failure is a Source validation failure the binding maps to an error code; it
11
+ * must not leak which of the two the client got wrong, and it must not depend
12
+ * on any owner-specific state. We return a binding-neutral failure and let the
13
+ * OAuth/RAR layer map it to RFC 9396 `invalid_authorization_details`.
14
+ */
15
+ import { type DeclarationSnapshot, type SelectionRequest } from "./types.js";
16
+ /**
17
+ * Binding-neutral validation failure codes. The OAuth/RAR binding maps these
18
+ * to wire errors in `../../../server/src/routes/pdpp-authorize.ts`; Core
19
+ * itself stays binding-neutral (§9 AS item 5).
20
+ */
21
+ export type SelectionFailureCode =
22
+ /** Both or neither of `streams` and `selection_preset`. */
23
+ "source_validation_failed" | "unknown_stream" | "unknown_preset" | "unknown_view" | "unknown_field" | "unsupported_selection_parameter" | "invalid_resource_key"
24
+ /**
25
+ * A v0.2 `minimum` the AS cannot interpret. Distinct from
26
+ * `unsupported_selection_parameter` (a v0.2 member on a v0.1 request) and
27
+ * from the issuance-time `access_denied` a well-formed but unsatisfiable
28
+ * minimum produces: only this one is fixable by the client resending.
29
+ */
30
+ | "invalid_minimum" | "invalid_request";
31
+ export interface SelectionFailure {
32
+ code: SelectionFailureCode;
33
+ message: string;
34
+ }
35
+ export type SelectionValidation = {
36
+ ok: true;
37
+ } | {
38
+ ok: false;
39
+ failure: SelectionFailure;
40
+ };
41
+ /**
42
+ * Validate one selection request against the retained declaration snapshot.
43
+ *
44
+ * The caller must have already retrieved and pinned `snapshot`; this function
45
+ * never fetches. §9 AS item 16 requires that the same snapshot carry through
46
+ * consent and issuance, so passing a freshly fetched declaration here and a
47
+ * different one to `resolveGrant` would defeat the whole guarantee.
48
+ */
49
+ export declare function validateSelectionRequest(request: SelectionRequest, snapshot: DeclarationSnapshot): SelectionValidation;
50
+ //# sourceMappingURL=selection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/pdpp/selection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAGL,KAAK,mBAAmB,EAExB,KAAK,gBAAgB,EAEtB,MAAM,YAAY,CAAC;AAEpB;;;;GAIG;AACH,MAAM,MAAM,oBAAoB;AAC9B,2DAA2D;AACzD,0BAA0B,GAC1B,gBAAgB,GAChB,gBAAgB,GAChB,cAAc,GACd,eAAe,GACf,iCAAiC,GACjC,sBAAsB;AACxB;;;;;GAKG;GACD,iBAAiB,GACjB,iBAAiB,CAAC;AAEtB,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,oBAAoB,CAAC;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,mBAAmB,GAC7B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,gBAAgB,CAAA;CAAE,CAAC;AAga1D;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EACzB,QAAQ,EAAE,mBAAmB,GAC5B,mBAAmB,CAwJrB"}