@aigne/afs-did-space 1.12.0-beta.5

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 (510) hide show
  1. package/LICENSE.md +26 -0
  2. package/README.md +129 -0
  3. package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.cjs +11 -0
  4. package/dist/_virtual/_@oxc-project_runtime@0.108.0/helpers/decorate.mjs +10 -0
  5. package/dist/_virtual/rolldown_runtime.cjs +29 -0
  6. package/dist/afs-metadata-context.cjs +20 -0
  7. package/dist/afs-metadata-context.d.cts +21 -0
  8. package/dist/afs-metadata-context.d.cts.map +1 -0
  9. package/dist/afs-metadata-context.d.mts +21 -0
  10. package/dist/afs-metadata-context.d.mts.map +1 -0
  11. package/dist/afs-metadata-context.mjs +18 -0
  12. package/dist/afs-metadata-context.mjs.map +1 -0
  13. package/dist/blocklet-hook.cjs +180 -0
  14. package/dist/blocklet-hook.d.cts +29 -0
  15. package/dist/blocklet-hook.d.cts.map +1 -0
  16. package/dist/blocklet-hook.d.mts +29 -0
  17. package/dist/blocklet-hook.d.mts.map +1 -0
  18. package/dist/blocklet-hook.mjs +178 -0
  19. package/dist/blocklet-hook.mjs.map +1 -0
  20. package/dist/changelog-schema.cjs +603 -0
  21. package/dist/changelog-schema.d.cts +395 -0
  22. package/dist/changelog-schema.d.cts.map +1 -0
  23. package/dist/changelog-schema.d.mts +395 -0
  24. package/dist/changelog-schema.d.mts.map +1 -0
  25. package/dist/changelog-schema.mjs +570 -0
  26. package/dist/changelog-schema.mjs.map +1 -0
  27. package/dist/changelog-write.cjs +80 -0
  28. package/dist/changelog-write.d.cts +70 -0
  29. package/dist/changelog-write.d.cts.map +1 -0
  30. package/dist/changelog-write.d.mts +70 -0
  31. package/dist/changelog-write.d.mts.map +1 -0
  32. package/dist/changelog-write.mjs +77 -0
  33. package/dist/changelog-write.mjs.map +1 -0
  34. package/dist/cid-byte-cache.cjs +126 -0
  35. package/dist/cid-byte-cache.d.cts +46 -0
  36. package/dist/cid-byte-cache.d.cts.map +1 -0
  37. package/dist/cid-byte-cache.d.mts +47 -0
  38. package/dist/cid-byte-cache.d.mts.map +1 -0
  39. package/dist/cid-byte-cache.mjs +125 -0
  40. package/dist/cid-byte-cache.mjs.map +1 -0
  41. package/dist/cid.cjs +68 -0
  42. package/dist/cid.d.cts +22 -0
  43. package/dist/cid.d.cts.map +1 -0
  44. package/dist/cid.d.mts +22 -0
  45. package/dist/cid.d.mts.map +1 -0
  46. package/dist/cid.mjs +65 -0
  47. package/dist/cid.mjs.map +1 -0
  48. package/dist/client.cjs +221 -0
  49. package/dist/client.d.cts +72 -0
  50. package/dist/client.d.cts.map +1 -0
  51. package/dist/client.d.mts +72 -0
  52. package/dist/client.d.mts.map +1 -0
  53. package/dist/client.mjs +220 -0
  54. package/dist/client.mjs.map +1 -0
  55. package/dist/cloudflare.cjs +510 -0
  56. package/dist/cloudflare.d.cts +307 -0
  57. package/dist/cloudflare.d.cts.map +1 -0
  58. package/dist/cloudflare.d.mts +308 -0
  59. package/dist/cloudflare.d.mts.map +1 -0
  60. package/dist/cloudflare.mjs +507 -0
  61. package/dist/cloudflare.mjs.map +1 -0
  62. package/dist/ctime-backfill.cjs +272 -0
  63. package/dist/ctime-backfill.d.cts +169 -0
  64. package/dist/ctime-backfill.d.cts.map +1 -0
  65. package/dist/ctime-backfill.d.mts +169 -0
  66. package/dist/ctime-backfill.d.mts.map +1 -0
  67. package/dist/ctime-backfill.mjs +267 -0
  68. package/dist/ctime-backfill.mjs.map +1 -0
  69. package/dist/d1-gc-queue.cjs +80 -0
  70. package/dist/d1-gc-queue.d.cts +59 -0
  71. package/dist/d1-gc-queue.d.cts.map +1 -0
  72. package/dist/d1-gc-queue.d.mts +59 -0
  73. package/dist/d1-gc-queue.d.mts.map +1 -0
  74. package/dist/d1-gc-queue.mjs +81 -0
  75. package/dist/d1-gc-queue.mjs.map +1 -0
  76. package/dist/d1-resolve-store.cjs +189 -0
  77. package/dist/d1-resolve-store.d.cts +93 -0
  78. package/dist/d1-resolve-store.d.cts.map +1 -0
  79. package/dist/d1-resolve-store.d.mts +93 -0
  80. package/dist/d1-resolve-store.d.mts.map +1 -0
  81. package/dist/d1-resolve-store.mjs +190 -0
  82. package/dist/d1-resolve-store.mjs.map +1 -0
  83. package/dist/d1-schema.cjs +361 -0
  84. package/dist/d1-schema.d.cts +237 -0
  85. package/dist/d1-schema.d.cts.map +1 -0
  86. package/dist/d1-schema.d.mts +237 -0
  87. package/dist/d1-schema.d.mts.map +1 -0
  88. package/dist/d1-schema.mjs +341 -0
  89. package/dist/d1-schema.mjs.map +1 -0
  90. package/dist/d1-share-store.cjs +0 -0
  91. package/dist/d1-share-store.d.cts +53 -0
  92. package/dist/d1-share-store.d.cts.map +1 -0
  93. package/dist/d1-share-store.d.mts +53 -0
  94. package/dist/d1-share-store.d.mts.map +1 -0
  95. package/dist/d1-share-store.mjs +0 -0
  96. package/dist/d1-share-store.mjs.map +1 -0
  97. package/dist/d1-tree-index.cjs +1098 -0
  98. package/dist/d1-tree-index.d.cts +203 -0
  99. package/dist/d1-tree-index.d.cts.map +1 -0
  100. package/dist/d1-tree-index.d.mts +203 -0
  101. package/dist/d1-tree-index.d.mts.map +1 -0
  102. package/dist/d1-tree-index.mjs +1094 -0
  103. package/dist/d1-tree-index.mjs.map +1 -0
  104. package/dist/data-backend.cjs +147 -0
  105. package/dist/data-backend.d.cts +30 -0
  106. package/dist/data-backend.d.cts.map +1 -0
  107. package/dist/data-backend.d.mts +30 -0
  108. package/dist/data-backend.d.mts.map +1 -0
  109. package/dist/data-backend.mjs +148 -0
  110. package/dist/data-backend.mjs.map +1 -0
  111. package/dist/dedup-backfill.cjs +278 -0
  112. package/dist/dedup-backfill.d.cts +165 -0
  113. package/dist/dedup-backfill.d.cts.map +1 -0
  114. package/dist/dedup-backfill.d.mts +165 -0
  115. package/dist/dedup-backfill.d.mts.map +1 -0
  116. package/dist/dedup-backfill.mjs +273 -0
  117. package/dist/dedup-backfill.mjs.map +1 -0
  118. package/dist/did-space-like.d.cts +2 -0
  119. package/dist/did-space-like.d.mts +2 -0
  120. package/dist/did-utils.cjs +44 -0
  121. package/dist/did-utils.d.cts +25 -0
  122. package/dist/did-utils.d.cts.map +1 -0
  123. package/dist/did-utils.d.mts +25 -0
  124. package/dist/did-utils.d.mts.map +1 -0
  125. package/dist/did-utils.mjs +43 -0
  126. package/dist/did-utils.mjs.map +1 -0
  127. package/dist/dirty-path-queue.cjs +31 -0
  128. package/dist/dirty-path-queue.d.cts +104 -0
  129. package/dist/dirty-path-queue.d.cts.map +1 -0
  130. package/dist/dirty-path-queue.d.mts +104 -0
  131. package/dist/dirty-path-queue.d.mts.map +1 -0
  132. package/dist/dirty-path-queue.mjs +31 -0
  133. package/dist/dirty-path-queue.mjs.map +1 -0
  134. package/dist/dirty-path-schema.cjs +142 -0
  135. package/dist/dirty-path-schema.d.cts +90 -0
  136. package/dist/dirty-path-schema.d.cts.map +1 -0
  137. package/dist/dirty-path-schema.d.mts +90 -0
  138. package/dist/dirty-path-schema.d.mts.map +1 -0
  139. package/dist/dirty-path-schema.mjs +136 -0
  140. package/dist/dirty-path-schema.mjs.map +1 -0
  141. package/dist/download-actions.cjs +43 -0
  142. package/dist/download-actions.mjs +40 -0
  143. package/dist/download-actions.mjs.map +1 -0
  144. package/dist/fs-object-store.cjs +153 -0
  145. package/dist/fs-object-store.d.cts +21 -0
  146. package/dist/fs-object-store.d.cts.map +1 -0
  147. package/dist/fs-object-store.d.mts +22 -0
  148. package/dist/fs-object-store.d.mts.map +1 -0
  149. package/dist/fs-object-store.mjs +153 -0
  150. package/dist/fs-object-store.mjs.map +1 -0
  151. package/dist/gc-queue.d.cts +43 -0
  152. package/dist/gc-queue.d.cts.map +1 -0
  153. package/dist/gc-queue.d.mts +43 -0
  154. package/dist/gc-queue.d.mts.map +1 -0
  155. package/dist/index.cjs +2712 -0
  156. package/dist/index.d.cts +504 -0
  157. package/dist/index.d.cts.map +1 -0
  158. package/dist/index.d.mts +505 -0
  159. package/dist/index.d.mts.map +1 -0
  160. package/dist/index.mjs +2537 -0
  161. package/dist/index.mjs.map +1 -0
  162. package/dist/inline-content-migration.cjs +212 -0
  163. package/dist/inline-content-migration.d.cts +110 -0
  164. package/dist/inline-content-migration.d.cts.map +1 -0
  165. package/dist/inline-content-migration.d.mts +111 -0
  166. package/dist/inline-content-migration.d.mts.map +1 -0
  167. package/dist/inline-content-migration.mjs +207 -0
  168. package/dist/inline-content-migration.mjs.map +1 -0
  169. package/dist/inline-content.cjs +145 -0
  170. package/dist/inline-content.d.cts +98 -0
  171. package/dist/inline-content.d.cts.map +1 -0
  172. package/dist/inline-content.d.mts +98 -0
  173. package/dist/inline-content.d.mts.map +1 -0
  174. package/dist/inline-content.mjs +137 -0
  175. package/dist/inline-content.mjs.map +1 -0
  176. package/dist/local-changelog.cjs +241 -0
  177. package/dist/local-changelog.d.cts +119 -0
  178. package/dist/local-changelog.d.cts.map +1 -0
  179. package/dist/local-changelog.d.mts +119 -0
  180. package/dist/local-changelog.d.mts.map +1 -0
  181. package/dist/local-changelog.mjs +240 -0
  182. package/dist/local-changelog.mjs.map +1 -0
  183. package/dist/local.cjs +435 -0
  184. package/dist/local.d.cts +254 -0
  185. package/dist/local.d.cts.map +1 -0
  186. package/dist/local.d.mts +254 -0
  187. package/dist/local.d.mts.map +1 -0
  188. package/dist/local.mjs +427 -0
  189. package/dist/local.mjs.map +1 -0
  190. package/dist/memory-gc-queue.cjs +36 -0
  191. package/dist/memory-gc-queue.d.cts +22 -0
  192. package/dist/memory-gc-queue.d.cts.map +1 -0
  193. package/dist/memory-gc-queue.d.mts +22 -0
  194. package/dist/memory-gc-queue.d.mts.map +1 -0
  195. package/dist/memory-gc-queue.mjs +36 -0
  196. package/dist/memory-gc-queue.mjs.map +1 -0
  197. package/dist/memory-tree-index.cjs +734 -0
  198. package/dist/memory-tree-index.d.cts +159 -0
  199. package/dist/memory-tree-index.d.cts.map +1 -0
  200. package/dist/memory-tree-index.d.mts +159 -0
  201. package/dist/memory-tree-index.d.mts.map +1 -0
  202. package/dist/memory-tree-index.mjs +735 -0
  203. package/dist/memory-tree-index.mjs.map +1 -0
  204. package/dist/metadata-db.cjs +562 -0
  205. package/dist/metadata-db.d.cts +102 -0
  206. package/dist/metadata-db.d.cts.map +1 -0
  207. package/dist/metadata-db.d.mts +102 -0
  208. package/dist/metadata-db.d.mts.map +1 -0
  209. package/dist/metadata-db.mjs +562 -0
  210. package/dist/metadata-db.mjs.map +1 -0
  211. package/dist/mime-utils.cjs +2 -0
  212. package/dist/mime-utils.d.cts +2 -0
  213. package/dist/mime-utils.d.mts +2 -0
  214. package/dist/mime-utils.mjs +3 -0
  215. package/dist/object-key.cjs +41 -0
  216. package/dist/object-key.d.cts +25 -0
  217. package/dist/object-key.d.cts.map +1 -0
  218. package/dist/object-key.d.mts +25 -0
  219. package/dist/object-key.d.mts.map +1 -0
  220. package/dist/object-key.mjs +40 -0
  221. package/dist/object-key.mjs.map +1 -0
  222. package/dist/packages/session/dist/index.cjs +788 -0
  223. package/dist/packages/session/dist/index.mjs +782 -0
  224. package/dist/packages/session/dist/index.mjs.map +1 -0
  225. package/dist/platform/r2/dist/types.d.cts +49 -0
  226. package/dist/platform/r2/dist/types.d.cts.map +1 -0
  227. package/dist/prefix-range.cjs +33 -0
  228. package/dist/prefix-range.d.cts +29 -0
  229. package/dist/prefix-range.d.cts.map +1 -0
  230. package/dist/prefix-range.d.mts +29 -0
  231. package/dist/prefix-range.d.mts.map +1 -0
  232. package/dist/prefix-range.mjs +33 -0
  233. package/dist/prefix-range.mjs.map +1 -0
  234. package/dist/prefixed-tree-index.cjs +238 -0
  235. package/dist/prefixed-tree-index.d.cts +85 -0
  236. package/dist/prefixed-tree-index.d.cts.map +1 -0
  237. package/dist/prefixed-tree-index.d.mts +85 -0
  238. package/dist/prefixed-tree-index.d.mts.map +1 -0
  239. package/dist/prefixed-tree-index.mjs +239 -0
  240. package/dist/prefixed-tree-index.mjs.map +1 -0
  241. package/dist/presign-signer.cjs +7 -0
  242. package/dist/presign-signer.d.cts +99 -0
  243. package/dist/presign-signer.d.cts.map +1 -0
  244. package/dist/presign-signer.d.mts +99 -0
  245. package/dist/presign-signer.d.mts.map +1 -0
  246. package/dist/presign-signer.mjs +7 -0
  247. package/dist/presign-signer.mjs.map +1 -0
  248. package/dist/providers/platform/r2/dist/index.d.mts +3 -0
  249. package/dist/providers/platform/r2/dist/types.d.mts +49 -0
  250. package/dist/providers/platform/r2/dist/types.d.mts.map +1 -0
  251. package/dist/reconcile.cjs +184 -0
  252. package/dist/reconcile.d.cts +26 -0
  253. package/dist/reconcile.d.cts.map +1 -0
  254. package/dist/reconcile.d.mts +26 -0
  255. package/dist/reconcile.d.mts.map +1 -0
  256. package/dist/reconcile.mjs +184 -0
  257. package/dist/reconcile.mjs.map +1 -0
  258. package/dist/reference-check.cjs +49 -0
  259. package/dist/reference-check.d.cts +10 -0
  260. package/dist/reference-check.d.cts.map +1 -0
  261. package/dist/reference-check.d.mts +10 -0
  262. package/dist/reference-check.d.mts.map +1 -0
  263. package/dist/reference-check.mjs +48 -0
  264. package/dist/reference-check.mjs.map +1 -0
  265. package/dist/remote-afs.cjs +681 -0
  266. package/dist/remote-afs.d.cts +236 -0
  267. package/dist/remote-afs.d.cts.map +1 -0
  268. package/dist/remote-afs.d.mts +236 -0
  269. package/dist/remote-afs.d.mts.map +1 -0
  270. package/dist/remote-afs.mjs +676 -0
  271. package/dist/remote-afs.mjs.map +1 -0
  272. package/dist/rename-guard.cjs +18 -0
  273. package/dist/rename-guard.mjs +18 -0
  274. package/dist/rename-guard.mjs.map +1 -0
  275. package/dist/resolve.cjs +260 -0
  276. package/dist/resolve.d.cts +113 -0
  277. package/dist/resolve.d.cts.map +1 -0
  278. package/dist/resolve.d.mts +113 -0
  279. package/dist/resolve.d.mts.map +1 -0
  280. package/dist/resolve.mjs +260 -0
  281. package/dist/resolve.mjs.map +1 -0
  282. package/dist/rsync-content.cjs +33 -0
  283. package/dist/rsync-content.mjs +33 -0
  284. package/dist/rsync-content.mjs.map +1 -0
  285. package/dist/rsync.cjs +400 -0
  286. package/dist/rsync.d.cts +157 -0
  287. package/dist/rsync.d.cts.map +1 -0
  288. package/dist/rsync.d.mts +157 -0
  289. package/dist/rsync.d.mts.map +1 -0
  290. package/dist/rsync.mjs +397 -0
  291. package/dist/rsync.mjs.map +1 -0
  292. package/dist/run-gc.cjs +57 -0
  293. package/dist/run-gc.d.cts +40 -0
  294. package/dist/run-gc.d.cts.map +1 -0
  295. package/dist/run-gc.d.mts +41 -0
  296. package/dist/run-gc.d.mts.map +1 -0
  297. package/dist/run-gc.mjs +57 -0
  298. package/dist/run-gc.mjs.map +1 -0
  299. package/dist/scope-id.cjs +70 -0
  300. package/dist/scope-id.d.cts +35 -0
  301. package/dist/scope-id.d.cts.map +1 -0
  302. package/dist/scope-id.d.mts +35 -0
  303. package/dist/scope-id.d.mts.map +1 -0
  304. package/dist/scope-id.mjs +68 -0
  305. package/dist/scope-id.mjs.map +1 -0
  306. package/dist/scope-migration-node.cjs +172 -0
  307. package/dist/scope-migration-node.d.cts +44 -0
  308. package/dist/scope-migration-node.d.cts.map +1 -0
  309. package/dist/scope-migration-node.d.mts +44 -0
  310. package/dist/scope-migration-node.d.mts.map +1 -0
  311. package/dist/scope-migration-node.mjs +171 -0
  312. package/dist/scope-migration-node.mjs.map +1 -0
  313. package/dist/scope-migration.cjs +155 -0
  314. package/dist/scope-migration.d.cts +65 -0
  315. package/dist/scope-migration.d.cts.map +1 -0
  316. package/dist/scope-migration.d.mts +65 -0
  317. package/dist/scope-migration.d.mts.map +1 -0
  318. package/dist/scope-migration.mjs +154 -0
  319. package/dist/scope-migration.mjs.map +1 -0
  320. package/dist/share-declaration.cjs +225 -0
  321. package/dist/share-declaration.d.cts +30 -0
  322. package/dist/share-declaration.d.cts.map +1 -0
  323. package/dist/share-declaration.d.mts +32 -0
  324. package/dist/share-declaration.d.mts.map +1 -0
  325. package/dist/share-declaration.mjs +221 -0
  326. package/dist/share-declaration.mjs.map +1 -0
  327. package/dist/share-hook.cjs +63 -0
  328. package/dist/share-hook.mjs +62 -0
  329. package/dist/share-hook.mjs.map +1 -0
  330. package/dist/share-resolve.cjs +176 -0
  331. package/dist/share-resolve.d.cts +36 -0
  332. package/dist/share-resolve.d.cts.map +1 -0
  333. package/dist/share-resolve.d.mts +36 -0
  334. package/dist/share-resolve.d.mts.map +1 -0
  335. package/dist/share-resolve.mjs +177 -0
  336. package/dist/share-resolve.mjs.map +1 -0
  337. package/dist/share-serve.cjs +145 -0
  338. package/dist/share-serve.d.cts +30 -0
  339. package/dist/share-serve.d.cts.map +1 -0
  340. package/dist/share-serve.d.mts +30 -0
  341. package/dist/share-serve.d.mts.map +1 -0
  342. package/dist/share-serve.mjs +144 -0
  343. package/dist/share-serve.mjs.map +1 -0
  344. package/dist/share-store.cjs +25 -0
  345. package/dist/share-store.d.cts +65 -0
  346. package/dist/share-store.d.cts.map +1 -0
  347. package/dist/share-store.d.mts +65 -0
  348. package/dist/share-store.d.mts.map +1 -0
  349. package/dist/share-store.mjs +25 -0
  350. package/dist/share-store.mjs.map +1 -0
  351. package/dist/share-virtual-path.cjs +102 -0
  352. package/dist/share-virtual-path.mjs +101 -0
  353. package/dist/share-virtual-path.mjs.map +1 -0
  354. package/dist/space-resolver.cjs +54 -0
  355. package/dist/space-resolver.d.cts +34 -0
  356. package/dist/space-resolver.d.cts.map +1 -0
  357. package/dist/space-resolver.d.mts +34 -0
  358. package/dist/space-resolver.d.mts.map +1 -0
  359. package/dist/space-resolver.mjs +55 -0
  360. package/dist/space-resolver.mjs.map +1 -0
  361. package/dist/sqlite-gc-queue.cjs +51 -0
  362. package/dist/sqlite-gc-queue.d.cts +22 -0
  363. package/dist/sqlite-gc-queue.d.cts.map +1 -0
  364. package/dist/sqlite-gc-queue.d.mts +22 -0
  365. package/dist/sqlite-gc-queue.d.mts.map +1 -0
  366. package/dist/sqlite-gc-queue.mjs +52 -0
  367. package/dist/sqlite-gc-queue.mjs.map +1 -0
  368. package/dist/sqlite-resolve-store.cjs +163 -0
  369. package/dist/sqlite-resolve-store.d.cts +50 -0
  370. package/dist/sqlite-resolve-store.d.cts.map +1 -0
  371. package/dist/sqlite-resolve-store.d.mts +50 -0
  372. package/dist/sqlite-resolve-store.d.mts.map +1 -0
  373. package/dist/sqlite-resolve-store.mjs +164 -0
  374. package/dist/sqlite-resolve-store.mjs.map +1 -0
  375. package/dist/sqlite-share-store.cjs +157 -0
  376. package/dist/sqlite-share-store.d.cts +31 -0
  377. package/dist/sqlite-share-store.d.cts.map +1 -0
  378. package/dist/sqlite-share-store.d.mts +31 -0
  379. package/dist/sqlite-share-store.d.mts.map +1 -0
  380. package/dist/sqlite-share-store.mjs +157 -0
  381. package/dist/sqlite-share-store.mjs.map +1 -0
  382. package/dist/sqlite-tree-index.cjs +901 -0
  383. package/dist/sqlite-tree-index.d.cts +107 -0
  384. package/dist/sqlite-tree-index.d.cts.map +1 -0
  385. package/dist/sqlite-tree-index.d.mts +107 -0
  386. package/dist/sqlite-tree-index.d.mts.map +1 -0
  387. package/dist/sqlite-tree-index.mjs +902 -0
  388. package/dist/sqlite-tree-index.mjs.map +1 -0
  389. package/dist/sync-engine.cjs +1324 -0
  390. package/dist/sync-engine.d.cts +473 -0
  391. package/dist/sync-engine.d.cts.map +1 -0
  392. package/dist/sync-engine.d.mts +473 -0
  393. package/dist/sync-engine.d.mts.map +1 -0
  394. package/dist/sync-engine.mjs +1315 -0
  395. package/dist/sync-engine.mjs.map +1 -0
  396. package/dist/sync-state.cjs +303 -0
  397. package/dist/sync-state.d.cts +224 -0
  398. package/dist/sync-state.d.cts.map +1 -0
  399. package/dist/sync-state.d.mts +224 -0
  400. package/dist/sync-state.d.mts.map +1 -0
  401. package/dist/sync-state.mjs +297 -0
  402. package/dist/sync-state.mjs.map +1 -0
  403. package/dist/timestamp.cjs +92 -0
  404. package/dist/timestamp.mjs +91 -0
  405. package/dist/timestamp.mjs.map +1 -0
  406. package/dist/transports/http.cjs +54 -0
  407. package/dist/transports/http.d.cts +26 -0
  408. package/dist/transports/http.d.cts.map +1 -0
  409. package/dist/transports/http.d.mts +26 -0
  410. package/dist/transports/http.d.mts.map +1 -0
  411. package/dist/transports/http.mjs +54 -0
  412. package/dist/transports/http.mjs.map +1 -0
  413. package/dist/transports/static.cjs +55 -0
  414. package/dist/transports/static.d.cts +28 -0
  415. package/dist/transports/static.d.cts.map +1 -0
  416. package/dist/transports/static.d.mts +28 -0
  417. package/dist/transports/static.d.mts.map +1 -0
  418. package/dist/transports/static.mjs +55 -0
  419. package/dist/transports/static.mjs.map +1 -0
  420. package/dist/transports/types.cjs +13 -0
  421. package/dist/transports/types.d.cts +72 -0
  422. package/dist/transports/types.d.cts.map +1 -0
  423. package/dist/transports/types.d.mts +72 -0
  424. package/dist/transports/types.d.mts.map +1 -0
  425. package/dist/transports/types.mjs +13 -0
  426. package/dist/transports/types.mjs.map +1 -0
  427. package/dist/transports/ws.cjs +207 -0
  428. package/dist/transports/ws.d.cts +47 -0
  429. package/dist/transports/ws.d.cts.map +1 -0
  430. package/dist/transports/ws.d.mts +47 -0
  431. package/dist/transports/ws.d.mts.map +1 -0
  432. package/dist/transports/ws.mjs +206 -0
  433. package/dist/transports/ws.mjs.map +1 -0
  434. package/dist/tree-index.cjs +333 -0
  435. package/dist/tree-index.d.cts +524 -0
  436. package/dist/tree-index.d.cts.map +1 -0
  437. package/dist/tree-index.d.mts +524 -0
  438. package/dist/tree-index.d.mts.map +1 -0
  439. package/dist/tree-index.mjs +322 -0
  440. package/dist/tree-index.mjs.map +1 -0
  441. package/dist/tree-query.cjs +655 -0
  442. package/dist/tree-query.d.cts +70 -0
  443. package/dist/tree-query.d.cts.map +1 -0
  444. package/dist/tree-query.d.mts +70 -0
  445. package/dist/tree-query.d.mts.map +1 -0
  446. package/dist/tree-query.mjs +648 -0
  447. package/dist/tree-query.mjs.map +1 -0
  448. package/dist/upload-actions.cjs +97 -0
  449. package/dist/upload-actions.d.cts +19 -0
  450. package/dist/upload-actions.d.cts.map +1 -0
  451. package/dist/upload-actions.d.mts +21 -0
  452. package/dist/upload-actions.d.mts.map +1 -0
  453. package/dist/upload-actions.mjs +90 -0
  454. package/dist/upload-actions.mjs.map +1 -0
  455. package/dist/upload-session-store.cjs +185 -0
  456. package/dist/upload-session-store.d.cts +99 -0
  457. package/dist/upload-session-store.d.cts.map +1 -0
  458. package/dist/upload-session-store.d.mts +99 -0
  459. package/dist/upload-session-store.d.mts.map +1 -0
  460. package/dist/upload-session-store.mjs +184 -0
  461. package/dist/upload-session-store.mjs.map +1 -0
  462. package/dist/url-normalize.cjs +61 -0
  463. package/dist/url-normalize.d.cts +33 -0
  464. package/dist/url-normalize.d.cts.map +1 -0
  465. package/dist/url-normalize.d.mts +33 -0
  466. package/dist/url-normalize.d.mts.map +1 -0
  467. package/dist/url-normalize.mjs +61 -0
  468. package/dist/url-normalize.mjs.map +1 -0
  469. package/dist/versioned-content-backends.cjs +155 -0
  470. package/dist/versioned-content-backends.d.cts +49 -0
  471. package/dist/versioned-content-backends.d.cts.map +1 -0
  472. package/dist/versioned-content-backends.d.mts +49 -0
  473. package/dist/versioned-content-backends.d.mts.map +1 -0
  474. package/dist/versioned-content-backends.mjs +154 -0
  475. package/dist/versioned-content-backends.mjs.map +1 -0
  476. package/dist/versioned-content-index.cjs +102 -0
  477. package/dist/versioned-content-index.d.cts +46 -0
  478. package/dist/versioned-content-index.d.cts.map +1 -0
  479. package/dist/versioned-content-index.d.mts +46 -0
  480. package/dist/versioned-content-index.d.mts.map +1 -0
  481. package/dist/versioned-content-index.mjs +103 -0
  482. package/dist/versioned-content-index.mjs.map +1 -0
  483. package/dist/versioned-content-store.cjs +121 -0
  484. package/dist/versioned-content-store.d.cts +90 -0
  485. package/dist/versioned-content-store.d.cts.map +1 -0
  486. package/dist/versioned-content-store.d.mts +90 -0
  487. package/dist/versioned-content-store.d.mts.map +1 -0
  488. package/dist/versioned-content-store.mjs +122 -0
  489. package/dist/versioned-content-store.mjs.map +1 -0
  490. package/dist/versioned-scope.cjs +39 -0
  491. package/dist/versioned-scope.d.cts +57 -0
  492. package/dist/versioned-scope.d.cts.map +1 -0
  493. package/dist/versioned-scope.d.mts +57 -0
  494. package/dist/versioned-scope.d.mts.map +1 -0
  495. package/dist/versioned-scope.mjs +37 -0
  496. package/dist/versioned-scope.mjs.map +1 -0
  497. package/migrations/0001_tree_entries.sql +17 -0
  498. package/migrations/0002_resolve_entries.sql +7 -0
  499. package/migrations/0003_entries_v2.sql +38 -0
  500. package/migrations/0004_gc_queue.sql +5 -0
  501. package/migrations/0006_resolve_enhance.sql +14 -0
  502. package/migrations/0007_resolve_created_at.sql +10 -0
  503. package/migrations/0008_changelog.sql +34 -0
  504. package/migrations/0009_device_sync_state.sql +29 -0
  505. package/migrations/0010_scope_meta.sql +33 -0
  506. package/migrations/0011_shares.sql +25 -0
  507. package/migrations/0012_scope_meta_file_count.sql +41 -0
  508. package/migrations/0013_scope_meta_total_bytes.sql +47 -0
  509. package/migrations/0014_rename_tables.sql +62 -0
  510. package/package.json +102 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["scan","succeeded","meta"],"sources":["../src/index.ts"],"sourcesContent":["import type {\n AFSAccessMode,\n AFSBatchConflictInfo,\n AFSBatchDeleteEntry,\n AFSBatchDeleteResult,\n AFSBatchReadEntry,\n AFSBatchReadEntryResult,\n AFSBatchReadResult,\n AFSBatchWriteEntry,\n AFSBatchWriteResult,\n AFSCollectionQueryResult,\n AFSCollectionQuerySpec,\n AFSDeleteOptions,\n AFSEntry,\n AFSEntryMetadata,\n AFSExecResult,\n AFSExplainResult,\n AFSListOptions,\n AFSListResult,\n AFSOperationOptions,\n AFSQueryOptions,\n AFSSearchOptions,\n AFSStatResult,\n AFSWriteEntryPayload,\n AFSWriteOptions,\n AFSWriteResult,\n CapabilitiesManifest,\n OperationsDeclaration,\n ProviderManifest,\n ProviderTreeSchema,\n} from \"@aigne/afs\";\nimport {\n AFSCompactedError,\n AFSConflictError,\n AFSForbiddenError,\n AFSNotFoundError,\n AFSUnsupportedError,\n AFSValidationError,\n collectionQueryStandardAction,\n isValidOrderBy,\n type OrderByTuple,\n orderByRequested,\n orderEntries,\n resolveFieldPath,\n SCRIPT_EVENT_TYPES,\n} from \"@aigne/afs\";\nimport {\n Actions,\n AFSBaseProvider,\n Delete,\n Explain,\n List,\n Meta,\n Read,\n type RouteContext,\n Search,\n Stat,\n Write,\n} from \"@aigne/afs/provider\";\nimport type { ObjectStore } from \"@aigne/afs-r2\";\nimport { time } from \"@aigne/afs-timing\";\nimport { joinURL } from \"ufo\";\nimport { z } from \"zod\";\nimport { applyBlockletDeleteHook, applyBlockletWriteHook } from \"./blocklet-hook.js\";\nimport {\n CHANGELOG_ROW_KIND,\n serializeChangelogEntry,\n serializeManifestEntry,\n watermarkWritePrefix,\n} from \"./changelog-schema.js\";\nimport { checksumSha256OfContent, cidToChecksumSha256, computeCID } from \"./cid.js\";\nimport { normalizeId, validateId } from \"./did-utils.js\";\nimport {\n DOWNLOAD_ACTIONS,\n DOWNLOAD_GRANT_TTL_SEC,\n PrepareDownloadArgsSchema,\n} from \"./download-actions.js\";\nimport type { GcQueue } from \"./gc-queue.js\";\nimport { decodeInlineText } from \"./inline-content.js\";\nimport { detectMimeType, isTextMime } from \"./mime-utils.js\";\nimport type { PresignSigner } from \"./presign-signer.js\";\nimport type { DIDSpaceResolver } from \"./resolve.js\";\nimport { isShareReservedPath } from \"./share-declaration.js\";\nimport { applyShareDeleteHook, applyShareWriteHook } from \"./share-hook.js\";\nimport type { ShareResolver } from \"./share-resolve.js\";\nimport { matchSharesVirtualPath, ShareVirtualHandler } from \"./share-virtual-path.js\";\nimport { resolveCtime } from \"./timestamp.js\";\nimport type {\n BatchDeleteEntry,\n BatchPutEntry,\n PutOpts,\n TreeEntry,\n TreeIndex,\n TreeIndexListOptions,\n} from \"./tree-index.js\";\nimport { loopBatchDeleteEntries, loopBatchPutEntries } from \"./tree-index.js\";\nimport {\n assertTreeQuerySpec,\n parseRecordText,\n projectRecordFields,\n type TreeQueryRow,\n} from \"./tree-query.js\";\nimport {\n AbortUploadArgsSchema,\n CommitUploadArgsSchema,\n GRANT_EXPIRES_SEC,\n ifMatchPreconditionFailed,\n PrepareUploadArgsSchema,\n UPLOAD_ACTIONS,\n zodMessage,\n} from \"./upload-actions.js\";\nimport {\n UPLOAD_SESSION_TTL_MS,\n type UploadSession,\n type UploadSessionEntryInput,\n type UploadSessionStore,\n} from \"./upload-session-store.js\";\nimport { normalizeItemUrl } from \"./url-normalize.js\";\n\nexport {\n type AFSMetadataContext,\n attachMetadataContext,\n detachMetadataContext,\n getMetadataContext,\n} from \"./afs-metadata-context.js\";\nexport {\n BLOCKLET_PUBLISH_MARKER,\n type BlockletPublishMarker,\n} from \"./blocklet-hook.js\";\nexport {\n CHANGELOG_DDL,\n CHANGELOG_INDEX_SQL,\n CHANGELOG_ROW_KIND,\n CHANGELOG_SCOPE_CID_MIGRATION_SQL,\n CHANGELOG_TABLE_SQL,\n CHANGELOG_WIRE_EXTRA_FIELDS,\n type ChangelogRowInput,\n type ChangelogWireExtra,\n DEVICE_SYNC_STATE_INDEX_SQL,\n DEVICE_SYNC_STATE_TABLE_SQL,\n MANIFEST_FILE_KIND,\n MANIFEST_WIRE_EXTRA_FIELDS,\n type ManifestRowInput,\n type ManifestWireMeta,\n normalizeDdl,\n PREFIX_WATERMARK_TABLE_SQL,\n parseChangelogEntry,\n parseManifestEntry,\n SCOPE_META_FILE_COUNT_BACKFILL_SQL,\n SCOPE_META_FILE_COUNT_DELETE_ONE_SQL,\n SCOPE_META_FILE_COUNT_DELETE_RANGE_SQL,\n SCOPE_META_FILE_COUNT_TRIGGER_SQL,\n SCOPE_META_INDEX_SQL,\n SCOPE_META_TABLE_SQL,\n SCOPE_META_TOTAL_BYTES_BACKFILL_SQL,\n SCOPE_META_TOTAL_BYTES_COLUMN_SQL,\n SCOPE_META_TOTAL_BYTES_TRIGGER_SQL,\n SYNC_STATE_DDL,\n SYNC_STATE_INDEX_SQL,\n SYNC_STATE_TABLE_SQL,\n serializeChangelogEntry,\n serializeManifestEntry,\n} from \"./changelog-schema.js\";\nexport {\n buildChangelogBinds,\n CHANGELOG_INSERT_SQL,\n MAX_DEVICE_ID_BYTES,\n validateDeviceId,\n} from \"./changelog-write.js\";\nexport { cidToChecksumSha256, computeCID } from \"./cid.js\";\nexport { CachingObjectStore, CidByteCache, type CidByteCacheOptions } from \"./cid-byte-cache.js\";\nexport {\n type ConnectDIDSpaceOptions,\n connectDIDSpace,\n DIDSpaceClient,\n type DIDSpaceClientOptions,\n} from \"./client.js\";\nexport { D1GCQueue } from \"./d1-gc-queue.js\";\nexport { D1ResolveStore } from \"./d1-resolve-store.js\";\nexport {\n D1_DID_SPACE_SCHEMA_SQL,\n ENTRIES_CONTENT_TYPE_COLUMN_SQL,\n ENTRIES_CONTENT_TYPE_INDEX_DROP_SQL,\n ENTRIES_CONTENT_TYPE_INDEX_SQL,\n ENTRIES_DEDUP_INDEX_SQL,\n ENTRIES_DEDUP_KEY_COLUMN_SQL,\n ENTRIES_DEDUP_SCOPE_COLUMN_SQL,\n ENTRIES_INDEX_SQL,\n ENTRIES_INLINE_CONTENT_COLUMN_SQL,\n ENTRIES_METADATA_COLUMN_SQL,\n ENTRIES_TABLE_SQL,\n GC_QUEUE_INDEX_SQL,\n GC_QUEUE_TABLE_SQL,\n RESOLVE_ENTRIES_INDEX_SQL,\n RESOLVE_ENTRIES_TABLE_SQL,\n SHARES_INDEX_SQL,\n SHARES_TABLE_SQL,\n UPLOAD_SESSION_ENTRIES_TABLE_SQL,\n UPLOAD_SESSIONS_INDEX_SQL,\n UPLOAD_SESSIONS_TABLE_SQL,\n VERSIONED_SCOPES_INDEX_SQL,\n VERSIONED_SCOPES_TABLE_SQL,\n} from \"./d1-schema.js\";\nexport { D1ShareReconciler, D1ShareStore, type ReconcileReport } from \"./d1-share-store.js\";\nexport {\n ancestorDirs,\n D1TreeIndex,\n MAX_ENTRIES_PER_SCOPE,\n nameOf,\n parentOf,\n} from \"./d1-tree-index.js\";\nexport {\n DIDSpaceBlockletDataBackend,\n type DIDSpaceBlockletDataBackendOptions,\n} from \"./data-backend.js\";\nexport { normalizeId, validateId } from \"./did-utils.js\";\nexport {\n applyDirtyUpsert,\n type DirtyPathFollowerSource,\n type DirtyPathOp,\n type DirtyPathQueue,\n type DirtyPathRow,\n type DirtyPathStoredRow,\n type ListDirtyPathOptions,\n} from \"./dirty-path-queue.js\";\nexport {\n DIRTY_PATH_DDL,\n DIRTY_PATH_INDEX_SQL,\n DIRTY_PATH_TABLE_SQL,\n DIRTY_PATH_TRIGGER_SQL,\n} from \"./dirty-path-schema.js\";\nexport type { GcQueue } from \"./gc-queue.js\";\nexport {\n assertInlineThreshold,\n DEFAULT_INLINE_THRESHOLD,\n decodeInlineText,\n INGEST_DEVICE_ID,\n INLINE_CONTENT_HARD_CAP,\n type InlineCacheMode,\n type InlineContentOptions,\n} from \"./inline-content.js\";\n// NOTE: the inline-content backfill migration (inline-content-commit Phase 6) is\n// a ONE-TIME offline tool — it ships behind the `./inline-content-migration`\n// subpath (its own tsdown entry) and is deliberately NOT re-exported here, so it\n// never enters the CF worker bundle (index.ts is the worker entry; the worker\n// never runs the migration).\nexport {\n LOCAL_CHANGELOG_DEFAULT_LIMIT,\n LOCAL_CHANGELOG_MAX_LIMIT,\n LocalChangelog,\n type LocalChangelogOptions,\n} from \"./local-changelog.js\";\nexport { MemoryGcQueue } from \"./memory-gc-queue.js\";\nexport { MemoryTreeIndex } from \"./memory-tree-index.js\";\nexport { assertValidCid, objectKeyForCid } from \"./object-key.js\";\nexport { prefixRange } from \"./prefix-range.js\";\nexport { PrefixedTreeIndex } from \"./prefixed-tree-index.js\";\nexport {\n PRESIGN_MAX_EXPIRES_SEC,\n type PresignedGet,\n type PresignedPut,\n type PresignGetInput,\n type PresignPutInput,\n type PresignSigner,\n} from \"./presign-signer.js\";\nexport { referencedAnywhereD1, referencedAnywhereLibsql } from \"./reference-check.js\";\n// `RemoteUserSpaceAFS` was the Phase 1/2 single REST adapter. Phase 3\n// reframed it as `HttpTransport` underneath the new `DIDSpaceClient`\n// (see `./transports/http.ts` and `./client.ts`). The class file stays\n// in-tree because `HttpTransport` reuses its REST + error-mapping\n// internals — but it is no longer part of the package's public API.\n// External callers should switch to `connectDIDSpace` (HTTP transport).\n// `RpcUserSpaceAFS` (afs-rpc-batch P4) IS public: the afs-rpc wire transport\n// the SyncEngine + `arc space sync-bench` ride against live daemons/workers.\nexport {\n BatchOverBudgetError,\n BatchUnsupportedError,\n type RpcBatchEntryResult,\n type RpcBatchResult,\n RpcUserSpaceAFS,\n type RpcUserSpaceAFSOptions,\n} from \"./remote-afs.js\";\nexport { DIDSpaceResolver, type DomainResolveEntry, type ResolveEntry } from \"./resolve.js\";\nexport {\n type BuildManifestOptions,\n buildManifest,\n computeDiff,\n type FileFingerprint,\n fetchRemoteManifest,\n runWithConcurrency,\n type SyncDiff,\n type SyncDiffEntry,\n type SyncManifest,\n type SyncOptions,\n type SyncProgress,\n type SyncResult,\n syncDIDSpace,\n} from \"./rsync.js\";\nexport { DEFAULT_GC_GRACE_MS, type GcStats, type RunGcOptions, runGc } from \"./run-gc.js\";\nexport { decodeScopeHmacSecret, deriveScope, isPlainDidScope } from \"./scope-id.js\";\nexport {\n type BuildD1MigrationSqlOptions,\n buildD1MigrationSql,\n classifyScopes,\n type D1MigrationSql,\n migrateD1Scopes,\n type ScopeMigrationOptions,\n type ScopeMigrationReport,\n} from \"./scope-migration.js\";\n// NOTE: the Node migration (scope-migration-node.ts) uses node:fs and is\n// exposed via the `./local` subpath (re-exported from local.ts), NOT here —\n// index.ts is pulled into the CF worker bundle, whose node:fs stub has no\n// renameSync/readdirSync, so importing it from index would break the CF build.\nexport { ShareResolver } from \"./share-resolve.js\";\nexport {\n type BuildScopedAFS,\n type ServeShareOptions,\n type ShareLookup,\n serveShare,\n} from \"./share-serve.js\";\nexport {\n rowToEntry,\n type ShareEntry,\n type ShareRow,\n type ShareStore,\n} from \"./share-store.js\";\nexport { SqliteGcQueue } from \"./sqlite-gc-queue.js\";\nexport { SqliteResolveStore } from \"./sqlite-resolve-store.js\";\nexport { openDaemonShareStore, SqliteShareStore } from \"./sqlite-share-store.js\";\nexport {\n ConflictResolutionError,\n type ConflictResponse,\n CurrentObjectMissingError,\n type CurrentObjectSource,\n classifyMissingObject,\n PULL_BATCH_LIMIT,\n PULL_FETCH_CONCURRENCY,\n PUSH_BATCH_LIMIT,\n PUSH_PROGRESS_FLUSH_INTERVAL,\n SYNC_WALL_CLOCK_BUDGET_MS,\n type SyncCloudAFS,\n SyncEngine,\n type SyncEngineOptions,\n type SyncEngineProviderHandle,\n type SyncResult as SyncEngineResult,\n} from \"./sync-engine.js\";\nexport {\n type AppState,\n DEVICE_ID_FORMAT_RE,\n defaultAppState,\n generateDesktopDeviceId,\n isValidDeviceId,\n parseSyncStatus,\n SYNC_STATE_KEYS,\n SyncStateStore,\n type SyncStateStoreOptions,\n type SyncStatus,\n serializeSyncStatus,\n} from \"./sync-state.js\";\nexport {\n HttpTransport,\n type HttpTransportOptions,\n} from \"./transports/http.js\";\nexport {\n StaticReadonlyTransport,\n type StaticReadonlyTransportOptions,\n} from \"./transports/static.js\";\nexport type {\n HttpTransportConfig,\n StaticReadonlyTransportConfig,\n Transport,\n TransportConfig,\n TransportKind,\n Unsubscribe,\n WsTransportConfig,\n} from \"./transports/types.js\";\nexport {\n createWsTransport,\n WsTransport,\n type WsTransportOptions,\n} from \"./transports/ws.js\";\nexport {\n buildKeysetCursor,\n buildOrderedQueryParts,\n type ChangelogEntry,\n compareTreeSortValues,\n keysetAfter,\n type OrderedQueryParts,\n type ParsedTreeCursor,\n type PutOpts,\n parseTreeCursor,\n type TreeEntry,\n type TreeIndex,\n type TreeIndexListEntriesResult,\n type TreeIndexListOptions,\n type TreeIndexListResult,\n type TreeKeysetCursor,\n} from \"./tree-index.js\";\n// D3 expected-absent sentinel (upload-browser §4.2a): the ingest facade (aos)\n// imports it; recheck sites below consume it.\nexport { AFS_IFMATCH_ABSENT } from \"./upload-actions.js\";\nexport {\n D1UploadSessionStore,\n type NewUploadSession,\n SqliteUploadSessionStore,\n UPLOAD_SESSION_TTL_MS,\n type UploadSession,\n type UploadSessionEntry,\n type UploadSessionEntryInput,\n type UploadSessionEntryStatus,\n type UploadSessionStatus,\n type UploadSessionStore,\n} from \"./upload-session-store.js\";\nexport { normalizeItemUrl } from \"./url-normalize.js\";\nexport {\n D1VersionedScopeBackend,\n LibsqlVersionedScopeBackend,\n MemoryVersionedScopeBackend,\n} from \"./versioned-content-backends.js\";\nexport {\n type VersionedContentFile,\n VersionedContentIndex,\n type VersionedContentIndexOptions,\n} from \"./versioned-content-index.js\";\nexport {\n type EnsureScopeOptions,\n type EnsureScopeResult,\n type LoadedScopeContent,\n VersionedContentStore,\n type VersionedContentStoreOptions,\n type VersionedScopeBackend,\n type VersionedScopeMeta,\n} from \"./versioned-content-store.js\";\nexport {\n resolveVersionToken,\n type VersionedPackageIdentity,\n versionedScope,\n versionedScopeGroup,\n} from \"./versioned-scope.js\";\n\nimport { makeNsLog } from \"@aigne/afs\";\n\nconst log = makeNsLog(\"provider:did-space\");\n\n// ========== Helpers ==========\n\nexport { isShareDeclarationPath } from \"./share-declaration.js\";\nexport { detectMimeType, isTextMime };\n\nconst LIST_MAX_LIMIT = 1000;\n\n/**\n * Outcome of a shallow index scan (`listShallow` / `listShallowOrdered`):\n * `seen` counts every index row fetched — including rows past the build\n * cap — and `exhausted` says whether the cursor drained. Together they let\n * `shallowTotal` report the exact directory total without an extra COUNT\n * query whenever the directory fits in the scanned batches.\n */\ninterface ShallowScan {\n exhausted: boolean;\n seen: number;\n}\n\nexport interface DIDSpaceProviderOptions {\n did: string;\n objectStore: ObjectStore;\n treeIndex: TreeIndex;\n name?: string;\n description?: string;\n accessMode?: AFSAccessMode;\n /** Optional: gc queue for deferred R2 object cleanup (any `GcQueue` impl —\n * `D1GCQueue` on CF, `SqliteGcQueue` on Node, `MemoryGcQueue` in tests). */\n gcQueue?: GcQueue;\n /**\n * Task 2.4a: deviceId written into every `changelog` row for mutations\n * routed through the generic AFS write/delete handler. Production Worker\n * paths bypass this provider via `CloudflareDIDSpace.internalWrite` (Task\n * 2.4b) with a per-request deviceId from the `X-Device-Id` header; this\n * constructor default (`\"server:default\"`) is used only for tests,\n * conformance fixtures, and CLI flows that mount DIDSpaceProvider directly.\n */\n deviceId?: string;\n /** Optional: ShareResolver for .share reconcile hook (Phase 0.4) */\n shareResolver?: ShareResolver;\n /**\n * Owner DID recorded by the .share reconcile hook. Defaults to `did`. An\n * instance fragment provider (treeIndex prefixed to `blocklets/<i>/user/`)\n * has `did = instanceId`, but a share's owner is the WHOLE-SPACE user — pass\n * the user's DID here so reconcile keys `owner_did` to the space (matching\n * the serving scope), not the blocklet instance.\n */\n shareOwnerDid?: string;\n /**\n * Tree prefix prepended to the hook's `treePath` so the reconciled\n * `decl_path`/`source_path` are WHOLE-TREE paths (`blocklets/<i>/user/...`),\n * matching `shareResolver`'s whole-tree index and the serving scope. Set ONLY\n * on prefixed instance-fragment providers; whole-space providers leave it\n * unset (treePath is already whole-tree). Its presence also marks a provider\n * as an instance fragment, which suppresses the `.shares/` virtual read view.\n */\n shareTreePrefix?: string;\n /**\n * Optional: global resolve table for the blocklet publish/resolve hook\n * (#674). Writing a `blocklet.yaml` registers `resolve/blocklet/<id>` →\n * {owner, path} so the CF serve path can read the published files back.\n * Backed by the SAME D1 (CF) / in-memory (Node) store as the share/domain\n * resolve entries — see blocklet-hook.ts. Absent → blocklet registration off.\n */\n blockletResolver?: DIDSpaceResolver;\n /**\n * PLAINTEXT space-owner DID recorded by the blocklet hook as the resolve\n * entry's `owner` (so the serve path can reconstruct the space via\n * `getUserSpace(owner)`). Unlike `shareOwnerDid` (the de-id storage scope),\n * this MUST be the plaintext DID — the serve path re-derives the scope from\n * it. Defaults to `did`, which is correct for whole-space providers; instance\n * fragments (`did = instanceId`) MUST pass the user's plaintext DID here.\n */\n blockletOwnerDid?: string;\n /**\n * Upload plane (design §7 / §15). Injected by the runtime on the user-facing\n * space so the `prepare/commit/abort-upload` actions can mint grants + persist\n * sessions. All optional: when `sessionStore` is absent the actions report\n * unavailable; when `signer` is absent (Node, fallback-only) prepare returns\n * `grant: null` and the client falls back to batchWrite.\n */\n signer?: PresignSigner;\n uploadSessionStore?: UploadSessionStore;\n /**\n * The de-identified storage scope (= the owning DIDSpace's `this._scope`)\n * written into `upload_sessions.scope` and re-checked on commit for session\n * ownership isolation (§9 / §10). NEVER a plaintext user DID.\n */\n uploadScope?: string;\n}\n\n/**\n * AFS entry `id` is the basename (last path segment), matching AFSFS/AFSJSON —\n * NOT the full path. `AFSBaseProvider.buildEntry` defaults `id` to the full\n * normalized path, so the list handlers below MUST pass an explicit basename id;\n * otherwise consumers that labelize `entry.id` (e.g. the auto-surface settings\n * tabs) render the whole path instead of \"Input\"/\"Sort\"/\"View\". The stat handler\n * already does this (`afsPath.split(\"/\").pop()`); the list handlers were the gap.\n */\nfunction basenameId(path: string): string {\n return path.split(\"/\").filter(Boolean).pop() ?? \"/\";\n}\n\n/**\n * Provider-reserved meta keys (planning/agent-hub/metadata-foundation.md §\n * 白名单). These are computed by DID Space at write time and overwrite\n * anything the application tries to put under the same name. The application\n * may write any OTHER key into `payload.meta` and it'll be persisted to the\n * `entries.metadata` column.\n *\n * Note: `ctime / mtime` are NOT in `entry.meta` (they live at AFSEntry top\n * level as `createdAt / updatedAt`), so they're not in the reserved set —\n * the application can write `meta.ctime` and it'll be persisted as just\n * another application field, NOT conflated with the entry's timestamp.\n */\nconst PROVIDER_RESERVED_META_KEYS: ReadonlySet<string> = new Set([\n \"kind\",\n \"size\",\n \"cid\",\n \"mimeType\",\n]);\n\n/**\n * Strip provider-reserved keys from a write payload's meta, leaving only the\n * application-owned fields that should go to `entries.metadata`.\n * Returns undefined when nothing application-owned remains (avoids storing\n * `{}` blobs).\n */\nfunction extractApplicationMeta(\n meta: Record<string, unknown> | null | undefined,\n): Record<string, unknown> | undefined {\n if (!meta) return undefined;\n const out: Record<string, unknown> = {};\n let any = false;\n for (const [k, v] of Object.entries(meta)) {\n if (PROVIDER_RESERVED_META_KEYS.has(k)) continue;\n out[k] = v;\n any = true;\n }\n return any ? out : undefined;\n}\n\n/**\n * Loose upper bound on serialized application metadata (did-space-metadata\n * NEEDS DECISION 3). `metadata` rides `z.record(z.unknown())` and is NOT\n * digest-checked (it's application data, not bytes — design §5), so the wire\n * imposes no size limit of its own. Aside's real metadata is tiny (a few ISO\n * timestamps, ~50B), but a malicious / buggy client could otherwise stuff a\n * huge JSON blob straight into the D1 `metadata` column (row-size / write-\n * amplification risk, cf. the D1 burn-through lesson). 64KB is far above any\n * legitimate use yet blocks abuse. Shared by the two new server ingress points\n * (batchWrite + upload-plane commit) so the threshold can't drift.\n */\nconst METADATA_MAX_BYTES = 64 * 1024;\n\n/**\n * Reject abusively large application metadata gracefully (an `AFSValidationError`,\n * which afs-rpc maps to 400 — never an uncaught 500). Call AFTER\n * `extractApplicationMeta` so the reserved-key strip can't be gamed to dodge\n * the bound. No-op for absent metadata.\n */\nfunction assertMetadataSize(meta: Record<string, unknown> | undefined, path: string): void {\n if (!meta) return;\n const bytes = new TextEncoder().encode(JSON.stringify(meta)).length;\n if (bytes > METADATA_MAX_BYTES) {\n throw new AFSValidationError(\n `Application metadata for ${path} is ${bytes} bytes, over the ${METADATA_MAX_BYTES}-byte limit`,\n );\n }\n}\n\n/** Plain JSON object (not array, not null) — the deep-merge branch. */\nfunction isPlainObject(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n\n/** An incoming scalar that carries no information and must never overwrite. */\nfunction isEmptyScalar(v: unknown): boolean {\n return v === undefined || v === null || v === \"\";\n}\n\n/** Union two arrays, dedup by structural identity, existing entries first. */\nfunction unionArrays(existing: unknown[], incoming: unknown[]): unknown[] {\n const seen = new Set(existing.map((x) => JSON.stringify(x)));\n const out = [...existing];\n for (const item of incoming) {\n const key = JSON.stringify(item);\n if (!seen.has(key)) {\n out.push(item);\n seen.add(key);\n }\n }\n return out;\n}\n\n/**\n * Merge incoming item content into the existing item on a duplicate-key write\n * (#492). A re-save is ADDITIVE and must never DEGRADE the stored item:\n *\n * - keys in `immutable` (always `createdAt`, plus caller-supplied lifecycle\n * fields like `status`) keep the existing value — a re-clip never resets an\n * archived item or rewrites its creation time;\n * - arrays union-dedup (existing first) so tags / collections accrete;\n * - plain objects deep-merge recursively, so a partial re-clip of `og` /\n * `content` keeps fields the new capture omitted;\n * - scalars take the incoming value EXCEPT empty ones (`undefined` / `null` /\n * `\"\"`), which keep the existing value — a bookmarklet that failed to grab a\n * title must not wipe the good title already saved;\n * - type conflicts (array↔scalar, object↔scalar) take the incoming value.\n */\nfunction mergeItemContent(\n existing: Record<string, unknown>,\n incoming: Record<string, unknown>,\n immutable: ReadonlySet<string> = new Set([\"createdAt\"]),\n): Record<string, unknown> {\n const merged: Record<string, unknown> = { ...existing };\n for (const [k, v] of Object.entries(incoming)) {\n if (immutable.has(k)) continue;\n const cur = merged[k];\n if (Array.isArray(v) && Array.isArray(cur)) {\n merged[k] = unionArrays(cur, v);\n } else if (isPlainObject(v) && isPlainObject(cur)) {\n // Nested objects deep-merge; immutable applies at every depth.\n merged[k] = mergeItemContent(cur, v, immutable);\n } else if (isEmptyScalar(v)) {\n // Skip: never store/overwrite with an empty value.\n } else {\n merged[k] = v;\n }\n }\n return merged;\n}\n\nexport class DIDSpaceProvider extends AFSBaseProvider {\n static manifest(): ProviderManifest {\n return {\n name: \"did-space\",\n description:\n \"DID-scoped persistent storage with CID-based content deduplication.\\n- Per-user data isolation via DID prefix\\n- Content-addressable deduplication (CID v1, raw codec + SHA-256)\\n- R2 for objects, D1 for tree index\",\n uriTemplate: \"did-space://{did}/{path*}\",\n category: \"storage\",\n schema: z.object({ did: z.string(), path: z.string().optional() }),\n tags: [\"did\", \"storage\", \"cid\", \"dedup\", \"cloud\"],\n capabilityTags: [\"read-write\", \"crud\", \"search\", \"auth:token\"],\n security: { riskLevel: \"sandboxed\", resourceAccess: [] },\n capabilities: { filesystem: { read: true, write: true } },\n noPerEntryActions: true,\n };\n }\n\n static treeSchema(): ProviderTreeSchema {\n return {\n operations: [\"list\", \"read\", \"write\", \"delete\", \"search\", \"stat\", \"explain\"],\n tree: {\n \"/\": { kind: \"did-space:root\" },\n \"/{path+}\": { kind: \"did-space:file\" },\n },\n auth: { type: \"custom\" },\n bestFor: [\"user files\", \"persistent storage\", \"content-addressed data\"],\n notFor: [\"large binary blobs\", \"real-time streaming\"],\n };\n }\n\n readonly name: string;\n readonly description?: string;\n readonly accessMode: AFSAccessMode;\n readonly did: string;\n private objectStore: ObjectStore;\n private treeIndex: TreeIndex;\n readonly gcQueue?: GcQueue;\n /** See `DIDSpaceProviderOptions.deviceId`. Read by writeHandler/deleteHandler. */\n readonly deviceId: string;\n /** Optional ShareResolver for .share reconcile hook (Phase 0.4) */\n private readonly shareResolver?: ShareResolver;\n /** See `DIDSpaceProviderOptions.shareOwnerDid` / `shareTreePrefix`. */\n private readonly shareOwnerDid?: string;\n private readonly shareTreePrefix?: string;\n /** See `DIDSpaceProviderOptions.blockletResolver` / `blockletOwnerDid` (#674). */\n private readonly blockletResolver?: DIDSpaceResolver;\n private readonly blockletOwnerDid?: string;\n /** Upload plane deps (design §7). See `DIDSpaceProviderOptions`. */\n private readonly signer?: PresignSigner;\n private readonly uploadSessionStore?: UploadSessionStore;\n private readonly uploadScope?: string;\n\n constructor(options: DIDSpaceProviderOptions) {\n super();\n validateId(options.did);\n this.name = options.name || \"did-space\";\n this.description = options.description;\n this.accessMode = options.accessMode ?? \"readwrite\";\n this.did = normalizeId(options.did);\n this.objectStore = options.objectStore;\n this.treeIndex = options.treeIndex;\n this.gcQueue = options.gcQueue;\n this.deviceId = options.deviceId ?? \"server:default\";\n this.shareResolver = options.shareResolver;\n this.shareOwnerDid = options.shareOwnerDid;\n this.shareTreePrefix = options.shareTreePrefix;\n this.blockletResolver = options.blockletResolver;\n this.blockletOwnerDid = options.blockletOwnerDid;\n this.signer = options.signer;\n this.uploadSessionStore = options.uploadSessionStore;\n this.uploadScope = options.uploadScope;\n }\n\n // ========== Path helpers ==========\n\n /** Convert AFS path to tree-index path (strip leading /) */\n private treePath(afsPath: string): string {\n // Defense-in-depth: key invariants must hold even if AFS core is bypassed\n if (afsPath.includes(\"\\0\")) throw new Error(\"Null byte in path\");\n // Segment-boundary check: only reject \"..\" as an exact path segment (e.g. \"/foo/../bar\"),\n // not as a substring of a valid name (e.g. \"/foo/..hidden\").\n if (/(?:^|\\/)\\.\\.(?:\\/|$)/.test(afsPath)) throw new Error(\"Path traversal in path\");\n return afsPath.replace(/^\\/+/, \"\");\n }\n\n /** Convert AFS path to tree-index prefix for directory listing */\n private treeListPrefix(afsPath: string): string {\n if (afsPath === \"/\") return \"\";\n return `${this.treePath(afsPath)}/`;\n }\n\n /**\n * Remap a write/delete into the arguments the .share reconcile hook expects.\n * On a whole-space provider this is identity. On a prefixed instance-fragment\n * provider (`shareTreePrefix` set) it restores the WHOLE-TREE decl path and\n * keys the share to the space owner (`shareOwnerDid`), so reconcile stores the\n * same `owner_did` + full `decl_path` the public serving path resolves by.\n */\n private shareHookArgs(\n afsPath: string,\n treePath: string,\n ): { afsPath: string; treePath: string; ownerDid: string } {\n const fullTreePath = this.shareTreePrefix ? joinURL(this.shareTreePrefix, treePath) : treePath;\n return {\n afsPath: this.shareTreePrefix ? `/${fullTreePath}` : afsPath,\n treePath: fullTreePath,\n ownerDid: this.shareOwnerDid ?? this.did,\n };\n }\n\n /**\n * Remap a write/delete into the arguments the blocklet hook expects. Same\n * whole-tree path restoration as {@link shareHookArgs}, but the recorded\n * `ownerDid` is the PLAINTEXT space owner (`blockletOwnerDid`), not the de-id\n * scope — the serve path re-derives the storage scope from the plaintext DID.\n */\n private blockletHookArgs(\n afsPath: string,\n treePath: string,\n ): { afsPath: string; treePath: string; ownerDid: string } {\n const fullTreePath = this.shareTreePrefix ? joinURL(this.shareTreePrefix, treePath) : treePath;\n return {\n afsPath: this.shareTreePrefix ? `/${fullTreePath}` : afsPath,\n treePath: fullTreePath,\n ownerDid: this.blockletOwnerDid ?? this.did,\n };\n }\n\n private objectKey(cid: string): string {\n // CID format assertion: computeCID() always returns base32lower (starts with 'b')\n // or base58btc (starts with 'z'); both use [a-zA-Z0-9] charset, typical length 46-59 chars\n if (!/^[bz][a-zA-Z0-9]{20,100}$/.test(cid)) {\n throw new Error(`Invalid CID format: ${cid.slice(0, 30)}`);\n }\n return `objects/${cid}`;\n }\n\n private async isDirectory(path: string): Promise<boolean> {\n if (path === \"/\") return true;\n return this.treeIndex.hasChildren(this.treeListPrefix(path));\n }\n\n /** Collect all CIDs under a prefix for GC queuing before bulk delete. */\n private async collectCIDsByPrefix(prefix: string): Promise<string[]> {\n const cids: string[] = [];\n let cursor: string | undefined;\n do {\n const result = await this.treeIndex.listEntries(prefix, { limit: 1000, cursor });\n for (const e of result.entries) {\n if (e.cid) cids.push(e.cid);\n }\n cursor = result.hasMore ? result.cursor : undefined;\n } while (cursor);\n return cids;\n }\n\n // ========== Meta ==========\n\n @Meta(\"/:path*\")\n async readMeta(ctx: RouteContext<{ path?: string }>): Promise<AFSEntry | undefined> {\n const afsPath = joinURL(\"/\", ctx.params.path ?? \"\");\n\n if (afsPath === \"/\") {\n const childrenCount = await this.treeIndex.countChildren(this.treeListPrefix(\"/\"));\n return this.buildEntry(joinURL(afsPath, \".meta\"), {\n content: { type: \"directory\", path: \"/\" },\n meta: { kind: \"did-space:root\", childrenCount } as AFSEntryMetadata,\n });\n }\n\n // readMeta is HEAD-like — it synthesizes its own metadata payload and never\n // reads entry.content, so skip projecting the inline bytes (projection audit).\n const entry = await this.treeIndex.get(this.treePath(afsPath), { includeContent: false });\n if (entry) {\n return this.buildEntry(joinURL(afsPath, \".meta\"), {\n content: { type: \"file\", path: afsPath, size: entry.size, cid: entry.cid },\n meta: {\n kind: \"did-space:file\",\n size: entry.size,\n cid: entry.cid,\n mimeType: entry.mimeType,\n } as AFSEntryMetadata,\n createdAt: new Date(entry.ctime),\n updatedAt: new Date(entry.mtime),\n });\n }\n\n if (await this.isDirectory(afsPath)) {\n const childrenCount = await this.treeIndex.countChildren(this.treeListPrefix(afsPath));\n return this.buildEntry(joinURL(afsPath, \".meta\"), {\n content: { type: \"directory\", path: afsPath },\n meta: { kind: \"did-space:directory\", childrenCount } as AFSEntryMetadata,\n });\n }\n\n throw new AFSNotFoundError(afsPath);\n }\n\n // ========== List ==========\n\n /**\n * Override to implement the `maxDepth: -1` snapshot contract.\n *\n * When called with `maxDepth: -1`, collects ALL file entries under `path`\n * using cursor-based pagination through the treeIndex and returns them in\n * a single `AFSListResult` with `meta.cursor = String(manifestSeq)` so\n * `SyncEngine.fullResync()` can advance `cloudSeq` correctly.\n *\n * > 10_000 entries → sets `meta.truncated: true` (HTTP 200, SyncEngine\n * throws `ManifestTooLargeError`).\n *\n * All other options fall through to `super.list()` → `listHandler`.\n */\n override async list(path: string, options?: AFSListOptions): Promise<AFSListResult> {\n if (options?.maxDepth !== -1) {\n return super.list(path, options);\n }\n\n // Decision #3: .changelog does not support maxDepth=-1\n const normPath = path.startsWith(\"/\") ? path.slice(1) : path;\n if (normPath === \".changelog\" || normPath.startsWith(\".changelog/\")) {\n throw new AFSValidationError(\n \".changelog path does not support maxDepth=-1 (changelog uses cursor-based incremental access)\",\n );\n }\n\n // Mutex: cannot combine maxDepth=-1 with cursor/limit/offset\n if (\n options.cursor !== undefined ||\n (options.limit !== undefined && Number.isFinite(options.limit)) ||\n (options.offset !== undefined && Number.isFinite(options.offset))\n ) {\n throw new AFSValidationError(\n \"list with maxDepth=-1 cannot be combined with cursor, limit, or offset\",\n );\n }\n\n const SNAPSHOT_MAX_ENTRIES = 10_000;\n const prefix = this.treeListPrefix(path);\n const allEntries: AFSEntry[] = [];\n let cursor: string | undefined;\n\n do {\n const result = await this.treeIndex.listEntries(prefix, {\n limit: LIST_MAX_LIMIT,\n cursor,\n });\n\n for (const treeEntry of result.entries) {\n if (allEntries.length >= SNAPSHOT_MAX_ENTRIES) {\n return {\n data: allEntries,\n meta: {\n truncated: true,\n ...(orderByRequested(options.orderBy) ? { orderByIgnored: true as const } : {}),\n },\n };\n }\n // Canonical sync wire (T1.2): cid emitted at BOTH top-level (TS engine +\n // AUP/UI read it) AND extra.cid (Swift/Kotlin read it) — additive, so no\n // cross-phase lockstep. Single-sourced in changelog-schema.ts.\n allEntries.push(\n this.buildEntry(`/${treeEntry.path}`, {\n id: basenameId(treeEntry.path),\n meta: serializeManifestEntry({\n cid: treeEntry.cid,\n size: treeEntry.size,\n mtime: treeEntry.mtime,\n mimeType: treeEntry.mimeType,\n }) as AFSEntryMetadata,\n createdAt: new Date(treeEntry.ctime),\n updatedAt: new Date(treeEntry.mtime),\n }),\n );\n }\n\n cursor = result.hasMore ? result.cursor : undefined;\n } while (cursor);\n\n const manifestSeq = await this.treeIndex.getMaxSeq();\n const snapshotMeta: AFSListResult[\"meta\"] = { cursor: String(manifestSeq) };\n // Snapshot order is manifest order (sync semantics) — a requested\n // orderBy is surfaced as ignored, never silently dropped.\n if (orderByRequested(options.orderBy)) snapshotMeta.orderByIgnored = true;\n return { data: allEntries, meta: snapshotMeta };\n }\n\n @List(\"/:path*\", { handleDepth: true })\n async listHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSListResult> {\n const afsPath = ctx.params.path ? `/${ctx.params.path}` : \"/\";\n const options = ctx.options as {\n limit?: number;\n maxDepth?: number;\n offset?: number;\n cursor?: string;\n orderBy?: unknown;\n includeContent?: boolean;\n includeChildrenCounts?: boolean;\n };\n const includeContent = options?.includeContent === true;\n const includeChildrenCounts = options?.includeChildrenCounts === true;\n\n // Provider-side orderBy validation (core whitelist + key cap 3). The\n // TreeIndex's own whitelist-throw stays internal — user input can never\n // reach it: invalid/over-cap/malformed specs degrade to the default\n // order with meta.orderByIgnored (never-throw contract).\n const orderRequested = orderByRequested(options?.orderBy);\n const orderBy: OrderByTuple[] | undefined =\n orderRequested && isValidOrderBy(options?.orderBy) ? options.orderBy : undefined;\n /** Merge the no-silent-drop flag into a result when ordering was requested but not applied. */\n const flagIgnored = (result: AFSListResult): AFSListResult =>\n orderRequested ? { ...result, meta: { ...result.meta, orderByIgnored: true } } : result;\n\n // Phase 0.5: .shares/ virtual path routing — orderBy unsupported (flag, route untouched).\n // Only WHOLE-SPACE providers own this view; instance fragments (shareTreePrefix\n // set) reconcile .share writes but never expose `.shares/` (no new read surface).\n const sharesMatch = matchSharesVirtualPath(afsPath);\n if (sharesMatch && this.shareResolver && !this.shareTreePrefix) {\n const handler = new ShareVirtualHandler(this.shareResolver, this.did);\n const { list } = await handler.list(sharesMatch);\n return flagIgnored({ data: list });\n }\n\n // Task 1.9: .changelog + cursor → return changelog rows from treeIndex.\n // Changelog order is seq (sync semantics) — orderBy unsupported (flag).\n const normPath = afsPath.startsWith(\"/\") ? afsPath.slice(1) : afsPath;\n const isChangelog = normPath === \".changelog\" || normPath.startsWith(\".changelog/\");\n if (isChangelog && options?.cursor !== undefined) {\n return flagIgnored(await this.listChangelog(options.cursor, options.limit));\n }\n\n const limit = Math.min(options?.limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n const offset = Math.max(0, Number(options?.offset) || 0);\n const maxDepth = options?.maxDepth ?? 1;\n\n // Collect offset + limit entries so base.ts can apply offset slicing\n const collectLimit = offset + limit;\n\n if (maxDepth === 0) return { data: [] };\n\n const prefix = this.treeListPrefix(afsPath);\n\n if (afsPath !== \"/\") {\n // Existence probe only — the entry's content is never read (projection audit).\n const entry = await this.treeIndex.get(this.treePath(afsPath), { includeContent: false });\n if (!entry) {\n const hasAny = await this.treeIndex.hasChildren(prefix);\n if (!hasAny) {\n throw new AFSNotFoundError(afsPath);\n }\n }\n }\n\n const entries: AFSEntry[] = [];\n if (maxDepth === 1) {\n if (orderBy) {\n const scan = await this.listShallowOrdered(\n prefix,\n collectLimit,\n entries,\n orderBy,\n includeContent,\n );\n if (includeChildrenCounts) await this.fillChildrenCounts(entries);\n return this.withLiveSeq(\n { data: entries, total: await this.shallowTotal(prefix, scan) },\n prefix,\n isChangelog,\n );\n }\n const scan = await this.listShallow(prefix, collectLimit, entries, undefined, includeContent);\n if (includeChildrenCounts) await this.fillChildrenCounts(entries);\n // requested but invalid/over-cap → default order + flag\n return this.withLiveSeq(\n flagIgnored({ data: entries, total: await this.shallowTotal(prefix, scan) }),\n prefix,\n isChangelog,\n );\n }\n // Deep (maxDepth > 1) ordering is ambiguous (Decision 5: shallow only).\n // No `total` here: a deep total would need a bounded-depth subtree count\n // the index doesn't expose; deep listings keep the legacy truncation\n // behavior until a consumer actually needs deep pagination.\n await this.listDeep(afsPath, prefix, collectLimit, maxDepth, entries, includeContent);\n return flagIgnored({ data: entries });\n }\n\n /**\n * True direct-children total for a shallow listing.\n *\n * AFSListResult contract (`packages/core/src/type.ts`): absent `total`\n * means \"data IS the complete result\" — so a handler that truncates its\n * collection MUST report `total`, or every consumer downstream (base.ts\n * pagination, afs-list pager) mistakes the page for the whole set.\n *\n * Cost model (D1: per-query round-trips dominate): `listShallow` scans\n * the index in LIST_MAX_LIMIT batches and keeps counting rows past the\n * build cap, so when the cursor drained (directories ≤ LIST_MAX_LIMIT\n * children — the common case) the scan itself yields the exact total:\n * ZERO extra queries. Only a directory truncated mid-cursor (> 1000\n * children) pays ONE COUNT round-trip (same `countChildren(prefix)`\n * call and parent-key format `readMeta` already relies on).\n */\n private async shallowTotal(prefix: string, scan: ShallowScan): Promise<number> {\n if (scan.exhausted) return scan.seen;\n return this.treeIndex.countChildren(prefix);\n }\n\n /**\n * Attach the per-prefix watermark `version` as the result's top-level\n * `liveSeq` (Live Update Resilience §4 / 0a'). Read ONE row via the\n * TreeIndex — O(1), independent of changelog history/global write volume.\n *\n * - Skipped for `.changelog` listings (sync-internal, no live-update scope).\n * - Skipped when the index has no `getPrefixWatermark` (rollout) or reports\n * no watermark key for the path (`null` — no collection root): the\n * consumer then falls back to full re-list on the next edge/poll, still\n * correct.\n * - A valid-but-never-written collection root reports `\"0\"` so consumers\n * baseline at 0 instead of conservatively refetching every poll tick on a\n * read-only collection (the first write bumps to 1 > 0 and is detected).\n * - The value is prefix-LOCAL (only this collection root's write count), so\n * it never leaks another blocklet's timing (invariant I3).\n */\n private async withLiveSeq(\n result: AFSListResult,\n prefix: string,\n isChangelog: boolean,\n ): Promise<AFSListResult> {\n if (isChangelog || !this.treeIndex.getPrefixWatermark) return result;\n const version = await this.treeIndex.getPrefixWatermark(prefix);\n if (version != null) result.liveSeq = String(version);\n return result;\n }\n\n /**\n * Shallow listing with a VALID orderBy (did-space-sorting Phase 3).\n *\n * - Single tuple → forwarded to the TreeIndex (`listChildren` orders\n * natively over the (scope,parent,col,name) indexes; keyset cursor\n * pages stay globally ordered, so collecting offset+limit entries is\n * the correct order-before-pagination slice).\n * - 2-3 tuples → the index can order by one column only, so collect the\n * FULL child set and apply the canonical core sort before truncation\n * (order → offset → limit still holds).\n */\n private async listShallowOrdered(\n prefix: string,\n collectLimit: number,\n entries: AFSEntry[],\n orderBy: OrderByTuple[],\n includeContent = false,\n ): Promise<ShallowScan> {\n if (orderBy.length === 1) {\n const [field, order] = orderBy[0]!;\n return this.listShallow(\n prefix,\n collectLimit,\n entries,\n { orderBy: field, order },\n includeContent,\n );\n }\n const all: AFSEntry[] = [];\n await this.listShallow(prefix, Number.MAX_SAFE_INTEGER, all, undefined, includeContent);\n const { entries: sorted } = orderEntries(all, orderBy);\n entries.push(...sorted.slice(0, collectLimit));\n // The multi-tuple sort collected the FULL child set — total is free.\n return { exhausted: true, seen: all.length };\n }\n\n private async listShallow(\n prefix: string,\n limit: number,\n entries: AFSEntry[],\n order?: { orderBy: TreeIndexListOptions[\"orderBy\"]; order: \"asc\" | \"desc\" },\n includeContent = false,\n ): Promise<ShallowScan> {\n let cursor: string | undefined;\n let seen = 0;\n\n do {\n const result = await this.treeIndex.listChildren(prefix, {\n limit: LIST_MAX_LIMIT,\n cursor,\n includeContent,\n ...(order ?? {}),\n });\n\n // Count every fetched row even past the build cap — the batch is\n // already in memory, and when the cursor drains `seen` IS the\n // directory's exact child count, sparing shallowTotal a COUNT\n // round-trip (on D1, per-query latency dominates).\n seen += result.entries.length;\n\n for (const child of result.entries) {\n if (entries.length >= limit) continue; // build cap reached — count only\n\n const isDir = child.path.endsWith(\"/\");\n if (isDir) {\n // Display path: strip trailing \"/\" and prepend \"/\"\n const displayPath = `/${child.path.slice(0, -1)}`;\n entries.push(\n this.buildEntry(displayPath, {\n id: basenameId(displayPath),\n meta: {\n kind: \"did-space:directory\",\n // -1 = \"has children, count unknown\" (the conformance-\n // documented sentinel listDeep already uses). Exact counts\n // are OPT-IN via AFSListOptions.includeChildrenCounts —\n // fillChildrenCounts patches the final page — so plain lists\n // (sync, feeds, polling) pay ZERO counting cost. The old\n // always-on countChildrenGrouped(prefix) scanned EVERY\n // descendant under the listed prefix per list and exhausted\n // the D1 free tier (~100M rows_read/day) once the aside user\n // space grew past ~1k dirs.\n childrenCount: -1,\n // Surface the row's size so AFS-level ordering sees exactly\n // the value the index sorted by (missing ⇒ \"sorts last\"\n // would diverge from the row's position).\n size: child.size,\n } as AFSEntryMetadata,\n createdAt: new Date(child.ctime),\n updatedAt: new Date(child.mtime),\n }),\n );\n } else {\n entries.push(\n this.buildEntry(`/${child.path}`, {\n id: basenameId(child.path),\n // includeContent (§2.I): attach the inline copy ONLY after\n // re-verifying it hashes to the cid — a failed check is a\n // best-effort miss (caller read-fallback), never bad bytes.\n ...(includeContent && (await this.verifiedInline(child)) !== null\n ? { content: child.content }\n : {}),\n meta: {\n kind: \"did-space:file\",\n cid: child.cid,\n size: child.size,\n mimeType: child.mimeType,\n } as AFSEntryMetadata,\n createdAt: new Date(child.ctime),\n updatedAt: new Date(child.mtime),\n }),\n );\n }\n }\n\n cursor = result.hasMore ? result.cursor : undefined;\n } while (cursor && entries.length < limit);\n\n return { exhausted: cursor === undefined, seen };\n }\n\n /**\n * Patch EXACT `meta.childrenCount` onto the directory entries of a\n * collected shallow page — the opt-in half of the two-tier childrenCount\n * contract (`AFSListOptions.includeChildrenCounts`; default tier is the\n * `-1` sentinel stamped by listShallow). Page-bounded by construction:\n * only the dirs actually collected are counted, ONE `countChildrenMany`\n * round-trip (per-dir `countChildren` fallback for indexes without it),\n * so the cost is Σ direct children of the page's dirs — never the\n * whole-subtree scan the retired `countChildrenGrouped` performed.\n */\n private async fillChildrenCounts(entries: AFSEntry[]): Promise<void> {\n const dirs = entries.filter(\n (e) => (e.meta as AFSEntryMetadata | undefined)?.kind === \"did-space:directory\",\n );\n if (dirs.length === 0) return;\n // Display path \"/a/b\" → the trailing-slash index key \"a/b/\" listChildren\n // yields (and countChildren/countChildrenMany expect).\n const keyOf = (e: AFSEntry) => `${this.treePath(e.path)}/`;\n if (this.treeIndex.countChildrenMany) {\n const counts = await this.treeIndex.countChildrenMany(dirs.map(keyOf));\n for (const e of dirs) {\n (e.meta as AFSEntryMetadata).childrenCount = counts.get(keyOf(e)) ?? 0;\n }\n return;\n }\n for (const e of dirs) {\n (e.meta as AFSEntryMetadata).childrenCount = await this.treeIndex.countChildren(keyOf(e));\n }\n }\n\n private async listDeep(\n afsBasePath: string,\n prefix: string,\n limit: number,\n maxDepth: number,\n entries: AFSEntry[],\n includeContent = false,\n ): Promise<void> {\n const prefixDepth = afsBasePath === \"/\" ? 0 : afsBasePath.split(\"/\").filter(Boolean).length;\n const seenDirs = new Set<string>();\n let cursor: string | undefined;\n\n do {\n const result = await this.treeIndex.listEntries(prefix, {\n limit: LIST_MAX_LIMIT,\n cursor,\n includeContent,\n });\n\n for (const treeEntry of result.entries) {\n if (entries.length >= limit) return;\n\n const rest = treeEntry.path.slice(prefix.length);\n const parts = rest.split(\"/\").filter(Boolean);\n\n for (let i = 0; i < parts.length - 1; i++) {\n if (i + 1 > maxDepth) break;\n const dirKey = prefix + parts.slice(0, i + 1).join(\"/\");\n if (!seenDirs.has(dirKey)) {\n seenDirs.add(dirKey);\n entries.push(\n this.buildEntry(`/${dirKey}`, {\n id: basenameId(dirKey),\n meta: { kind: \"did-space:directory\", childrenCount: -1 } as AFSEntryMetadata,\n }),\n );\n }\n }\n\n const path = `/${treeEntry.path}`;\n const pathDepth = path.split(\"/\").filter(Boolean).length;\n if (pathDepth - prefixDepth <= maxDepth) {\n entries.push(\n this.buildEntry(path, {\n id: basenameId(path),\n ...(includeContent && (await this.verifiedInline(treeEntry)) !== null\n ? { content: treeEntry.content }\n : {}),\n meta: {\n kind: \"did-space:file\",\n cid: treeEntry.cid,\n size: treeEntry.size,\n mimeType: treeEntry.mimeType,\n } as AFSEntryMetadata,\n createdAt: new Date(treeEntry.ctime),\n updatedAt: new Date(treeEntry.mtime),\n }),\n );\n }\n }\n\n cursor = result.hasMore ? result.cursor : undefined;\n } while (cursor && entries.length < limit);\n }\n\n /**\n * Task 1.9: list changelog rows starting after `cursor` (seq number).\n * Returns rows as AFSEntry objects + meta.cursor pointing to the last row's seq.\n */\n private async listChangelog(cursor: string, limit?: number): Promise<AFSListResult> {\n const sinceSeq = Number(cursor) || 0;\n const effectiveLimit = Math.min(limit || LIST_MAX_LIMIT, LIST_MAX_LIMIT);\n\n // Phase 1 compaction watermark check: reject cursors that fall below the\n // compacted watermark so clients know they must full-resync.\n const watermark = (await this.treeIndex.getCompactedBelowSeq?.()) ?? 0;\n if (watermark > 0 && sinceSeq < watermark) {\n throw new AFSCompactedError(\"/.changelog\", String(watermark));\n }\n\n // Single changelog-read contract across all backends (Memory / D1 /\n // SQLite / Prefixed). Phase 1: replaces the old getChangelogSnapshot\n // duck-type + D1 empty-stub (formerly index.ts:693) that silently broke\n // incremental sync on every non-Memory backend.\n const changelog = await this.treeIndex.getChangelogSince(sinceSeq, effectiveLimit);\n\n // Canonical sync wire (T1.1): all protocol fields live under `meta.extra`\n // (the only position all four runtimes decode — design §4). `path` → the\n // serializer's `originalPath`. Single-sourced in changelog-schema.ts.\n const entries: AFSEntry[] = changelog.entries.map((row) =>\n this.buildEntry(`/.changelog/${row.seq}`, {\n content: null,\n meta: {\n kind: CHANGELOG_ROW_KIND,\n extra: serializeChangelogEntry(row),\n } as AFSEntryMetadata,\n }),\n );\n\n return {\n data: entries,\n meta: {\n // cursor = max inner seq scanned (NOT the last returned entry's seq) so\n // a prefix-filtered empty page still advances the cursor — the client\n // never re-requests the same window. See PrefixedTreeIndex.getChangelogSince.\n cursor: String(changelog.cursor),\n hasMore: changelog.hasMore,\n },\n };\n }\n\n // ========== Read ==========\n\n /**\n * Promote write + delete to the object form so callers can discover the\n * `ifMatch` sub-capability (CLAUDE.md \"Sub-capability schema\"). The base impl\n * (base.ts) returns plain booleans; without this override the if-match\n * conformance suite's `getCapabilityFeature(\"write\",\"ifMatch\")` reads nothing\n * and the suite skips. Mirrors AFSFS's override (fs/src/index.ts).\n */\n protected getOperationsDeclaration(): OperationsDeclaration {\n const ops = super.getOperationsDeclaration();\n const writeSupported =\n typeof ops.write === \"boolean\" ? ops.write : ops.write?.supported === true;\n if (writeSupported) {\n // tree-* modes are implemented by AFSBaseProvider's write() dispatch,\n // which runs BEFORE the router reaches our @Write handler — they work\n // on any JSON file in the space (CAS content is JSON text, the base\n // R-M-W parse→modify→replace round-trip composes with CAS writes).\n // Declaring them here is the TEST gate, not the feature gate: the\n // feature-gated conformance suites only run against providers that\n // declare, so an undeclared-but-working mode would be silently\n // unprotected.\n //\n // Known double-check (accepted): _executeTreeWrite carries the read's\n // version as ifMatch into the inner write, and our writeHandler\n // (index.ts ifMatch block) re-checks the CID itself. The two checks\n // are equivalent (version IS the cid); the cost is one extra index\n // read per tree-* write. Not worth deduplicating.\n ops.write = {\n supported: true,\n features: {\n ifMatch: true,\n treeMerge: true,\n treeToggle: true,\n treeIncrement: true,\n treeListAdd: true,\n treeListRemove: true,\n // afs-rpc-batch P3: NATIVE module-level batchWrite/batchDelete\n // (deliberately distinct from the auto-derived batchWrite\n // capability bit — 声明即配套, gated by the conformance suite).\n batchPushdown: true,\n },\n };\n }\n const deleteSupported =\n typeof ops.delete === \"boolean\" ? ops.delete : ops.delete?.supported === true;\n if (deleteSupported) {\n ops.delete = { supported: true, features: { ifMatch: true } };\n }\n // did-space is a handleDepth provider — the base.ts fallback never sorts\n // its pages, so orderBy is implemented natively (Phase 3) and declared\n // here. base.list keys its no-silent-drop merge off this declaration.\n const listSupported = typeof ops.list === \"boolean\" ? ops.list : ops.list?.supported === true;\n if (listSupported) {\n // includeContent (settings-layering §2.I): list entries MAY carry their\n // bytes inline (write-through rows). BEST-EFFORT by contract — entries\n // without an inline copy are legal, callers read-fallback.\n // (Dir-per-record content now travels via the query standard action's\n // doc form — the contentFile list flag was deleted in T4.3.)\n ops.list = {\n supported: true,\n features: { orderBy: true, includeContent: true },\n };\n }\n return ops;\n }\n\n @Read(\"/.meta/.capabilities\")\n async readCapabilities(_ctx: RouteContext): Promise<AFSEntry | undefined> {\n const operations = this.getOperationsDeclaration();\n // Collection query (afs-collection-query Phase 1): declared ONLY when the\n // backing index implements the engine — a declaration the runtime cannot\n // honor would violate the strict \"declare ⇒ execute\" contract. Consumers\n // probe per-mount via this manifest's standardActions (design §3.4 —\n // never the aggregated root view).\n const queryable = typeof this.treeIndex.query === \"function\";\n if (queryable) operations.query = true;\n const manifest: CapabilitiesManifest = {\n schemaVersion: 1,\n provider: this.name,\n description: this.description || \"DID-scoped persistent storage with CID-based deduplication\",\n tools: [],\n actions: [],\n operations,\n ...(queryable\n ? {\n standardActions: [\n collectionQueryStandardAction({\n doc: true,\n groupBy: true,\n annotate: true,\n aggregate: true,\n }),\n ],\n }\n : {}),\n };\n\n return {\n id: \"/.meta/.capabilities\",\n path: \"/.meta/.capabilities\",\n content: manifest,\n meta: { kind: \"afs:capabilities\", operations } as AFSEntryMetadata,\n };\n }\n\n // ========== Collection query (afs-collection-query Phase 1) ==========\n\n /**\n * Typed collection query over a directory of records (design §3.5).\n *\n * - dir-per-record (`spec.doc`): direct child dirs joined with their\n * `<dir>/<doc>` document; file-per-record (no doc): direct child files'\n * inline content is the record.\n * - where/orderBy/pagination/total/groupBy execute inside the TreeIndex\n * engine (SQL or in-memory — lockstep-tested). select + annotate.memberOf\n * are page-level post-processing here, identical across backends.\n * - Strict contract: spec arrives core-validated; provider constraints\n * (single orderBy key, no text) throw AFSValidationError. An index\n * without the engine (e.g. not-yet-migrated backends) throws\n * AFSUnsupportedError — and is never declared in capabilities.\n */\n async query(\n path: string,\n spec: AFSCollectionQuerySpec,\n _options?: AFSQueryOptions,\n ): Promise<AFSCollectionQueryResult> {\n if (!this.treeIndex.query) {\n throw new AFSUnsupportedError(\n \"query\",\n \"Collection query is not supported by this index backend\",\n );\n }\n const afsPath = joinURL(\"/\", path);\n if (this.isVirtualPath(afsPath) || matchSharesVirtualPath(afsPath)) {\n throw new AFSValidationError(\n `Invalid query spec: path: not a queryable collection: ${afsPath}`,\n );\n }\n assertTreeQuerySpec(spec);\n\n const prefix = this.treeListPrefix(afsPath);\n if (afsPath !== \"/\") {\n // Same existence contract as list: a path that is neither a file nor a\n // directory with children is NotFound (empty dirs have no index rows).\n const entry = await this.treeIndex.get(this.treePath(afsPath), { includeContent: false });\n if (!entry && !(await this.treeIndex.hasChildren(prefix))) {\n throw new AFSNotFoundError(afsPath);\n }\n }\n\n const result = await this.treeIndex.query(prefix, spec);\n\n // annotate.memberOf: resolve the reference doc ONCE, build the folded\n // member set, flag each page row (output-only — never affects filtering).\n let memberValues: Set<string> | undefined;\n if (spec.annotate) {\n memberValues = new Set();\n try {\n const ref = await this.read(joinURL(\"/\", spec.annotate.memberOf.doc));\n const parsed = parseRecordText(\n typeof ref.data?.content === \"string\" ? ref.data.content : undefined,\n );\n const raw = resolveFieldPath(parsed, spec.annotate.memberOf.field);\n if (Array.isArray(raw)) {\n for (const v of raw) {\n memberValues.add(typeof v === \"string\" ? v.toLowerCase() : String(v));\n }\n }\n } catch {\n // Missing reference doc ⇒ nothing is a member (empty flags, no error).\n }\n }\n\n const entries: AFSEntry[] = [];\n for (const row of result.rows) {\n entries.push(await this.queryRowToEntry(row, spec, memberValues));\n }\n\n const out: AFSCollectionQueryResult = { entries, total: result.total };\n if (result.cursor) out.cursor = result.cursor;\n if (result.groups) out.groups = result.groups;\n if (result.aggregateGroups) out.aggregateGroups = result.aggregateGroups;\n if (result.seekOffset !== undefined) out.seekOffset = result.seekOffset;\n // Same top-level liveSeq contract as list (review R2-#2): the queried\n // collection root's prefix-local watermark version, for live-update\n // reconcile. Absent when the index has no watermark for the prefix.\n if (this.treeIndex.getPrefixWatermark) {\n const version = await this.treeIndex.getPrefixWatermark(prefix);\n if (version != null) out.liveSeq = String(version);\n }\n return out;\n }\n\n /** Map an engine row to an AFSEntry (mirrors the list handlers' shapes). */\n private async queryRowToEntry(\n row: TreeQueryRow,\n spec: AFSCollectionQuerySpec,\n memberValues?: Set<string>,\n ): Promise<AFSEntry> {\n const isDir = row.kind === \"dir\";\n const displayPath = isDir ? `/${row.path.slice(0, -1)}` : `/${row.path}`;\n\n // cid-verify inline/joined content before surfacing (same best-effort\n // rule as list: a failed check drops content, never returns bad bytes).\n const verifyCid = isDir ? row.contentCid : row.cid;\n const verified =\n row.content !== undefined && verifyCid\n ? await this.verifiedInline({ cid: verifyCid, content: row.content })\n : null;\n\n let content: unknown;\n if (spec.select) {\n content = projectRecordFields(parseRecordText(verified ?? undefined), spec.select);\n } else if (verified !== null) {\n content = verified;\n }\n\n const entry = this.buildEntry(displayPath, {\n id: basenameId(displayPath),\n ...(content !== undefined ? { content } : {}),\n meta: isDir\n ? ({\n // doc-mode: row.metadata is sourced from the JOIN'd file row\n // (tree-query.ts `cf_metadata ?? metadata` mapper), so the\n // dir-row response surfaces the same application metadata the\n // file row would — `createdAt` on `items/{uuid}/item.json`\n // reaches the consumer through `items/{uuid}/`'s dir entry.\n // Application keys spread FIRST so provider-reserved keys win.\n ...(row.metadata ?? {}),\n kind: \"did-space:directory\",\n // Exact child counts would be an N+1 of count queries per page —\n // query rows report \"has children, count unknown\".\n childrenCount: -1,\n size: row.size,\n } as AFSEntryMetadata)\n : ({\n // Application metadata surfaces FIRST so provider-reserved keys\n // (kind/cid/size/mimeType) overlay on top — same precedence as\n // the read path; matches the metadata-foundation Phase 1 contract.\n ...(row.metadata ?? {}),\n kind: \"did-space:file\",\n cid: row.cid,\n size: row.size,\n mimeType: row.mimeType,\n } as AFSEntryMetadata),\n createdAt: new Date(row.ctime),\n updatedAt: new Date(row.mtime),\n });\n\n if (spec.annotate && memberValues) {\n const { by, as } = spec.annotate.memberOf;\n const byValue =\n by === \"$id\" ? row.name : resolveFieldPath(parseRecordText(verified ?? row.content), by);\n const member =\n byValue != null &&\n memberValues.has(typeof byValue === \"string\" ? byValue.toLowerCase() : String(byValue));\n entry._derived = { [as]: member ? \"1\" : \"\" };\n }\n return entry;\n }\n\n @Read(\"/:path*\")\n async readHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSEntry> {\n const afsPath = joinURL(\"/\", ctx.params.path ?? \"\");\n\n // Phase 0.5: .shares/ virtual path routing (whole-space providers only — see listHandler)\n const sharesMatch = matchSharesVirtualPath(afsPath);\n if (sharesMatch && this.shareResolver && !this.shareTreePrefix) {\n const handler = new ShareVirtualHandler(this.shareResolver, this.did);\n const result = await handler.read(sharesMatch);\n if (!result) throw new AFSNotFoundError(afsPath);\n return result.data;\n }\n\n // Task 1.8: .objects/{cid} virtual read — return bytes directly from objectStore.\n const normPath = afsPath.startsWith(\"/\") ? afsPath.slice(1) : afsPath;\n if (normPath.startsWith(\".objects/\")) {\n const cid = normPath.slice(\".objects/\".length);\n // GC plan §4.2 — index-layer read authorization (THE security change).\n // Under the global object pool (Model B) objects are no longer isolated by\n // a per-user key prefix; a caller may read a cid ONLY if THIS view\n // references it. `treeIndex.isReferenced` is view-local (prefix-local for a\n // blocklet provider, whole-scope for the space-root provider), so this is\n // automatically blocklet-fragment-scoped. 404 (not 403) to avoid confirming\n // existence to an unauthorized caller. A malformed/garbage cid is never\n // referenced → NotFound, so this also closes the bad-input path before\n // `objectKey()` would ever throw.\n if (!(await time(\"ds.ref\", () => this.treeIndex.isReferenced(cid)))) {\n throw new AFSNotFoundError(afsPath);\n }\n const obj = await time(\"ds.obj\", () => this.objectStore.get(this.objectKey(cid)));\n if (!obj) throw new AFSNotFoundError(afsPath);\n const bytes = new Uint8Array(await time(\"ds.body\", () => obj.arrayBuffer()));\n return this.buildEntry(afsPath, {\n content: bytes,\n meta: { kind: \"did-space:object\", cid, size: bytes.length } as AFSEntryMetadata,\n });\n }\n\n if (afsPath === \"/\") {\n const childrenCount = await this.treeIndex.countChildren(this.treeListPrefix(\"/\"));\n return this.buildEntry(afsPath, {\n content: `DID Space root for ${this.did} (${childrenCount} entries)`,\n meta: { kind: \"did-space:root\", childrenCount } as AFSEntryMetadata,\n });\n }\n\n // Server-Timing decomposition (ds.* segments): a small-JSON read through\n // this path is exactly ONE indexed D1 query + ONE R2 get. If `op` is slow\n // but `ds.idx`+`ds.obj` don't account for it, the time is above us (AFS\n // routing / overlay); if the segments themselves balloon far past the\n // backends' intrinsic latency (D1/R2 same-region ≈ 30-100ms), the requests\n // are queuing on the Workers 6-simultaneous-connection cap.\n //\n // Batch-optimised lookup: when available, getAndHasChildren collapses the\n // sequential get() + isDirectory() calls into a single D1 round-trip so\n // miss-path reads (e.g. \"try layout.aup, then layout.json\") cost 1 HTTP\n // call instead of 2.\n // get() WITHOUT hasChildren. hasChildren is consumed ONLY on the miss path\n // (the isDir branch at the end) — a returned file entry, inline or R2-backed,\n // never uses it. Batching it upfront (#950) therefore paid one extra D1\n // statement on EVERY hit, including the hot warm `.web-cache` serve, which\n // regressed the #808 warm-serve budget from 2 → 3. Resolve isDirectory\n // lazily below, and only when the file lookup actually missed: a miss costs\n // get()+isDirectory() (two round-trips, cold-start layout fallback chains\n // only) while every hit now costs a single statement.\n const entry = await time(\"ds.idx\", () => this.treeIndex.get(this.treePath(afsPath)));\n if (entry) {\n // Inline-content fast path (write-through read, settings-layering 1d):\n // an index row carrying a cid-VERIFIED inline copy serves the read with\n // ZERO object fetches (Node: saves an fs read; CF: saves an R2 GET).\n // Read-equivalence invariant: verified inline ≡ objects — a failed\n // verification falls back to objects with a repair log, NEVER surfacing\n // corrupt bytes. Inline copies exist only for text content (write path\n // gates on string), so the text-mime branch is the only consumer.\n if (entry.content !== undefined && isTextMime(entry.mimeType)) {\n const verified = await time(\"ds.inl\", async () => {\n const actual = await computeCID(entry.content as string);\n return actual === entry.cid;\n });\n if (verified) {\n return this.buildEntry(afsPath, {\n content: entry.content,\n meta: {\n // Application metadata first (planning/agent-hub/metadata-foundation.md):\n // provider-reserved keys (kind / size / cid / mimeType / version)\n // overwrite anything the application tried to put under the same\n // name; any other key flows through to the caller.\n ...(entry.metadata ?? {}),\n kind: \"did-space:file\",\n size: entry.size,\n cid: entry.cid,\n mimeType: entry.mimeType,\n // Opaque optimistic-concurrency version (EXT-4) — same token\n // stat() surfaces. Read-borne version is what lets the base\n // tree-* RMW check a caller ifMatch precondition without an\n // extra stat round-trip.\n version: entry.cid,\n } as AFSEntryMetadata,\n createdAt: new Date(entry.ctime),\n updatedAt: new Date(entry.mtime),\n });\n }\n log.warn(\n `[did-space] inline content failed cid verification at ${afsPath} (cid=${entry.cid}) — serving from objects; row will self-repair on next write`,\n );\n }\n const obj = await time(\"ds.obj\", () => this.objectStore.get(this.objectKey(entry.cid)));\n const content = await time(\"ds.body\", async () =>\n obj\n ? isTextMime(entry.mimeType)\n ? await obj.text()\n : await obj.arrayBuffer()\n : isTextMime(entry.mimeType)\n ? \"\"\n : new ArrayBuffer(0),\n );\n return this.buildEntry(afsPath, {\n content,\n meta: {\n ...(entry.metadata ?? {}),\n kind: \"did-space:file\",\n size: entry.size,\n cid: entry.cid,\n mimeType: entry.mimeType,\n // Opaque optimistic-concurrency version (EXT-4) — same token as\n // stat(); see the inline fast path above.\n version: entry.cid,\n } as AFSEntryMetadata,\n createdAt: new Date(entry.ctime),\n updatedAt: new Date(entry.mtime),\n });\n }\n\n const isDir = await this.isDirectory(afsPath);\n if (isDir) {\n const childrenCount = await this.treeIndex.countChildren(this.treeListPrefix(afsPath));\n return this.buildEntry(afsPath, {\n content: `Directory: ${afsPath} (${childrenCount} entries)`,\n meta: { kind: \"did-space:directory\", childrenCount } as AFSEntryMetadata,\n });\n }\n\n throw new AFSNotFoundError(afsPath);\n }\n\n /**\n * presignRead — path-keyed read-grant capability (preview-r2-direct §3).\n *\n * Resolves `path` in THIS provider's (prefix-isolated) view exactly like\n * `read`/`stat` (`treeIndex.get(treePath(path))`, incl. the same null-byte /\n * `..`-segment guards). iff the resolved entry has a cid AND a signer with\n * `presignGet` is present → mint a short-TTL presigned GET with the\n * Content-Type baked in, and return `{ url, expiresAt }`.\n *\n * The path resolution IS the authorization: a caller can only presign what\n * `read` would already return. Prefix isolation is inherited from the view's\n * `PrefixedTreeIndex` — no separate object-level `isReferenced(cid)` is needed\n * (that primitive is for the cid-keyed `.objects/{cid}` path, which has no\n * tree path). NEVER throws to the caller: no signer (Node) / non-CAS / no cid /\n * unresolved / any internal error → `null`, and the raw handler then falls back\n * to the worker serve path. TTL = `DOWNLOAD_GRANT_TTL_SEC` (2h) — never the 7d\n * signer cap (§8.3).\n */\n async presignRead(\n path: string,\n opts?: { responseContentType?: string },\n ): Promise<{ url: string; expiresAt: string } | null> {\n try {\n // presign needs only the cid to sign an object URL — never the inline bytes.\n const entry = await this.treeIndex.get(this.treePath(path), { includeContent: false });\n if (!entry?.cid) return null;\n if (this.signer == null || typeof this.signer.presignGet !== \"function\") return null;\n const g = await this.signer.presignGet({\n objectKey: this.objectKey(entry.cid),\n expiresInSec: DOWNLOAD_GRANT_TTL_SEC,\n responseContentType: opts?.responseContentType,\n });\n return { url: g.url, expiresAt: g.expiresAt };\n } catch {\n // Fail-soft: any resolution/signing error → null → worker-serve fallback.\n return null;\n }\n }\n\n /**\n * Re-verify an entry's inline copy against its cid (§2.I list contract).\n * Returns the content when verified, null otherwise (best-effort miss).\n */\n private async verifiedInline(entry: { cid: string; content?: string }): Promise<string | null> {\n if (entry.content === undefined) return null;\n return (await computeCID(entry.content)) === entry.cid ? entry.content : null;\n }\n\n // ========== D4: Virtual path protection ==========\n\n /**\n * Returns true if the given AFS path is a virtual D4-protected path\n * (.objects/* or .changelog/*).\n */\n private isVirtualPath(afsPath: string): boolean {\n const norm = afsPath.startsWith(\"/\") ? afsPath.slice(1) : afsPath;\n return (\n norm === \".objects\" ||\n norm.startsWith(\".objects/\") ||\n norm === \".changelog\" ||\n norm.startsWith(\".changelog/\")\n );\n }\n\n // ========== Write ==========\n\n @Write(\"/:path*\")\n async writeHandler(\n ctx: RouteContext<{ path?: string }>,\n payload: AFSWriteEntryPayload,\n ): Promise<{ data: AFSEntry }> {\n const afsPath = joinURL(\"/\", ctx.params.path ?? \"\");\n\n // D4: block public writes to virtual namespaces\n if (this.isVirtualPath(afsPath)) {\n throw new AFSForbiddenError(afsPath, \"virtual_path\");\n }\n\n // Phase 0.4: block writes to reserved share virtual paths\n if (isShareReservedPath(afsPath)) {\n throw new AFSForbiddenError(afsPath, \"share-path-reserved\");\n }\n\n // ifMatch optimistic-concurrency (EXT-4 / Phase 1): when the caller supplies\n // options.ifMatch, compare it to the current entry's CID (the opaque version\n // surfaced by statHandler). Mismatch → AFSConflictError; a missing target\n // with ifMatch present is also a conflict (caller expected a known prior\n // version). Absence of ifMatch falls back to last-write-wins (back-compat).\n // ifMatch precondition (incl. the D3 expected-absent sentinel) via the one\n // shared predicate — see ifMatchPreconditionFailed. The browser legacy\n // upload reaches write() when SessionUserAFS routes a single-entry write\n // here (not the batchWrite recheck), so this site MUST honor the sentinel.\n const writeIfMatch = (ctx.options as AFSWriteOptions | undefined)?.ifMatch;\n if (writeIfMatch !== undefined) {\n const current = await this.treeIndex.get(this.treePath(afsPath), { includeContent: false });\n if (ifMatchPreconditionFailed(writeIfMatch, current)) {\n throw new AFSConflictError(afsPath, {\n cid: current?.cid ?? null,\n mtime: current?.mtime ?? null,\n });\n }\n }\n\n if (payload.content === undefined && payload.meta !== undefined) {\n return {\n data: this.buildEntry(afsPath, {\n meta: { kind: \"did-space:file\", ...payload.meta } as AFSEntryMetadata,\n }),\n };\n }\n\n // Resolve content to bytes + storage value\n let bytes: Uint8Array;\n let storeValue: string | ArrayBuffer;\n if (payload.content instanceof Uint8Array) {\n bytes = payload.content;\n storeValue = bytes.buffer as ArrayBuffer;\n } else if (payload.content instanceof ArrayBuffer) {\n bytes = new Uint8Array(payload.content);\n storeValue = payload.content;\n } else {\n const text =\n typeof payload.content === \"string\" ? payload.content : JSON.stringify(payload.content);\n bytes = new TextEncoder().encode(text);\n storeValue = text;\n }\n\n const cid = await computeCID(bytes);\n const treePath = this.treePath(afsPath);\n\n // Phase 0.4: pre-io share hook (before R2 PUT)\n await applyShareWriteHook({\n ...this.shareHookArgs(afsPath, treePath),\n bytes,\n cid,\n resolver: this.shareResolver,\n phase: \"pre-io\",\n });\n\n // Content-addressable dedup: skip R2 put if object already exists\n const existingObj = await this.objectStore.head(this.objectKey(cid));\n if (!existingObj) {\n await this.objectStore.put(this.objectKey(cid), storeValue);\n }\n\n // Write provenance (§2.E): a transport (afs-rpc / mobile sync) can attach\n // the originating deviceId + client mtime via options.meta. Falls back to\n // the provider's configured deviceId and server-now when absent.\n const writeMeta = (ctx.options as AFSWriteOptions | undefined)?.meta;\n const writeDeviceId =\n typeof writeMeta?.deviceId === \"string\" && writeMeta.deviceId\n ? writeMeta.deviceId\n : this.deviceId;\n const now = typeof writeMeta?.mtime === \"number\" ? writeMeta.mtime : Date.now();\n // Detect mime type: explicit meta > filename detection > binary content sniff > undefined\n let mimeType =\n (payload.meta?.mimeType as string | undefined) ?? detectMimeType(afsPath) ?? undefined;\n // If mime is still unknown and content was binary (Uint8Array/ArrayBuffer input),\n // mark as octet-stream so readHandler knows to return ArrayBuffer, not text.\n if (\n !mimeType &&\n (payload.content instanceof Uint8Array || payload.content instanceof ArrayBuffer)\n ) {\n mimeType = \"application/octet-stream\";\n }\n\n // R1 (feed-sort §5.1): file-row ctime = application createdAt when present,\n // else now. ctime is set ONLY on first insert; TreeIndex.put() preserves it\n // on overwrite (ON CONFLICT) since createdAt is immutable. mtime stays `now`\n // (the LWW/write timestamp — Rule R NEVER maps updatedAt onto file mtime).\n const ctime = resolveCtime(payload.meta as Record<string, unknown> | undefined, now);\n const treeEntry: TreeEntry = { cid, size: bytes.length, mtime: now, ctime, mimeType };\n // Application metadata (planning/agent-hub/metadata-foundation.md): strip\n // provider-reserved keys, persist the rest to entries.metadata. createdAt /\n // updatedAt survive here (not reserved) — the tree-index reads them for\n // Rule R2 (direct-parent DIR ctime stamp).\n const appMeta = extractApplicationMeta(payload.meta as Record<string, unknown> | undefined);\n if (appMeta) {\n // Dedup-on-write (#1159): project the stamped identity onto the entry's\n // dedup columns. `dedupKey` stays in the metadata blob (observability /\n // collection-query); `dedupScope` is an index key only — strip it so it\n // doesn't clutter the app-visible metadata.\n if (typeof appMeta.dedupScope === \"string\") {\n treeEntry.dedupScope = appMeta.dedupScope;\n delete appMeta.dedupScope;\n }\n if (typeof appMeta.dedupKey === \"string\") treeEntry.dedupKey = appMeta.dedupKey;\n if (Object.keys(appMeta).length > 0) treeEntry.metadata = appMeta;\n }\n // Layer 0 inline content: offer text content to the index. An index\n // constructed with `inlineCache: \"on\"` stores it (≤ threshold, cid-\n // verified) as a read-acceleration copy; the default-off index ignores it\n // — byte-identical legacy behavior. The blob write above is NEVER skipped\n // either way (cas-blob-always-written invariant).\n // Byte payloads (afs-rpc base64 / mobile transport) are offered too when\n // they decode as UTF-8 text (same rule the sync-engine write path uses,\n // see writeSyncEntry) — otherwise every mobile-written item.json would\n // stay un-inlined and the T0.7 contentFile join could never hit.\n if (typeof storeValue === \"string\") {\n treeEntry.content = storeValue;\n } else {\n const inlineText = decodeInlineText(bytes, mimeType);\n if (inlineText !== null) treeEntry.content = inlineText;\n }\n const { oldCid } = await this.treeIndex.put(treePath, treeEntry, {\n deviceId: writeDeviceId,\n });\n if (this.gcQueue) {\n // §4.7.1 write-dequeue: a write re-references `cid`. If a prior\n // delete/overwrite had queued it, remove it so a concurrent GC sweep can't\n // delete a now-live object (closes the dedup re-reference race).\n await this.gcQueue.remove(cid);\n if (oldCid && oldCid !== cid) {\n await this.gcQueue.enqueue([oldCid]);\n }\n }\n\n // Phase 0.4: post-io share hook (after tree_entries written)\n await applyShareWriteHook({\n ...this.shareHookArgs(afsPath, treePath),\n bytes,\n cid,\n resolver: this.shareResolver,\n phase: \"post-io\",\n });\n\n // #674: blocklet publish/resolve hook — a `blocklet.yaml` write registers\n // resolve/blocklet/<id> → {owner, path} so the CF serve path finds it.\n await applyBlockletWriteHook({\n ...this.blockletHookArgs(afsPath, treePath),\n bytes,\n resolver: this.blockletResolver,\n });\n\n // Let the ASH scheduler pick up dynamically-written automations.\n if (afsPath.endsWith(\".ash\")) {\n this.emit({\n type: SCRIPT_EVENT_TYPES.REGISTERED,\n path: afsPath,\n data: { runtime: \"ash\" },\n });\n }\n\n // Post-write prefix watermark (Live Update Resilience Phase 3): attach the\n // new collection-root version to the result meta so the AFS core can put it\n // on the afs:write event for push gap detection. Reduced to the first path\n // segment internally; absent for root-level files (no collection root).\n const meta: AFSEntryMetadata = {\n // Application metadata first; provider-reserved keys below win.\n ...(appMeta ?? {}),\n kind: \"did-space:file\",\n size: treeEntry.size,\n cid,\n mimeType: treeEntry.mimeType,\n } as AFSEntryMetadata;\n if (this.treeIndex.getPrefixWatermark) {\n const version = await this.treeIndex.getPrefixWatermark(this.treePath(afsPath));\n if (version != null) (meta as Record<string, unknown>).liveSeq = String(version);\n }\n return {\n data: this.buildEntry(afsPath, {\n content: storeValue,\n meta,\n createdAt: new Date(treeEntry.ctime),\n updatedAt: new Date(treeEntry.mtime),\n }),\n };\n }\n\n // ========== Delete ==========\n\n @Delete(\"/:path*\")\n async deleteHandler(\n ctx: RouteContext<{ path?: string }>,\n ): Promise<{ path: string; deleted: boolean }> {\n const afsPath = joinURL(\"/\", ctx.params.path ?? \"\");\n\n // D4: block public deletes to virtual namespaces\n if (this.isVirtualPath(afsPath)) {\n throw new AFSForbiddenError(afsPath, \"virtual_path\");\n }\n\n // Phase 0.4: block deletes to reserved share virtual paths\n if (isShareReservedPath(afsPath)) {\n throw new AFSForbiddenError(afsPath, \"share-path-reserved\");\n }\n\n const treePath = this.treePath(afsPath);\n\n // ifMatch optimistic-concurrency for delete (Phase 1, §2.D). Delete carries\n // ifMatch under options.meta.ifMatch (AFSDeleteOptions.meta). Mismatch (or a\n // missing target when ifMatch is present) → AFSConflictError, so a stale\n // delete can't silently clobber a concurrent update (last-delete-wins).\n const deleteMeta = (ctx.options as AFSDeleteOptions | undefined)?.meta;\n const deleteIfMatch = deleteMeta?.ifMatch;\n if (deleteIfMatch !== undefined) {\n const current = await this.treeIndex.get(treePath, { includeContent: false });\n if (!current || current.cid !== deleteIfMatch) {\n throw new AFSConflictError(afsPath, {\n cid: current?.cid ?? null,\n mtime: current?.mtime ?? null,\n });\n }\n }\n\n // T1.5: thread the CLIENT's deviceId + mtime into the delete changelog row.\n // Without this the row records the provider default deviceId + server clock,\n // which (a) breaks echo prevention — the deleter pulls back its own delete —\n // and (b) makes LWW delete-vs-put compare server time, not client mtime.\n const deleteOpts: PutOpts = {\n deviceId:\n typeof deleteMeta?.deviceId === \"string\" && deleteMeta.deviceId\n ? deleteMeta.deviceId\n : this.deviceId,\n ...(typeof deleteMeta?.mtime === \"number\" ? { mtime: deleteMeta.mtime } : {}),\n };\n\n // Try as file first\n const entry = await this.treeIndex.get(treePath, { includeContent: false });\n if (entry) {\n // Enqueue before delete: if enqueue fails, entries untouched → no orphan; safe to retry.\n // If delete fails after enqueue: CID is queued but entries still reference it →\n // isReferenced() returns true → GC skips it (safe).\n await this.gcQueue?.enqueue([entry.cid]);\n await this.treeIndex.delete(treePath, deleteOpts);\n\n // Phase 0.4: delete hook (after tree_entries removed)\n await applyShareDeleteHook({\n ...this.shareHookArgs(afsPath, treePath),\n resolver: this.shareResolver,\n });\n\n // #674: blocklet unregister — deleting a `blocklet.yaml` removes its\n // resolve/blocklet/<id> entry (looked up by owner+path).\n await applyBlockletDeleteHook({\n ...this.blockletHookArgs(afsPath, treePath),\n resolver: this.blockletResolver,\n });\n\n // Let the ASH scheduler tear down triggers for deleted automations.\n if (afsPath.endsWith(\".ash\")) {\n this.emit({\n type: SCRIPT_EVENT_TYPES.UNREGISTERED,\n path: afsPath,\n data: { runtime: \"ash\" },\n });\n }\n\n return { path: afsPath, deleted: true };\n }\n\n // Try as directory — bulk delete all entries under prefix\n const prefix = this.treeListPrefix(afsPath);\n if (this.gcQueue) {\n const cids = await this.collectCIDsByPrefix(prefix);\n if (cids.length > 0) await this.gcQueue.enqueue(cids);\n }\n const deleted = await this.treeIndex.deleteByPrefix(prefix, deleteOpts);\n if (deleted === 0) {\n throw new AFSNotFoundError(afsPath);\n }\n\n return { path: afsPath, deleted: true };\n }\n\n // ========== Batch pushdown (afs-rpc-batch P3, design §6.3) ==========\n\n /** Conflict failure shaped exactly like the single-op AFSConflictError surface. */\n private batchConflictFailure(\n afsPath: string,\n conflict: AFSBatchConflictInfo,\n ): { path: string; success: false; error: string; code: string; conflict: AFSBatchConflictInfo } {\n return {\n path: afsPath,\n success: false,\n error: `Write conflict at ${afsPath}`,\n code: \"AFS_CONFLICT\",\n conflict,\n };\n }\n\n /** ONE preflight read for a batch — getMany when the index has it, per-path get otherwise. */\n private async batchPreread(treePaths: string[]): Promise<Map<string, TreeEntry | null>> {\n if (this.treeIndex.getMany) return this.treeIndex.getMany(treePaths);\n return new Map(\n await Promise.all(treePaths.map(async (tp) => [tp, await this.treeIndex.get(tp)] as const)),\n );\n }\n\n /** Run `fn` over `items` with bounded concurrency (Workers cap: 6 sockets). */\n private async boundedAll<T>(items: T[], limit: number, fn: (item: T) => Promise<void>) {\n let next = 0;\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n while (next < items.length) {\n const item = items[next++]!;\n await fn(item);\n }\n });\n await Promise.all(workers);\n }\n\n /**\n * Native batch read (issue #808 follow-up) — the render fast path. Resolves the\n * whole path set with ONE `treeIndex.getMany` (chunked `IN(…)`, which carries\n * inline content when the index has it), so small cid-verified inline files are\n * served with ZERO R2 gets; only the (few, large) non-inline entries fall back\n * to bounded-concurrent `objectStore.get`. Mirrors the single-read handler's\n * inline-verify → objects cascade per entry. File-oriented: getMany matches\n * `kind='file'`, so directory / absent paths come back AFS_NOT_FOUND (callers\n * reading directories use `list`/`read`).\n */\n async batchRead(\n entries: AFSBatchReadEntry[],\n _options?: AFSOperationOptions,\n ): Promise<AFSBatchReadResult> {\n const afsPaths = entries.map((e) => joinURL(\"/\", e.path));\n const treePaths = afsPaths.map((p) => this.treePath(p));\n const preread = await this.batchPreread(treePaths);\n const results: AFSBatchReadEntryResult[] = new Array(entries.length);\n\n const fileEntry = (afsPath: string, entry: TreeEntry, content: unknown): AFSEntry =>\n this.buildEntry(afsPath, {\n content,\n meta: {\n ...(entry.metadata ?? {}),\n kind: \"did-space:file\",\n size: entry.size,\n cid: entry.cid,\n mimeType: entry.mimeType,\n version: entry.cid,\n } as AFSEntryMetadata,\n createdAt: new Date(entry.ctime),\n updatedAt: new Date(entry.mtime),\n });\n\n const needObject: number[] = [];\n for (let i = 0; i < entries.length; i++) {\n const entry = preread.get(treePaths[i]!);\n if (!entry) {\n results[i] = {\n path: afsPaths[i]!,\n success: false,\n error: `Path not found: ${afsPaths[i]}`,\n code: \"AFS_NOT_FOUND\",\n };\n continue;\n }\n // Inline fast path (cid-verified) — zero R2, mirrors the single read.\n if (entry.content !== undefined && isTextMime(entry.mimeType)) {\n if ((await computeCID(entry.content)) === entry.cid) {\n results[i] = {\n path: afsPaths[i]!,\n success: true,\n data: fileEntry(afsPaths[i]!, entry, entry.content),\n };\n continue;\n }\n log.warn(\n `[did-space] inline content failed cid verification at ${afsPaths[i]} (cid=${entry.cid}) — serving from objects; row will self-repair on next write`,\n );\n }\n needObject.push(i);\n }\n\n // Non-inline entries: bounded-concurrent R2 (Workers 6-socket cap).\n await this.boundedAll(needObject, 6, async (i) => {\n const entry = preread.get(treePaths[i]!)!;\n const obj = await this.objectStore.get(this.objectKey(entry.cid));\n const isText = isTextMime(entry.mimeType);\n const content = obj\n ? isText\n ? await obj.text()\n : await obj.arrayBuffer()\n : isText\n ? \"\"\n : new ArrayBuffer(0);\n results[i] = {\n path: afsPaths[i]!,\n success: true,\n data: fileEntry(afsPaths[i]!, entry, content),\n };\n });\n\n const succeeded = results.filter((r) => r.success).length;\n return { results, succeeded, failed: entries.length - succeeded };\n }\n\n /**\n * Native batch write — the CF-subrequest-budget merge (§4.3): eight-step\n * order aligned point-for-point with the single write path (preread BEFORE\n * share pre-io, so a stale ifMatch on a `.share` declaration yields 409,\n * never a share error):\n * 1 shape/decode/computeCID → 2 ONE preread (conflict/skip exit here —\n * no share hook, no R2 upload) → 3 share pre-io (survivors) → 4 in-batch\n * CID dedup → 5 unconditional R2 put (unique cids, bounded ≤6 —\n * P0-measured wall-time) → 6 treeIndex.batchPutEntries (single db.batch)\n * → 7 gcQueue removeMany/enqueue → 8 share post-io + per-entry results.\n */\n async batchWrite(\n entries: AFSBatchWriteEntry[],\n _options?: AFSOperationOptions,\n ): Promise<AFSBatchWriteResult> {\n // Dedup-on-write batch (native sync write model, #492 / #1159): when any\n // entry opts into `dedupBy` (or the deprecated `dedupKey` alias), route\n // every entry through the single-write path SEQUENTIALLY. Sequential is\n // load-bearing — a later same-URL entry reads the earlier entry's\n // just-written record and merges into it (in-batch coalescing) instead of\n // racing it. The fast parallel path below handles the common no-dedup batch\n // unchanged.\n if (entries.some((e) => e.options?.dedupBy || e.options?.dedupKey)) {\n const seq: AFSBatchWriteResult[\"results\"] = [];\n let succeeded = 0;\n for (const entry of entries) {\n const afsPath = joinURL(\"/\", entry.path);\n try {\n const payload = entry.content;\n if (!payload || payload.content === undefined) {\n throw new AFSValidationError(\"Batch write requires entry content\");\n }\n const opts: AFSWriteOptions = {\n ...(entry.options ?? {}),\n ...(entry.mode ? { mode: entry.mode } : {}),\n };\n const res = await this.write(entry.path, payload, opts);\n seq.push({ path: res.data.path, success: true, data: res.data });\n succeeded++;\n } catch (err) {\n seq.push({\n path: afsPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n code:\n err instanceof AFSConflictError\n ? \"AFS_CONFLICT\"\n : ((err as { code?: string })?.code ?? \"AFS_WRITE_ERROR\"),\n });\n }\n }\n return { results: seq, succeeded, failed: entries.length - succeeded };\n }\n\n const results: AFSBatchWriteResult[\"results\"] = new Array(entries.length);\n\n interface Prepared {\n i: number;\n afsPath: string;\n treePath: string;\n bytes: Uint8Array;\n storeValue: string | ArrayBuffer;\n cid: string;\n treeEntry: TreeEntry;\n deviceId: string;\n ifMatch?: string;\n }\n\n // 1. shape / path 校验 + decode / computeCID — per-entry failures exit here.\n const prepared: Prepared[] = [];\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i]!;\n const afsPath = joinURL(\"/\", entry.path);\n if (entry.patches || (entry.mode && entry.mode !== \"replace\")) {\n results[i] = {\n path: afsPath,\n success: false,\n error: `Batch write supports replace-mode content writes only (got mode '${entry.mode ?? \"patches\"}')`,\n code: \"AFS_UNSUPPORTED\",\n };\n continue;\n }\n if (this.isVirtualPath(afsPath) || isShareReservedPath(afsPath)) {\n results[i] = {\n path: afsPath,\n success: false,\n error: `Forbidden at ${afsPath}: virtual_path`,\n code: \"AFS_FORBIDDEN\",\n };\n continue;\n }\n const payload = entry.content ?? {};\n if (payload.content === undefined) {\n results[i] = {\n path: afsPath,\n success: false,\n error: \"Batch write requires entry content (meta-only writes are single-op)\",\n code: \"AFS_VALIDATION_ERROR\",\n };\n continue;\n }\n let bytes: Uint8Array;\n let storeValue: string | ArrayBuffer;\n if (payload.content instanceof Uint8Array) {\n bytes = payload.content;\n storeValue = bytes.buffer as ArrayBuffer;\n } else if (payload.content instanceof ArrayBuffer) {\n bytes = new Uint8Array(payload.content);\n storeValue = payload.content;\n } else {\n const text =\n typeof payload.content === \"string\" ? payload.content : JSON.stringify(payload.content);\n bytes = new TextEncoder().encode(text);\n storeValue = text;\n }\n const cid = await computeCID(bytes);\n const writeOptions = entry.options as AFSWriteOptions | undefined;\n const writeMeta = writeOptions?.meta;\n const deviceId =\n typeof writeMeta?.deviceId === \"string\" && writeMeta.deviceId\n ? writeMeta.deviceId\n : this.deviceId;\n const now = typeof writeMeta?.mtime === \"number\" ? writeMeta.mtime : Date.now();\n let mimeType =\n (payload.meta?.mimeType as string | undefined) ?? detectMimeType(afsPath) ?? undefined;\n if (\n !mimeType &&\n (payload.content instanceof Uint8Array || payload.content instanceof ArrayBuffer)\n ) {\n mimeType = \"application/octet-stream\";\n }\n // R1 (feed-sort §5.1): per-entry file ctime from createdAt (else now).\n // createdAt rides the wire entry's top-level `meta`, which afs-rpc already\n // lifted onto `payload.meta` (NOT options.meta — that's deviceId/mtime\n // provenance). mtime stays `now` (LWW timestamp untouched by Rule R).\n const ctime = resolveCtime(payload.meta as Record<string, unknown> | undefined, now);\n const treeEntry: TreeEntry = { cid, size: bytes.length, mtime: now, ctime, mimeType };\n // Application metadata (did-space-metadata G1): mirror the single write\n // path (index.ts:1707). afs-rpc already lifted the wire entry's top-level\n // `meta` onto `payload.meta` (wireMeta), so the batchWrite leg only had to\n // consume it. Strip provider-reserved keys, then bound the size before it\n // reaches the index — a per-entry validation failure, not a batch-wide throw.\n const appMeta = extractApplicationMeta(payload.meta as Record<string, unknown> | undefined);\n if (appMeta) {\n try {\n assertMetadataSize(appMeta, afsPath);\n } catch (err) {\n results[i] = {\n path: afsPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n code: (err as { code?: string }).code ?? \"AFS_VALIDATION_ERROR\",\n };\n continue;\n }\n treeEntry.metadata = appMeta;\n }\n if (typeof storeValue === \"string\") {\n treeEntry.content = storeValue;\n } else {\n const inlineText = decodeInlineText(bytes, mimeType);\n if (inlineText !== null) treeEntry.content = inlineText;\n }\n prepared.push({\n i,\n afsPath,\n treePath: this.treePath(afsPath),\n bytes,\n storeValue,\n cid,\n treeEntry,\n deviceId,\n ifMatch: writeOptions?.ifMatch,\n });\n }\n\n // 2. ONE preread — ifMatch conflicts exit HERE, before any share hook or R2\n // traffic (bandwidth + orphan discipline). Skip-if-unchanged no longer\n // exits here (did-space-metadata G4): it is decided by batchPutEntries,\n // the sole skip authority, and routed to `skipped` from its results.\n const preread = await this.batchPreread(prepared.map((p) => p.treePath));\n\n const skipped: Prepared[] = [];\n let live: Prepared[] = [];\n for (const p of prepared) {\n const existing = preread.get(p.treePath) ?? null;\n // ifMatch precondition (incl. the D3 expected-absent sentinel, §4.2a) via\n // the one shared predicate — present-when-absent-expected ⇒ conflict.\n if (ifMatchPreconditionFailed(p.ifMatch, existing)) {\n results[p.i] = this.batchConflictFailure(p.afsPath, {\n currentCid: existing?.cid ?? null,\n currentMtime: existing?.mtime ?? null,\n currentDeviceId: null,\n });\n continue;\n }\n // NO provider-level cid-match early-skip (did-space-metadata G4, aligning\n // with the commit path §5.2): `batchPutEntries` is now the SOLE skip\n // authority so the metadata-aware (and content-aware) skip judgement lives\n // in exactly one place. A TRUE no-op (cid+mime+content+metadata all equal)\n // comes back as `r.skipped` below and is routed to the `skipped` bucket\n // there — preserving written-only post-io hooks + liveSeq-from-watermark.\n live.push(p);\n }\n\n // 3. share pre-io hook — survivors only, fail-closed per entry.\n const preIoOk: Prepared[] = [];\n for (const p of live) {\n try {\n await applyShareWriteHook({\n ...this.shareHookArgs(p.afsPath, p.treePath),\n bytes: p.bytes,\n cid: p.cid,\n resolver: this.shareResolver,\n phase: \"pre-io\",\n });\n preIoOk.push(p);\n } catch (err) {\n results[p.i] = {\n path: p.afsPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n code: (err as { code?: string }).code,\n };\n }\n }\n live = preIoOk;\n\n // 4+5. CID dedup → unconditional R2 put (unique cids, bounded concurrency).\n const uniqueCids = new Map<string, Prepared>();\n for (const p of live) if (!uniqueCids.has(p.cid)) uniqueCids.set(p.cid, p);\n const uploadFailed = new Map<string, string>();\n const uploaded: string[] = [];\n await this.boundedAll([...uniqueCids.values()], 6, async (p) => {\n try {\n await this.objectStore.put(this.objectKey(p.cid), p.storeValue);\n uploaded.push(p.cid);\n } catch (err) {\n uploadFailed.set(p.cid, err instanceof Error ? err.message : String(err));\n }\n });\n if (uploadFailed.size > 0) {\n const stillLive: Prepared[] = [];\n for (const p of live) {\n const failure = uploadFailed.get(p.cid);\n if (failure !== undefined) {\n results[p.i] = { path: p.afsPath, success: false, error: `R2 put failed: ${failure}` };\n } else {\n stillLive.push(p);\n }\n }\n live = stillLive;\n }\n\n // 6. Single atomic index batch. On failure the batch rolled back — the\n // already-uploaded objects are unreferenced, so enqueue them for GC\n // (isReferenced keeps anything a concurrent writer claimed).\n let indexResults: Awaited<ReturnType<NonNullable<TreeIndex[\"batchPutEntries\"]>>> = [];\n if (live.length > 0) {\n const batchEntries: BatchPutEntry[] = live.map((p) => ({\n path: p.treePath,\n entry: p.treeEntry,\n opts: { deviceId: p.deviceId },\n }));\n try {\n indexResults = this.treeIndex.batchPutEntries\n ? await this.treeIndex.batchPutEntries(batchEntries, { preread })\n : await loopBatchPutEntries(this.treeIndex, batchEntries, { preread });\n } catch (err) {\n await this.gcQueue?.enqueue(uploaded);\n const message = err instanceof Error ? err.message : String(err);\n for (const p of live) {\n results[p.i] = { path: p.afsPath, success: false, error: message };\n }\n live = [];\n }\n }\n\n // 7. GC bookkeeping — ONE removeMany for every re-referenced cid\n // (written + skipped: a batch write rescues queued cids exactly like\n // the single-op write-dequeue, §4.7.1), then enqueue replaced cids.\n const written: Array<{ p: Prepared; oldCid?: string; liveSeq?: number; error?: string }> = [];\n live.forEach((p, j) => {\n const r = indexResults[j];\n if (!r) {\n results[p.i] = { path: p.afsPath, success: false, error: \"index batch returned no result\" };\n return;\n }\n if (r.conflict) {\n results[p.i] = this.batchConflictFailure(p.afsPath, r.conflict);\n return;\n }\n if (r.error) {\n results[p.i] = { path: p.afsPath, success: false, error: r.error };\n return;\n }\n // True no-op (cid+mime+content+metadata all equal) → route to the skipped\n // bucket (did-space-metadata G4 §5.2): keeps post-io share hooks written-\n // only and GC re-referenced = written + skipped (both unchanged); a no-op\n // must NOT fire a post-io share reconcile.\n if (r.skipped) {\n skipped.push(p);\n return;\n }\n written.push({ p, oldCid: r.oldCid, liveSeq: r.liveSeq });\n });\n if (this.gcQueue) {\n const reReferenced = [\n ...new Set([...written.map((w) => w.p.cid), ...skipped.map((s) => s.cid)]),\n ];\n if (reReferenced.length > 0) {\n if (this.gcQueue.removeMany) await this.gcQueue.removeMany(reReferenced);\n else for (const cid of reReferenced) await this.gcQueue.remove(cid);\n }\n const replaced = [\n ...new Set(written.filter((w) => w.oldCid && w.oldCid !== w.p.cid).map((w) => w.oldCid!)),\n ];\n if (replaced.length > 0) await this.gcQueue.enqueue(replaced);\n }\n\n // 8. share post-io (written only) + per-entry results. A post-io failure\n // surfaces on ITS entry (the write persisted — same half-done window\n // as the single-op path).\n for (const w of written) {\n try {\n await applyShareWriteHook({\n ...this.shareHookArgs(w.p.afsPath, w.p.treePath),\n bytes: w.p.bytes,\n cid: w.p.cid,\n resolver: this.shareResolver,\n phase: \"post-io\",\n });\n } catch (err) {\n w.error = err instanceof Error ? err.message : String(err);\n }\n if (w.p.afsPath.endsWith(\".ash\")) {\n this.emit({\n type: SCRIPT_EVENT_TYPES.REGISTERED,\n path: w.p.afsPath,\n data: { runtime: \"ash\" },\n });\n }\n }\n\n // Skipped entries: success result mirroring the single-op skip (current\n // state echoed; liveSeq = the prefix's current watermark, reused from\n // this batch's written entries where possible).\n const maxSeqByPrefix = new Map<string, number>();\n for (const w of written) {\n if (typeof w.liveSeq !== \"number\") continue;\n const wm = watermarkWritePrefix(w.p.treePath);\n if (wm === null) continue;\n maxSeqByPrefix.set(wm, Math.max(maxSeqByPrefix.get(wm) ?? 0, w.liveSeq));\n }\n for (const s of skipped) {\n const wm = watermarkWritePrefix(s.treePath);\n let liveSeq: number | undefined = wm !== null ? maxSeqByPrefix.get(wm) : undefined;\n if (liveSeq === undefined && this.treeIndex.getPrefixWatermark) {\n liveSeq = (await this.treeIndex.getPrefixWatermark(s.treePath)) ?? undefined;\n }\n results[s.i] = {\n path: s.afsPath,\n success: true,\n data: this.buildBatchWriteData(s, liveSeq),\n };\n }\n for (const w of written) {\n if (w.error) {\n results[w.p.i] = { path: w.p.afsPath, success: false, error: w.error };\n continue;\n }\n results[w.p.i] = {\n path: w.p.afsPath,\n success: true,\n data: this.buildBatchWriteData(w.p, w.liveSeq),\n };\n }\n\n const succeeded = results.filter((r) => r?.success).length;\n return { results, succeeded, failed: results.length - succeeded };\n }\n\n /** Write-echo entry — field-for-field the single-op writeHandler result. */\n private buildBatchWriteData(\n p: { afsPath: string; storeValue: string | ArrayBuffer; cid: string; treeEntry: TreeEntry },\n liveSeq: number | undefined,\n ): AFSEntry {\n const meta: AFSEntryMetadata = {\n kind: \"did-space:file\",\n size: p.treeEntry.size,\n cid: p.cid,\n mimeType: p.treeEntry.mimeType,\n } as AFSEntryMetadata;\n if (liveSeq != null) (meta as Record<string, unknown>).liveSeq = String(liveSeq);\n return this.buildEntry(p.afsPath, {\n content: p.storeValue,\n meta,\n createdAt: new Date(p.treeEntry.ctime),\n updatedAt: new Date(p.treeEntry.mtime),\n });\n }\n\n // ========== Upload plane actions (design §7.2 / §10) ==========\n\n /** Build a failed AFSExecResult (shared across the three action handlers). */\n private uploadErr(code: string, message: string): AFSExecResult {\n return { success: false, error: { code, message } };\n }\n\n /**\n * Session ownership isolation (§9 / §10): a session belongs to THIS view only\n * when its scope equals this provider's storage scope. A different-scope (or\n * unknown) session is treated as not-found — never confirm another user's\n * session exists, and never let one view commit into another.\n */\n private ownsSession(session: UploadSession | null): session is UploadSession {\n return !!session && session.scope === (this.uploadScope ?? this.did);\n }\n\n /**\n * Validate an action-supplied `path`. Unlike `@Write` handlers, action args\n * carry NO router-layer traversal protection — `args.entries[].path` is raw\n * client input, so we MUST normalize + reject traversal / reserved virtual\n * prefixes explicitly (design §10). Returns the tree path on success.\n */\n private validateActionPath(\n afsPath: string,\n ): { ok: true; treePath: string } | { ok: false; reason: string } {\n const norm = afsPath.startsWith(\"/\") ? afsPath.slice(1) : afsPath;\n // Reserved virtual prefixes (design §10): `.objects` / `.changelog`\n // (isVirtualPath), `.shares` (isShareReservedPath), AND `.actions` — the\n // action namespace itself, which isVirtualPath does NOT cover. A grant must\n // never let a client commit a tree entry under any of these.\n if (\n this.isVirtualPath(afsPath) ||\n isShareReservedPath(afsPath) ||\n norm === \".actions\" ||\n norm.startsWith(\".actions/\")\n ) {\n return { ok: false, reason: `reserved path: ${afsPath}` };\n }\n let treePath: string;\n try {\n treePath = this.treePath(afsPath); // throws on null byte / `..` segment\n } catch (err) {\n return { ok: false, reason: err instanceof Error ? err.message : String(err) };\n }\n return { ok: true, treePath };\n }\n\n /**\n * Action catalogue — the upload-plane + download-plane actions, always listed\n * (protocol parity, T2.5). Each plane advertises its OWN capability flag:\n * `grantCapability` for prepare-upload, the INDEPENDENT `downloadGrantCapability`\n * for prepare-download (design §7.3 / Finding 4 — never reuse the upload flag,\n * so the two planes can be advertised separately).\n */\n @Actions(\"/\")\n listObjectPlaneActions(ctx: RouteContext): AFSListResult {\n // Both flags' current value ≡ `signer != null` (the only real signer,\n // R2PresignSigner, implements both presignPut and presignGet). The `typeof`\n // guard on presignGet is the defensive basis for a future PUT-only signer\n // (§7.3); it changes the wire field name, not today's value.\n const grantCapable = this.signer != null;\n const downloadGrantCapable =\n this.signer != null && typeof this.signer.presignGet === \"function\";\n const data = [...UPLOAD_ACTIONS, ...DOWNLOAD_ACTIONS].map((name) =>\n this.buildEntry(joinURL(ctx.path, name), {\n id: name,\n meta: {\n kind: \"afs:executable\",\n // Capability signals: grant minting only when a signer is wired.\n // Clients read these to choose grant-path vs batch fallback (P3).\n ...(name === \"prepare-upload\" ? { grantCapability: grantCapable } : {}),\n ...(name === \"prepare-download\" ? { downloadGrantCapability: downloadGrantCapable } : {}),\n } as AFSEntryMetadata,\n }),\n );\n return { data };\n }\n\n @Actions.Exec(\n \"/\",\n \"prepare-upload\",\n \"Reserve an upload session + (CF) mint exact-key checksum-pinned PUT grants\",\n {\n effect: \"write\",\n },\n )\n async execPrepareUpload(\n _ctx: RouteContext,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n if (!this.uploadSessionStore) {\n return this.uploadErr(\"AFS_UNSUPPORTED\", \"upload plane not available\");\n }\n const parsed = PrepareUploadArgsSchema.safeParse(args);\n if (!parsed.success) {\n return this.uploadErr(\"AFS_VALIDATION_ERROR\", zodMessage(parsed.error));\n }\n\n // Validate EVERY entry up-front; any failure rejects the whole prepare and\n // creates NO session (design negative case B).\n const outEntries: Array<Record<string, unknown>> = [];\n const storeEntries: UploadSessionEntryInput[] = [];\n const seenPaths = new Set<string>();\n for (const e of parsed.data.entries) {\n const afsPath = joinURL(\"/\", e.path);\n const pv = this.validateActionPath(afsPath);\n if (!pv.ok) {\n return this.uploadErr(\"AFS_VALIDATION_ERROR\", pv.reason);\n }\n if (seenPaths.has(afsPath)) {\n return this.uploadErr(\"AFS_VALIDATION_ERROR\", `duplicate path: ${afsPath}`);\n }\n seenPaths.add(afsPath);\n let checksum: string;\n try {\n checksum = cidToChecksumSha256(e.cid); // throws on non-raw+sha256 / malformed\n } catch (err) {\n return this.uploadErr(\n \"AFS_VALIDATION_ERROR\",\n `bad cid for ${afsPath}: ${err instanceof Error ? err.message : err}`,\n );\n }\n const objectKey = this.objectKey(e.cid);\n // v1: already-present is OFF (design §7.2 / decision 2) — every entry is\n // needs-upload and (CF) gets a grant, so a dangling cid can always be\n // re-uploaded.\n let grant: Record<string, unknown> | null = null;\n if (this.signer) {\n const g = await this.signer.presignPut({\n objectKey,\n checksumSha256: checksum,\n expiresInSec: GRANT_EXPIRES_SEC,\n // upload-limits Phase 4 anti-lie (D2 = §9.2(ii)): pin the declared size\n // into the PUT signature. ingest-prepare already gated size ≤ maxBytes;\n // R2 then rejects a body that doesn't match (403). grant is now triple-\n // pinned: exact key + content checksum + size.\n contentLength: e.size,\n });\n grant = {\n kind: \"presigned-put\",\n url: g.url,\n method: g.method,\n signedHeaders: g.signedHeaders,\n expiresAt: g.expiresAt,\n };\n }\n outEntries.push({\n path: afsPath,\n cid: e.cid,\n status: \"needs-upload\",\n objectKey,\n checksumSha256: checksum,\n grant,\n });\n storeEntries.push({\n path: afsPath,\n cid: e.cid,\n objectKey,\n checksumSha256: checksum,\n size: e.size,\n mimeType: e.mimeType ?? null,\n ifMatch: e.ifMatch ?? null,\n deviceId: e.deviceId ?? null,\n mtime: e.mtime ?? null,\n status: \"needs_upload\",\n });\n }\n\n const sessionId = crypto.randomUUID();\n const expiresAt = Date.now() + UPLOAD_SESSION_TTL_MS;\n // scope = the de-identified storage scope (§9); caller left null — session\n // ownership is enforced by scope, and we never store a user DID here.\n await this.uploadSessionStore.createSession({\n id: sessionId,\n scope: this.uploadScope ?? this.did,\n caller: null,\n expiresAt,\n entries: storeEntries,\n });\n return {\n success: true,\n data: { sessionId, expiresAt: new Date(expiresAt).toISOString(), entries: outEntries },\n };\n }\n\n @Actions.Exec(\n \"/\",\n \"prepare-download\",\n \"Mint exact-key short-TTL presigned GET grants for view-referenced objects\",\n {\n // MUST be \"write\" (Finding 1): minting bearer GET authority is a privileged\n // action. A \"read\" effect would let an anonymous network caller through the\n // exec-effect-gate (exec-effect-gate.ts:165). It changes NO persistent state\n // (zero tables, §9) — the convention is \"write\" == \"privileged / authed-only\".\n effect: \"write\",\n },\n )\n async execPrepareDownload(\n _ctx: RouteContext,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n const parsed = PrepareDownloadArgsSchema.safeParse(args);\n if (!parsed.success) {\n // Over maxEntries / empty / shape errors → whole request rejected, NO\n // grants minted (design §7.4 / Finding 5).\n return this.uploadErr(\"AFS_VALIDATION_ERROR\", zodMessage(parsed.error));\n }\n const inputEntries = parsed.data.entries;\n\n // 1+2. Entry-level dedupe + per-entry CID validation. Unlike prepare-upload\n // (any bad cid rejects the whole batch), reads are stateless partial-success:\n // a malformed cid is per-entry `invalid`, never连坐 the others (§7.4). Dedupe\n // by cid so a repeated cid is authorized once + signed once (§7.4).\n const cidValid = new Map<string, boolean>();\n const validCids: string[] = [];\n for (const e of inputEntries) {\n if (cidValid.has(e.cid)) continue;\n let ok = true;\n try {\n // Same raw+sha256 validation as prepare-upload — a non-CAS cid can never\n // be a stored object, so it's `invalid` input, not a lookup miss.\n cidToChecksumSha256(e.cid);\n } catch {\n ok = false;\n }\n cidValid.set(e.cid, ok);\n if (ok) validCids.push(e.cid);\n }\n\n // 3. Batch authorization — scope-aware THREE-WAY isReferencedMany (P1), NOT\n // the scope-blind referencedAnywhere* (that's GC liveness; using it = cross-\n // user read = security bug, §7.2). When NOTHING is valid, skip authz entirely\n // (zero DB roundtrips — the all-`invalid` fast path).\n let referenced = new Set<string>();\n if (validCids.length > 0) {\n try {\n referenced = await this.treeIndex.isReferencedMany(validCids);\n } catch {\n // Fail-closed (§7.4): if the authorization query is unavailable, fail the\n // WHOLE request so the client falls back to batchRead — NEVER degrade to\n // \"sign everything\" or a per-cid soft retry (would risk minting unauthorized\n // grants). The caller-facing message is a FIXED string — the DB error detail\n // is never surfaced, so no cid / query fragment can leak through it (§10).\n return this.uploadErr(\"AFS_INTERNAL_ERROR\", \"prepare-download authorization unavailable\");\n }\n }\n\n // 4. Batch sign (CF: presignGet; Node: grant=null, signer absent). Sign each\n // authorized cid once; a referenced cid that the signer can mint gets a\n // short-TTL exact-key GET grant.\n const canSign = this.signer != null && typeof this.signer.presignGet === \"function\";\n const grantByCid = new Map<string, Record<string, unknown> | null>();\n for (const cid of referenced) {\n if (canSign) {\n const g = await this.signer!.presignGet({\n objectKey: this.objectKey(cid),\n // SHORT TTL default — never PRESIGN_MAX_EXPIRES_SEC (§8.3).\n expiresInSec: DOWNLOAD_GRANT_TTL_SEC,\n });\n grantByCid.set(cid, {\n kind: \"presigned-get\",\n url: g.url,\n method: g.method,\n signedHeaders: g.signedHeaders,\n expiresAt: g.expiresAt,\n });\n } else {\n grantByCid.set(cid, null);\n }\n }\n\n // 5. Partial-success output, ALIGNED to input order + length (client indexes\n // back). A duplicate cid's every input row gets the same {status, grant}.\n // `forbidden` covers BOTH unreferenced AND not-found — never distinguished\n // (don't confirm cid existence, §10 / readHandler 404-not-403).\n const outEntries = inputEntries.map((e) => {\n if (!cidValid.get(e.cid)) {\n return { cid: e.cid, status: \"invalid\" };\n }\n if (!referenced.has(e.cid)) {\n return { cid: e.cid, status: \"forbidden\" };\n }\n return {\n cid: e.cid,\n status: \"ok\",\n objectKey: this.objectKey(e.cid),\n grant: grantByCid.get(e.cid) ?? null,\n };\n });\n return { success: true, data: { entries: outEntries } };\n }\n\n @Actions.Exec(\n \"/\",\n \"commit-upload\",\n \"Commit uploaded objects' metadata (trust existence, 0 R2 subrequests)\",\n {\n effect: \"write\",\n },\n )\n async execCommitUpload(\n _ctx: RouteContext,\n args: Record<string, unknown>,\n ): Promise<AFSExecResult> {\n if (!this.uploadSessionStore) {\n return this.uploadErr(\"AFS_UNSUPPORTED\", \"upload plane not available\");\n }\n const parsed = CommitUploadArgsSchema.safeParse(args);\n if (!parsed.success) {\n return this.uploadErr(\"AFS_VALIDATION_ERROR\", zodMessage(parsed.error));\n }\n const { sessionId, entries } = parsed.data;\n const session = await this.uploadSessionStore.getSession(sessionId);\n // Session ownership isolation (T2.3): unknown OR cross-scope → not found\n // (don't reveal another user's session exists).\n if (!this.ownsSession(session)) {\n return this.uploadErr(\"AFS_NOT_FOUND\", \"unknown upload session\");\n }\n if (session.status === \"aborted\") {\n return this.uploadErr(\"AFS_UNSUPPORTED\", \"session aborted\");\n }\n if (session.status === \"prepared\" && session.expiresAt <= Date.now()) {\n return this.uploadErr(\"AFS_UNSUPPORTED\", \"session expired\");\n }\n\n const result = await this.commitSessionEntries(session.id, session.entries, entries);\n // Idempotent: a re-commit of an already-committed session re-runs the same\n // writes; every entry hits the skip-if-unchanged path (existing.cid === cid),\n // so no new changelog row + liveSeq unchanged.\n await this.uploadSessionStore.markCommitted(session.id);\n return { success: true, data: result };\n }\n\n @Actions.Exec(\n \"/\",\n \"abort-upload\",\n \"Abort an upload session; staged objects become GC candidates\",\n {\n effect: \"write\",\n },\n )\n async execAbortUpload(_ctx: RouteContext, args: Record<string, unknown>): Promise<AFSExecResult> {\n if (!this.uploadSessionStore) {\n return this.uploadErr(\"AFS_UNSUPPORTED\", \"upload plane not available\");\n }\n const parsed = AbortUploadArgsSchema.safeParse(args);\n if (!parsed.success) {\n return this.uploadErr(\"AFS_VALIDATION_ERROR\", zodMessage(parsed.error));\n }\n const session = await this.uploadSessionStore.getSession(parsed.data.sessionId);\n if (!this.ownsSession(session)) {\n return this.uploadErr(\"AFS_NOT_FOUND\", \"unknown upload session\");\n }\n await this.uploadSessionStore.markAborted(session.id);\n // Staged-but-uncommitted objects: enqueue for GC cleanup. Once the session\n // is no longer `prepared` it loses the in-flight UNION protection\n // (reference-check.ts), so an orphan object is reclaimed on the next sweep.\n if (this.gcQueue) {\n const orphanCids = [\n ...new Set(session.entries.filter((e) => e.status !== \"committed\").map((e) => e.cid)),\n ];\n if (orphanCids.length > 0) await this.gcQueue.enqueue(orphanCids);\n }\n return { success: true, data: { sessionId: session.id, status: \"aborted\" } };\n }\n\n /**\n * Resolve the immutable-merge-key set: `createdAt` is always preserved, plus\n * any caller-supplied lifecycle fields (e.g. `status`).\n */\n private resolveImmutableMergeKeys(extra?: string[]): ReadonlySet<string> {\n const keys = new Set<string>([\"createdAt\"]);\n for (const k of extra ?? []) keys.add(k);\n return keys;\n }\n\n /** Extract the JSON record object from a write payload's `content`. */\n private parseRecordBody(content: unknown): Record<string, unknown> | null {\n if (\n content !== null &&\n typeof content === \"object\" &&\n !Array.isArray(content) &&\n !(content instanceof Uint8Array) &&\n !(content instanceof ArrayBuffer)\n ) {\n return content as Record<string, unknown>;\n }\n if (typeof content === \"string\") {\n try {\n const v = JSON.parse(content);\n return v !== null && typeof v === \"object\" && !Array.isArray(v)\n ? (v as Record<string, unknown>)\n : null;\n } catch {\n return null;\n }\n }\n return null;\n }\n\n /**\n * Stamp the dedup identity into a write's meta so the writeHandler can project\n * it onto the entry's `dedup_scope` / `dedup_key` columns (#1159). `dedupKey`\n * stays in the metadata blob (observability / collection-query); on a merge\n * we drop `createdAt` so the index keeps the original file ctime (R1,\n * feed-sort §5.1).\n */\n private stampDedupMeta(\n base: Record<string, unknown> | null | undefined,\n dedupScope: string,\n dedupKey: string,\n isDuplicate: boolean,\n ): Record<string, unknown> {\n const meta: Record<string, unknown> = { ...(base ?? {}) };\n meta.dedupKey = dedupKey;\n meta.dedupScope = dedupScope;\n if (isDuplicate) delete meta.createdAt;\n return meta;\n }\n\n /**\n * Dedup-on-write core (#492 / #1159) — the `options.dedupBy` upsert behind the\n * standard `write` / `batchWrite`. The record's `dedupBy` field (URL-valued)\n * is normalized into a `dedupKey`; the record lands at a STABLE readable path\n * (`{collection}/{uuid}.json`) and dedup resolves through the tree-index's\n * `(scope, dedup_scope, dedup_key)` secondary UNIQUE index — NOT a\n * cid-in-path filename (which silently orphaned records written under any\n * other layout, #1159). On a hit the incoming record is MERGED\n * (non-degrading) into the existing entry AT ITS REAL PATH. Concurrency-safe:\n * a racing create collides on the UNIQUE index, and the loser re-queries the\n * index and merges (bounded retry). Records missing the field are written\n * normally under the collection (no dedup).\n */\n private async upsertByDedupKey(\n path: string,\n content: AFSWriteEntryPayload,\n options: AFSWriteOptions,\n dedupBy: string,\n ): Promise<AFSWriteResult> {\n if (!this.treeIndex.findByDedupKey) {\n throw new AFSValidationError(\n \"dedup-on-write (dedupBy) is not supported by this DID Space index\",\n );\n }\n const { dedupBy: _by, dedupKey: _dk, mergeImmutableFields, ...baseOpts } = options;\n const body = this.parseRecordBody(content.content);\n const rawVal = body && typeof body[dedupBy] === \"string\" ? (body[dedupBy] as string) : null;\n\n // No usable key value → fresh entry under the collection (no dedup). `path`\n // is the collection directory, so we mint a random basename.\n if (!body || !rawVal) {\n const fresh = joinURL(\"/\", path, `${crypto.randomUUID()}.json`);\n const res = await super.write(fresh, content, baseOpts);\n return { ...res, deduped: false };\n }\n\n const dedupKey = normalizeItemUrl(rawVal);\n // The collection the record dedups within — decoupled from the row's\n // physical parent so flat + legacy dir-per-record layouts share one scope.\n const dedupScope = this.treePath(joinURL(\"/\", path));\n const immutable = this.resolveImmutableMergeKeys(mergeImmutableFields);\n\n const MAX_ATTEMPTS = 4;\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {\n const existing = await this.treeIndex.findByDedupKey(dedupScope, dedupKey);\n\n if (existing) {\n // Merge into the existing entry AT ITS REAL PATH (in place).\n const target = `/${existing.path}`;\n let existingBody: Record<string, unknown> | null = null;\n let version: string | undefined;\n try {\n const readResult = await this.read(target);\n existingBody = this.parseRecordBody(readResult.data?.content);\n version = (readResult.data?.meta as { version?: string } | undefined)?.version;\n } catch (err) {\n // Index pointed at a since-deleted path → re-query (miss → create).\n if (err instanceof AFSNotFoundError) continue;\n throw err;\n }\n const mergedBody =\n existingBody !== null ? mergeItemContent(existingBody, body, immutable) : { ...body };\n const meta = this.stampDedupMeta(content.meta, dedupScope, dedupKey, true);\n // Optimistic concurrency on the merge target: a concurrent merge to the\n // same path is detected and retried. A caller-supplied ifMatch is theirs.\n const callerIfMatch = baseOpts.ifMatch;\n const ifMatch = callerIfMatch ?? version;\n try {\n const res = await super.write(\n target,\n { ...content, content: mergedBody, meta },\n ifMatch ? { ...baseOpts, ifMatch } : baseOpts,\n );\n return { ...res, deduped: true };\n } catch (err) {\n if (err instanceof AFSConflictError && callerIfMatch === undefined) continue;\n throw err;\n }\n }\n\n // No existing → create a NEW flat entry. The partial UNIQUE index is the\n // concurrency backstop: a racing create collides here, we re-query and\n // merge on the next iteration.\n const fresh = joinURL(\"/\", path, `${crypto.randomUUID()}.json`);\n const meta = this.stampDedupMeta(content.meta, dedupScope, dedupKey, false);\n try {\n const res = await super.write(fresh, { ...content, content: body, meta }, baseOpts);\n return { ...res, deduped: false };\n } catch (err) {\n // A concurrent create may have won the UNIQUE race. If the index now\n // holds this key, loop → the next iteration merges into the winner.\n const now = await this.treeIndex.findByDedupKey(dedupScope, dedupKey);\n if (now) continue;\n throw err;\n }\n }\n throw new AFSConflictError(joinURL(\"/\", path), {});\n }\n\n /**\n * One-time reindex/backfill seam (#1159 — run from a deferred one-shot\n * script, NOT on the write hot path). Populates the dedup columns for\n * EXISTING records under `collection` so pre-feature entries (old\n * `{slug}.json` / `{uuid}/item.json` / `{cid}.json` layouts) become\n * dedup-able — fixing the \"an already-saved URL's first re-save duplicates\"\n * bug. Reads each record, extracts + normalizes `record[dedupBy]`, and writes\n * the dedup columns INDEX-ONLY (no changelog / no cid change) via\n * `TreeIndex.setDedupKey`. Records missing the field, and genuine\n * pre-existing duplicates (which would violate the UNIQUE index), are\n * skipped. Idempotent.\n */\n async reindexDedupKeys(\n collection: string,\n dedupBy: string,\n ): Promise<{ scanned: number; indexed: number; skipped: number }> {\n if (!this.treeIndex.setDedupKey) {\n throw new AFSValidationError(\"reindexDedupKeys is not supported by this DID Space index\");\n }\n const dedupScope = this.treePath(joinURL(\"/\", collection));\n const listPrefix = dedupScope.endsWith(\"/\") ? dedupScope : `${dedupScope}/`;\n let scanned = 0;\n let indexed = 0;\n let skipped = 0;\n let cursor: string | undefined;\n do {\n const page = await this.treeIndex.listEntries(listPrefix, { limit: 500, cursor });\n for (const e of page.entries) {\n scanned++;\n let body: Record<string, unknown> | null = null;\n try {\n const r = await this.read(`/${e.path}`);\n body = this.parseRecordBody(r.data?.content);\n } catch {\n skipped++;\n continue;\n }\n const raw = body && typeof body[dedupBy] === \"string\" ? (body[dedupBy] as string) : null;\n if (!raw) {\n skipped++;\n continue;\n }\n try {\n await this.treeIndex.setDedupKey(e.path, dedupScope, normalizeItemUrl(raw), {\n deviceId: this.deviceId,\n });\n indexed++;\n } catch {\n // UNIQUE violation → a genuine pre-existing duplicate; leave it out.\n skipped++;\n }\n }\n cursor = page.hasMore ? page.cursor : undefined;\n } while (cursor);\n return { scanned, indexed, skipped };\n }\n\n /**\n * Standard write, extended with the dedup-on-write upsert policy (#492 /\n * #1159). When `options.dedupBy` (canonical) or the deprecated `dedupKey`\n * alias is set the write becomes a secondary-index upsert (see\n * {@link upsertByDedupKey}); otherwise it is the base provider's write.\n */\n override async write(\n path: string,\n content: AFSWriteEntryPayload,\n options?: AFSWriteOptions,\n ): Promise<AFSWriteResult> {\n const dedupBy = options?.dedupBy ?? options?.dedupKey;\n if (dedupBy) {\n return this.upsertByDedupKey(path, content, options as AFSWriteOptions, dedupBy);\n }\n return super.write(path, content, options);\n }\n\n /**\n * The commit write — mirrors `batchWrite` steps 2/6/7/8 WITHOUT the R2 byte\n * leg (existence is trusted, §8): preread → ifMatch/skip → batchPutEntries →\n * GC bookkeeping → share hooks → per-entry results. `cid`/`size`/`mimeType`\n * come from the SESSION record (the prepared contract, re-validated against\n * the client's entries); `deviceId`/`mtime` are client provenance threaded to\n * the changelog (echo防回环, §6.1).\n */\n private async commitSessionEntries(\n sessionId: string,\n sessionEntries: ReadonlyArray<UploadSessionEntryInput>,\n clientEntries: ReadonlyArray<{\n path: string;\n cid: string;\n size: number;\n mimeType?: string;\n ifMatch?: string;\n deviceId?: string;\n mtime?: number;\n /** Optional cid-verified inline text copy (inline-content-commit §5.1). */\n content?: string;\n /** Optional application metadata to persist (did-space-metadata G2). */\n metadata?: Record<string, unknown>;\n }>,\n ): Promise<{\n ok: true;\n results: Array<Record<string, unknown>>;\n succeeded: number;\n failed: number;\n }> {\n const byPath = new Map(sessionEntries.map((e) => [joinURL(\"/\", e.path), e]));\n interface CommitItem {\n i: number;\n afsPath: string;\n treePath: string;\n cid: string;\n treeEntry: TreeEntry;\n deviceId: string;\n ifMatch?: string;\n }\n const results: Array<Record<string, unknown>> = new Array(clientEntries.length);\n const prepared: CommitItem[] = [];\n\n for (let i = 0; i < clientEntries.length; i++) {\n const c = clientEntries[i]!;\n const afsPath = joinURL(\"/\", c.path);\n const pv = this.validateActionPath(afsPath);\n if (!pv.ok) {\n results[i] = {\n path: afsPath,\n success: false,\n error: pv.reason,\n code: \"AFS_VALIDATION_ERROR\",\n };\n continue;\n }\n // Re-validate against the prepared contract (never trust client proof, §7.2).\n const se = byPath.get(afsPath);\n if (!se || se.cid !== c.cid) {\n results[i] = {\n path: afsPath,\n success: false,\n error: \"entry not in session, or cid mismatch with prepared contract\",\n code: \"AFS_VALIDATION_ERROR\",\n };\n continue;\n }\n const deviceId =\n typeof c.deviceId === \"string\" && c.deviceId ? c.deviceId : (se.deviceId ?? this.deviceId);\n const mtime = typeof c.mtime === \"number\" ? c.mtime : (se.mtime ?? Date.now());\n // R1 (feed-sort §5.1): file ctime = commit metadata's createdAt when\n // present, else `mtime` (this handler's insert-time fallback is mtime, not\n // now — there is no `payload` here, the source is the commit's `c.metadata`).\n const ctime = resolveCtime(c.metadata as Record<string, unknown> | undefined, mtime);\n const treeEntry: TreeEntry = {\n cid: se.cid,\n size: se.size,\n mtime,\n ctime,\n mimeType: se.mimeType ?? undefined,\n };\n // Inline content (collection-query support, inline-content-commit §5.1):\n // the client may attach a small text copy of the bytes it just PUT.\n // Accept it ONLY when (a) the prepared mime is text — mirror the write\n // path's `decodeInlineText` gate; the query reads the content column with\n // NO mime gate, so a non-text inline would pollute filters — AND (b) it\n // digest-pre-verifies: `base64pad(sha256(content)) === se.checksumSha256`\n // (ONE native SHA-256, no CID rebuild). Mismatch/non-text → drop the copy\n // (NO throw): the object is still checksum-proven in R2, the record just\n // isn't inline-indexed. Over-threshold/NUL copies that pass digest-pre are\n // harmlessly dropped one level down by the index's `resolveInlineContent`\n // (cache miss, not error), so no threshold check is needed here.\n if (c.content !== undefined && isTextMime(se.mimeType ?? undefined)) {\n const digest = await checksumSha256OfContent(c.content);\n if (digest === se.checksumSha256) treeEntry.content = c.content;\n }\n // Application metadata (did-space-metadata G2): strip provider-reserved\n // keys (same ingress discipline as G1/single write — §5 anti-spoof) and\n // bound the size (G1's shared assertMetadataSize, 64KB). NOT digest-\n // verified: metadata is application data, not bytes (design §5), so the\n // content digest gate above and the metadata size gate here are\n // orthogonal. A per-entry size violation fails JUST this entry.\n if (c.metadata) {\n const appMeta = extractApplicationMeta(c.metadata);\n if (appMeta) {\n try {\n assertMetadataSize(appMeta, afsPath);\n } catch (err) {\n results[i] = {\n path: afsPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n code: (err as { code?: string }).code ?? \"AFS_VALIDATION_ERROR\",\n };\n continue;\n }\n treeEntry.metadata = appMeta;\n }\n }\n prepared.push({\n i,\n afsPath,\n treePath: pv.treePath,\n cid: se.cid,\n treeEntry,\n deviceId,\n ...(se.ifMatch ? { ifMatch: se.ifMatch } : {}),\n });\n }\n\n const preread = await this.batchPreread(prepared.map((p) => p.treePath));\n const skipped: CommitItem[] = [];\n let live: CommitItem[] = [];\n for (const p of prepared) {\n const existing = preread.get(p.treePath) ?? null;\n // ifMatch at COMMIT time (design §10) + the D3 expected-absent sentinel\n // (§4.2a) via the one shared predicate — the prepared contract's ifMatch is\n // checked against the CURRENT entry, not prepare-time state.\n if (ifMatchPreconditionFailed(p.ifMatch, existing)) {\n results[p.i] = this.batchConflictFailure(p.afsPath, {\n currentCid: existing?.cid ?? null,\n currentMtime: existing?.mtime ?? null,\n currentDeviceId: null,\n });\n continue;\n }\n // NO provider-level cid-match early-skip here (inline-content-commit §5.2):\n // `batchPutEntries` is now the SOLE skip authority. Routing a cid-match to\n // `skipped` before the index would pre-empt the content-aware refill — a\n // row whose cid matches but whose inline `content` column is still NULL\n // (the regression's stuck state) must reach the UPSERT to self-repair.\n // A TRUE no-op (cid+mime+content all equal) comes back as `r.skipped`\n // below and is routed to the skipped bucket there.\n live.push(p);\n }\n\n // share pre-io (survivors). No R2 put — existence is trusted (§8).\n const preIoOk: CommitItem[] = [];\n for (const p of live) {\n try {\n await applyShareWriteHook({\n ...this.shareHookArgs(p.afsPath, p.treePath),\n bytes: new Uint8Array(0), // metadata commit — no bytes available\n cid: p.cid,\n resolver: this.shareResolver,\n phase: \"pre-io\",\n });\n preIoOk.push(p);\n } catch (err) {\n results[p.i] = {\n path: p.afsPath,\n success: false,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n live = preIoOk;\n\n let indexResults: Awaited<ReturnType<NonNullable<TreeIndex[\"batchPutEntries\"]>>> = [];\n if (live.length > 0) {\n const batchEntries: BatchPutEntry[] = live.map((p) => ({\n path: p.treePath,\n entry: p.treeEntry,\n opts: { deviceId: p.deviceId },\n }));\n indexResults = this.treeIndex.batchPutEntries\n ? await this.treeIndex.batchPutEntries(batchEntries, { preread })\n : await loopBatchPutEntries(this.treeIndex, batchEntries, { preread });\n }\n\n const written: Array<{ p: CommitItem; oldCid?: string; liveSeq?: number }> = [];\n live.forEach((p, j) => {\n const r = indexResults[j];\n if (!r) {\n results[p.i] = { path: p.afsPath, success: false, error: \"index batch returned no result\" };\n return;\n }\n if (r.conflict) {\n results[p.i] = this.batchConflictFailure(p.afsPath, r.conflict);\n return;\n }\n if (r.error) {\n results[p.i] = { path: p.afsPath, success: false, error: r.error };\n return;\n }\n // True no-op (cid+mime+content all equal) → route to the skipped bucket\n // (inline-content-commit §5.2 step 4c, a direct consequence of dropping the\n // provider-level early-skip above): keeps post-io share hooks written-only\n // and GC re-referenced = written + skipped (both unchanged); a no-op must\n // NOT fire a post-io share reconcile.\n if (r.skipped) {\n skipped.push(p);\n return;\n }\n written.push({ p, oldCid: r.oldCid, liveSeq: r.liveSeq });\n });\n\n // GC bookkeeping (mirror batchWrite step 7): re-referenced cids (written +\n // skipped) rescued from the queue; replaced oldCids enqueued.\n if (this.gcQueue) {\n const reReferenced = [\n ...new Set([...written.map((w) => w.p.cid), ...skipped.map((s) => s.cid)]),\n ];\n if (reReferenced.length > 0) {\n if (this.gcQueue.removeMany) await this.gcQueue.removeMany(reReferenced);\n else for (const cid of reReferenced) await this.gcQueue.remove(cid);\n }\n const replaced = [\n ...new Set(\n written.filter((w) => w.oldCid && w.oldCid !== w.p.cid).map((w) => w.oldCid as string),\n ),\n ];\n if (replaced.length > 0) await this.gcQueue.enqueue(replaced);\n }\n\n // share post-io (written only).\n for (const w of written) {\n try {\n await applyShareWriteHook({\n ...this.shareHookArgs(w.p.afsPath, w.p.treePath),\n bytes: new Uint8Array(0),\n cid: w.p.cid,\n resolver: this.shareResolver,\n phase: \"post-io\",\n });\n } catch {\n // post-io failure does not unwind the persisted write (same half-done\n // window as the single-op path); the entry still reports success below.\n }\n }\n\n // per-entry results — mirror batchWrite: { status:200, ok:true, data:{ path, meta:{ cid, liveSeq } } }.\n const commitOk = (p: CommitItem, liveSeq?: number): Record<string, unknown> => ({\n status: 200,\n ok: true,\n data: {\n path: p.afsPath,\n meta: { cid: p.cid, liveSeq: liveSeq != null ? String(liveSeq) : undefined },\n },\n });\n for (const w of written) results[w.p.i] = commitOk(w.p, w.liveSeq);\n for (const s of skipped) {\n let liveSeq: number | undefined;\n if (this.treeIndex.getPrefixWatermark) {\n liveSeq = (await this.treeIndex.getPrefixWatermark(s.treePath)) ?? undefined;\n }\n results[s.i] = commitOk(s, liveSeq);\n }\n\n // mark committed entries in the session.\n const committedPaths = [...written, ...skipped.map((s) => ({ p: s }))].map((w) => ({\n path: w.p.afsPath,\n status: \"committed\" as const,\n }));\n if (committedPaths.length > 0)\n await this.uploadSessionStore?.markEntries(sessionId, committedPaths);\n\n const succeeded = results.filter((r) => r?.ok === true).length;\n return { ok: true, results, succeeded, failed: results.length - succeeded };\n }\n\n /**\n * Native batch delete — same merge without the R2 leg: ONE preread → GC\n * enqueue (before delete, single-op ordering) → ONE atomic index batch →\n * share delete hooks. FILE entries only (no directory fallback — sync\n * never dir-deletes; a dir path fails per entry with 404).\n */\n async batchDelete(\n entries: AFSBatchDeleteEntry[],\n _options?: AFSOperationOptions,\n ): Promise<AFSBatchDeleteResult> {\n const results: AFSBatchDeleteResult[\"results\"] = new Array(entries.length);\n\n interface PreparedDel {\n i: number;\n afsPath: string;\n treePath: string;\n deviceId: string;\n mtime?: number;\n ifMatch?: string;\n }\n const prepared: PreparedDel[] = [];\n for (let i = 0; i < entries.length; i++) {\n const entry = entries[i]!;\n const afsPath = joinURL(\"/\", entry.path);\n if (this.isVirtualPath(afsPath) || isShareReservedPath(afsPath)) {\n results[i] = {\n path: afsPath,\n success: false,\n error: `Forbidden at ${afsPath}: virtual_path`,\n code: \"AFS_FORBIDDEN\",\n };\n continue;\n }\n const deleteMeta = (entry.options as AFSDeleteOptions | undefined)?.meta;\n prepared.push({\n i,\n afsPath,\n treePath: this.treePath(afsPath),\n deviceId:\n typeof deleteMeta?.deviceId === \"string\" && deleteMeta.deviceId\n ? deleteMeta.deviceId\n : this.deviceId,\n ...(typeof deleteMeta?.mtime === \"number\" ? { mtime: deleteMeta.mtime } : {}),\n ...(typeof deleteMeta?.ifMatch === \"string\" ? { ifMatch: deleteMeta.ifMatch } : {}),\n });\n }\n\n const preread = await this.batchPreread(prepared.map((p) => p.treePath));\n\n const live: PreparedDel[] = [];\n for (const p of prepared) {\n const existing = preread.get(p.treePath) ?? null;\n if (p.ifMatch !== undefined && (!existing || existing.cid !== p.ifMatch)) {\n results[p.i] = this.batchConflictFailure(p.afsPath, {\n currentCid: existing?.cid ?? null,\n currentMtime: existing?.mtime ?? null,\n currentDeviceId: null,\n });\n continue;\n }\n if (!existing) {\n results[p.i] = {\n path: p.afsPath,\n success: false,\n error: `Path not found: ${p.afsPath}`,\n code: \"AFS_NOT_FOUND\",\n };\n continue;\n }\n live.push(p);\n }\n\n // Enqueue BEFORE delete (single-op ordering: a failed enqueue leaves the\n // tree untouched; a failed delete after enqueue is safe — still referenced).\n if (this.gcQueue && live.length > 0) {\n const cids = [\n ...new Set(live.map((p) => (preread.get(p.treePath) ?? null)?.cid).filter(Boolean)),\n ] as string[];\n if (cids.length > 0) await this.gcQueue.enqueue(cids);\n }\n\n if (live.length > 0) {\n const batchEntries: BatchDeleteEntry[] = live.map((p) => ({\n path: p.treePath,\n opts: {\n deviceId: p.deviceId,\n ...(p.mtime !== undefined ? { mtime: p.mtime } : {}),\n },\n }));\n let indexResults: Awaited<ReturnType<NonNullable<TreeIndex[\"batchDeleteEntries\"]>>>;\n try {\n indexResults = this.treeIndex.batchDeleteEntries\n ? await this.treeIndex.batchDeleteEntries(batchEntries, { preread })\n : await loopBatchDeleteEntries(this.treeIndex, batchEntries, { preread });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n for (const p of live) results[p.i] = { path: p.afsPath, success: false, error: message };\n const succeededEarly = results.filter((r) => r?.success).length;\n return { results, succeeded: succeededEarly, failed: results.length - succeededEarly };\n }\n\n for (let j = 0; j < live.length; j++) {\n const p = live[j]!;\n const r = indexResults[j];\n if (!r || r.error || r.conflict || r.notFound) {\n results[p.i] = r?.conflict\n ? this.batchConflictFailure(p.afsPath, r.conflict)\n : {\n path: p.afsPath,\n success: false,\n error: r?.error ?? `Path not found: ${p.afsPath}`,\n ...(r?.notFound ? { code: \"AFS_NOT_FOUND\" } : {}),\n };\n continue;\n }\n await applyShareDeleteHook({\n ...this.shareHookArgs(p.afsPath, p.treePath),\n resolver: this.shareResolver,\n });\n if (p.afsPath.endsWith(\".ash\")) {\n this.emit({\n type: SCRIPT_EVENT_TYPES.UNREGISTERED,\n path: p.afsPath,\n data: { runtime: \"ash\" },\n });\n }\n results[p.i] = { path: p.afsPath, success: true };\n }\n }\n\n const succeeded = results.filter((r) => r?.success).length;\n return { results, succeeded, failed: results.length - succeeded };\n }\n\n // ========== Stat ==========\n\n @Stat(\"/:path*\")\n async statHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSStatResult> {\n const afsPath = joinURL(\"/\", ctx.params.path ?? \"\");\n\n if (afsPath === \"/\") {\n const childrenCount = await this.treeIndex.countChildren(this.treeListPrefix(\"/\"));\n return { data: { id: \"/\", path: \"/\", meta: { kind: \"did-space:root\", childrenCount } } };\n }\n\n // stat returns metadata only (size / cid / mimeType / version) — never the\n // inline bytes, so skip projecting content (projection audit).\n const entry = await this.treeIndex.get(this.treePath(afsPath), { includeContent: false });\n if (entry) {\n return {\n data: {\n id: afsPath.split(\"/\").pop() || afsPath,\n path: afsPath,\n meta: {\n kind: \"did-space:file\",\n size: entry.size,\n cid: entry.cid,\n mimeType: entry.mimeType,\n // Opaque optimistic-concurrency version (EXT-4). The CID is itself a\n // content hash, so it doubles as the version token at zero extra\n // storage — callers round-trip it verbatim via AFSWriteOptions.ifMatch\n // / AFSDeleteOptions.meta.ifMatch and must not parse it.\n version: entry.cid,\n },\n createdAt: new Date(entry.ctime),\n updatedAt: new Date(entry.mtime),\n },\n };\n }\n\n if (await this.isDirectory(afsPath)) {\n const prefix = this.treeListPrefix(afsPath);\n const childrenCount = await this.treeIndex.countChildren(prefix);\n const meta: AFSEntryMetadata = { kind: \"did-space:directory\", childrenCount };\n // Expose the collection-root watermark on directory stat (Live Update\n // Resilience 1a / IC-3): the client's edge reconcile reads THIS to detect\n // changes in O(1) — one watermark row, no list scan — instead of reusing a\n // stale list liveSeq. Prefix-local (same I3 contract as list/query liveSeq).\n if (this.treeIndex.getPrefixWatermark) {\n const version = await this.treeIndex.getPrefixWatermark(prefix);\n if (version != null) (meta as Record<string, unknown>).liveSeq = String(version);\n }\n // Directory created/modified: the scaffolded dir row carries ctime/mtime\n // (R2 stamps the direct parent on write), but get() skips cid-less dir\n // rows — so read them explicitly. Absent (scope root / unwritten dir) ⇒\n // omit, exactly as before. One indexed point-lookup; dir stat is cold.\n const stat: AFSStatResult[\"data\"] = {\n id: afsPath.split(\"/\").pop() || afsPath,\n path: afsPath,\n meta,\n };\n const dirTimes = await this.treeIndex.getDirTimes?.(prefix);\n if (dirTimes) {\n stat.createdAt = new Date(dirTimes.ctime);\n stat.updatedAt = new Date(dirTimes.mtime);\n }\n return { data: stat };\n }\n\n throw new AFSNotFoundError(afsPath);\n }\n\n // ========== Search ==========\n\n @Search(\"/:path*\")\n async searchHandler(\n ctx: RouteContext<{ path?: string }>,\n query: string,\n options?: AFSSearchOptions,\n ): Promise<{ data: AFSEntry[]; total: number }> {\n const afsPath = ctx.params.path ? `/${ctx.params.path}` : \"/\";\n const pattern = query || \"\";\n const limit = options?.limit || 50;\n\n if (!pattern) return { data: [], total: 0 };\n\n const prefix = this.treeListPrefix(afsPath);\n const results: AFSEntry[] = [];\n let cursor: string | undefined;\n const searchQuery = pattern.toLowerCase();\n\n do {\n const listResult = await this.treeIndex.list(prefix, {\n limit: LIST_MAX_LIMIT,\n cursor,\n });\n\n for (const treeListEntry of listResult.entries) {\n if (results.length >= limit) break;\n\n const path = `/${treeListEntry.path}`;\n const name = path.split(\"/\").pop() || \"\";\n\n // Search by name\n if (name.toLowerCase().includes(searchQuery)) {\n results.push(this.buildEntry(path, {}));\n continue;\n }\n\n // Search by content (skip binary files). The body is fetched from the\n // object store below (not entry.content), so no inline projection here.\n const treeEntry = await this.treeIndex.get(treeListEntry.path, { includeContent: false });\n if (treeEntry) {\n if (!isTextMime(treeEntry.mimeType)) continue;\n const obj = await this.objectStore.get(this.objectKey(treeEntry.cid));\n if (obj) {\n const content = await obj.text();\n if (content.toLowerCase().includes(searchQuery)) {\n results.push(this.buildEntry(path, { content }));\n }\n }\n }\n }\n\n cursor = listResult.hasMore ? listResult.cursor : undefined;\n } while (cursor && results.length < limit);\n\n return { data: results, total: results.length };\n }\n\n // ========== Explain ==========\n\n @Explain(\"/:path*\")\n async explainHandler(ctx: RouteContext<{ path?: string }>): Promise<AFSExplainResult> {\n const afsPath = joinURL(\"/\", ctx.params.path ?? \"\");\n const lines: string[] = [];\n lines.push(`# DID Space: ${afsPath}`);\n lines.push(\"\");\n\n if (afsPath === \"/\") {\n lines.push(`DID: ${this.did}`);\n lines.push(\"\");\n lines.push(this.description || \"DID-scoped persistent storage with CID-based deduplication\");\n lines.push(\"\");\n lines.push(\"## Operations\");\n lines.push(\"- `list /` — List root files and directories\");\n lines.push(\"- `read /{path}` — Read file content\");\n lines.push(\"- `write /{path}` — Write file (content-addressed dedup)\");\n lines.push(\"- `delete /{path}` — Delete file entry (lazy GC)\");\n } else {\n const entry = await this.treeIndex.get(this.treePath(afsPath), { includeContent: false });\n if (entry) {\n lines.push(`DID: ${this.did}`);\n lines.push(`Path: ${afsPath}`);\n lines.push(`Size: ${entry.size} bytes`);\n lines.push(`CID: ${entry.cid}`);\n lines.push(`MIME: ${entry.mimeType ?? \"unknown\"}`);\n lines.push(`Created: ${new Date(entry.ctime).toISOString()}`);\n lines.push(`Modified: ${new Date(entry.mtime).toISOString()}`);\n } else if (await this.isDirectory(afsPath)) {\n lines.push(`DID: ${this.did}`);\n lines.push(`Virtual directory: ${afsPath}`);\n lines.push(\"Use `list` to see contents.\");\n } else {\n lines.push(\"Path not found.\");\n }\n }\n\n return { format: \"markdown\", content: lines.join(\"\\n\") };\n }\n\n // ========== internalWrite / internalDelete — bypass D4 ==========\n //\n // These methods are called by the SyncEngine (Phase 2) to write/delete\n // without the D4 virtual path check. They mirror CloudflareDIDSpace's\n // internalWrite/internalDelete API so the SyncEngine can treat both\n // backends uniformly.\n\n /**\n * Write content to the provider, bypassing D4 virtual path protection.\n * Stores content to objectStore and treeIndex with the given deviceId.\n */\n async internalWrite(\n afsPath: string,\n opts: {\n content: Uint8Array;\n deviceId: string;\n mtime?: number;\n mimeType?: string;\n metadata?: Record<string, unknown>;\n },\n ): Promise<{ cid: string; oldCid?: string }> {\n // Phase 0.4: block SyncEngine writes to reserved share virtual paths\n if (isShareReservedPath(afsPath)) {\n throw new AFSForbiddenError(afsPath, \"share-path-reserved\");\n }\n\n const { content, deviceId, mtime, mimeType: explicitMimeType, metadata } = opts;\n\n let bytes: Uint8Array;\n let storeValue: string | ArrayBuffer;\n if (content instanceof Uint8Array) {\n bytes = content;\n storeValue = bytes.buffer as ArrayBuffer;\n } else {\n bytes = new Uint8Array(content);\n storeValue = bytes.buffer as ArrayBuffer;\n }\n\n const cid = await computeCID(bytes);\n const objKey = this.objectKey(cid);\n const treePath = this.treePath(afsPath);\n\n // Phase 0.4: pre-io share hook (before R2 PUT)\n await applyShareWriteHook({\n ...this.shareHookArgs(afsPath, treePath),\n bytes,\n cid,\n resolver: this.shareResolver,\n phase: \"pre-io\",\n });\n\n const existing = await this.objectStore.head(objKey);\n if (!existing) {\n await this.objectStore.put(objKey, storeValue);\n }\n\n const now = mtime ?? Date.now();\n const detectedMime = explicitMimeType ?? detectMimeType(afsPath) ?? undefined;\n // R1 (feed-sort §5.1 row 4): local-copy ctime from the SyncEngine-supplied\n // application createdAt (else the write time). internalWrite NEVER parses\n // bytes — the engine derived `metadata` via readApplicationMetadata. mtime\n // stays `now` (the LWW/origin timestamp — Rule R never touches it).\n const ctime = resolveCtime(metadata, now);\n const treeEntry: TreeEntry = {\n cid,\n size: bytes.length,\n mtime: now,\n ctime,\n mimeType: detectedMime,\n };\n // Persist app metadata so the tree-index can stamp the direct-parent DIR\n // row (R2) on this local copy and skip-if-unchanged still sees createdAt\n // changes. Reserved keys stripped (same ingress discipline as writeHandler).\n const appMeta = extractApplicationMeta(metadata);\n if (appMeta) treeEntry.metadata = appMeta;\n // Layer 0 inline content (1d): sync writes carry bytes — offer them as\n // text when they decode as UTF-8 (small + text mime only; the index\n // re-verifies the cid and applies its own threshold). Best-effort: an\n // undecodable payload simply isn't inlined.\n const inlineText = decodeInlineText(bytes, detectedMime);\n if (inlineText !== null) treeEntry.content = inlineText;\n\n const { oldCid } = await this.treeIndex.put(treePath, treeEntry, { deviceId });\n\n if (this.gcQueue) {\n // §4.7.1 write-dequeue — see writeHandler.\n await this.gcQueue.remove(cid);\n if (oldCid && oldCid !== cid) {\n await this.gcQueue.enqueue([oldCid]);\n }\n }\n\n // Phase 0.4: post-io share hook (after tree_entries written)\n await applyShareWriteHook({\n ...this.shareHookArgs(afsPath, treePath),\n bytes,\n cid,\n resolver: this.shareResolver,\n phase: \"post-io\",\n });\n\n // #674: blocklet publish/resolve hook (SyncEngine write path).\n await applyBlockletWriteHook({\n ...this.blockletHookArgs(afsPath, treePath),\n bytes,\n resolver: this.blockletResolver,\n });\n\n return oldCid === undefined ? { cid } : { cid, oldCid };\n }\n\n /**\n * Delete a file from the provider, bypassing D4 virtual path protection.\n */\n async internalDelete(\n afsPath: string,\n opts: { deviceId: string; mtime?: number },\n ): Promise<{ deleted: boolean }> {\n // Phase 0.4: block SyncEngine deletes to reserved share virtual paths\n if (isShareReservedPath(afsPath)) {\n throw new AFSForbiddenError(afsPath, \"share-path-reserved\");\n }\n\n const treePath = this.treePath(afsPath);\n const entry = await this.treeIndex.get(treePath, { includeContent: false });\n if (!entry) {\n return { deleted: false };\n }\n\n await this.gcQueue?.enqueue([entry.cid]);\n await this.treeIndex.delete(treePath, { deviceId: opts.deviceId });\n\n // Phase 0.4: delete hook (after tree_entries removed)\n await applyShareDeleteHook({\n ...this.shareHookArgs(afsPath, treePath),\n resolver: this.shareResolver,\n });\n\n // #674: blocklet unregister (SyncEngine delete path).\n await applyBlockletDeleteHook({\n ...this.blockletHookArgs(afsPath, treePath),\n resolver: this.blockletResolver,\n });\n\n return { deleted: true };\n }\n\n // ========== Capabilities ==========\n\n capabilities(): CapabilitiesManifest {\n return {\n schemaVersion: 1,\n provider: this.name,\n tools: [],\n actions: [],\n operations: this.getOperationsDeclaration(),\n };\n }\n}\n"],"mappings":"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"}