fedipod-server 0.28.1 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (438) hide show
  1. package/README.md +38 -34
  2. package/config/server.json +22 -0
  3. package/dist/claims.js +3 -2
  4. package/dist/directory.d.ts +2 -0
  5. package/dist/door.d.ts +4 -0
  6. package/dist/door.js +31 -0
  7. package/dist/fedipod.d.ts +16 -0
  8. package/dist/fedipod.js +13 -0
  9. package/dist/front.d.ts +3 -0
  10. package/dist/front.js +94 -0
  11. package/dist/handler.d.ts +39 -101
  12. package/dist/handler.js +86 -617
  13. package/dist/handler.jsonld +6 -30
  14. package/dist/identities.d.ts +62 -0
  15. package/dist/identities.js +236 -0
  16. package/dist/mounts.d.ts +43 -0
  17. package/dist/mounts.js +123 -0
  18. package/dist/opt-in.d.ts +46 -0
  19. package/dist/opt-in.js +176 -0
  20. package/dist/store-pod.js +37 -0
  21. package/package.json +10 -18
  22. package/lib/client/c2s.mjs +0 -582
  23. package/lib/client/localapi.mjs +0 -87
  24. package/lib/client/masto/accounts.mjs +0 -309
  25. package/lib/client/masto/body.mjs +0 -156
  26. package/lib/client/masto/index.mjs +0 -206
  27. package/lib/client/masto/instance.mjs +0 -112
  28. package/lib/client/masto/media.mjs +0 -79
  29. package/lib/client/masto/oauth.mjs +0 -656
  30. package/lib/client/masto/render.mjs +0 -518
  31. package/lib/client/masto/statuses.mjs +0 -372
  32. package/lib/client/masto/timelines.mjs +0 -438
  33. package/lib/client/oidc-auth.mjs +0 -62
  34. package/lib/client/streaming.mjs +0 -154
  35. package/lib/client/webpush.mjs +0 -98
  36. package/lib/connections/acctfeed.mjs +0 -257
  37. package/lib/connections/atproto.mjs +0 -309
  38. package/lib/connections/bskyfeed.mjs +0 -243
  39. package/lib/connections/bskygroup.mjs +0 -162
  40. package/lib/connections/fediacct.mjs +0 -253
  41. package/lib/connections/import.mjs +0 -357
  42. package/lib/connections/tagfeed.mjs +0 -212
  43. package/lib/connections/vault.mjs +0 -114
  44. package/lib/core/as2.mjs +0 -206
  45. package/lib/core/contexts/activitystreams.json +0 -379
  46. package/lib/core/contexts/anno.json +0 -126
  47. package/lib/core/contexts/did-v1.json +0 -57
  48. package/lib/core/contexts/fep-5711.json +0 -36
  49. package/lib/core/contexts/gotosocial.json +0 -86
  50. package/lib/core/contexts/identity-v1.json +0 -152
  51. package/lib/core/contexts/index.mjs +0 -63
  52. package/lib/core/contexts/join-lemmy.json +0 -33
  53. package/lib/core/contexts/joinmastodon.json +0 -28
  54. package/lib/core/contexts/litepub-0.1.json +0 -60
  55. package/lib/core/contexts/map.json +0 -19
  56. package/lib/core/contexts/miscellany.json +0 -19
  57. package/lib/core/contexts/quotes.json +0 -18
  58. package/lib/core/contexts/schemaorg.json +0 -8845
  59. package/lib/core/contexts/security-data-integrity-v1.json +0 -78
  60. package/lib/core/contexts/security-data-integrity-v2.json +0 -81
  61. package/lib/core/contexts/security-multikey-v1.json +0 -35
  62. package/lib/core/contexts/security-v1.json +0 -74
  63. package/lib/core/contexts/webfinger.json +0 -10
  64. package/lib/core/deliver.mjs +0 -371
  65. package/lib/core/graphview.mjs +0 -327
  66. package/lib/core/intake/activities.mjs +0 -633
  67. package/lib/core/intake/activity.mjs +0 -318
  68. package/lib/core/intake/channel.mjs +0 -144
  69. package/lib/core/intake/group.mjs +0 -256
  70. package/lib/core/intake/index.mjs +0 -701
  71. package/lib/core/intake/notes.mjs +0 -360
  72. package/lib/core/intake/verify.mjs +0 -142
  73. package/lib/core/keys.mjs +0 -153
  74. package/lib/core/lease.mjs +0 -206
  75. package/lib/core/polls.mjs +0 -105
  76. package/lib/core/profile-page.mjs +0 -104
  77. package/lib/core/proof.mjs +0 -79
  78. package/lib/core/publisher/collections.mjs +0 -237
  79. package/lib/core/publisher/index.mjs +0 -500
  80. package/lib/core/publisher/notes.mjs +0 -453
  81. package/lib/core/publisher/questions.mjs +0 -239
  82. package/lib/core/publisher/restore.mjs +0 -224
  83. package/lib/core/shapes/activitystreams.ttl +0 -157
  84. package/lib/core/shapes/index.mjs +0 -132
  85. package/lib/core/shapes/shapes-text.mjs +0 -13
  86. package/lib/core/social.mjs +0 -531
  87. package/lib/core/storage.mjs +0 -176
  88. package/lib/core/store.mjs +0 -568
  89. package/lib/core/wire-quotes.mjs +0 -71
  90. package/lib/core/wire.mjs +0 -889
  91. package/lib/device/account.mjs +0 -87
  92. package/lib/device/admin/index.mjs +0 -13
  93. package/lib/device/admin/origins.mjs +0 -35
  94. package/lib/device/admin/routes/connections.mjs +0 -144
  95. package/lib/device/admin/routes/gateway.mjs +0 -199
  96. package/lib/device/admin/routes/lifecycle.mjs +0 -200
  97. package/lib/device/admin/routes/owner.mjs +0 -322
  98. package/lib/device/admin/routes/setup.mjs +0 -412
  99. package/lib/device/admin/routes/social.mjs +0 -188
  100. package/lib/device/admin/server.mjs +0 -95
  101. package/lib/device/admin/static.mjs +0 -247
  102. package/lib/device/admin/surface.mjs +0 -315
  103. package/lib/device/certs.mjs +0 -281
  104. package/lib/device/cli/commands/account.mjs +0 -586
  105. package/lib/device/cli/commands/run.mjs +0 -278
  106. package/lib/device/cli/commands/service.mjs +0 -221
  107. package/lib/device/cli/commands/setup.mjs +0 -447
  108. package/lib/device/cli/commands/state.mjs +0 -561
  109. package/lib/device/cli/context.mjs +0 -288
  110. package/lib/device/export-collections.mjs +0 -161
  111. package/lib/device/gateway-move.mjs +0 -58
  112. package/lib/device/home.mjs +0 -161
  113. package/lib/device/migrate.mjs +0 -115
  114. package/lib/device/ports.mjs +0 -27
  115. package/lib/device/remote.mjs +0 -54
  116. package/lib/device/setup.mjs +0 -459
  117. package/lib/device/update.mjs +0 -96
  118. package/lib/gateway/caches.mjs +0 -36
  119. package/lib/gateway/directory.mjs +0 -90
  120. package/lib/gateway/front-core.mjs +0 -970
  121. package/lib/gateway/gateway-core.mjs +0 -165
  122. package/lib/gateway/headers.mjs +0 -49
  123. package/lib/gateway/httpsig.mjs +0 -159
  124. package/lib/gateway/notices.mjs +0 -84
  125. package/lib/gateway/quiet.mjs +0 -189
  126. package/lib/pod/README.md +0 -61
  127. package/lib/pod/actor.mjs +0 -96
  128. package/lib/pod/collection.mjs +0 -77
  129. package/lib/pod/containers.mjs +0 -140
  130. package/lib/pod/discovery.mjs +0 -46
  131. package/lib/pod/featured.mjs +0 -18
  132. package/lib/pod/followers.mjs +0 -24
  133. package/lib/pod/following.mjs +0 -10
  134. package/lib/pod/http.mjs +0 -74
  135. package/lib/pod/inbox.mjs +0 -166
  136. package/lib/pod/links.mjs +0 -35
  137. package/lib/pod/media.mjs +0 -27
  138. package/lib/pod/notes.mjs +0 -80
  139. package/lib/pod/notifications.mjs +0 -89
  140. package/lib/pod/outbox.mjs +0 -18
  141. package/lib/pod/package.json +0 -19
  142. package/lib/pod/policy.mjs +0 -58
  143. package/lib/pod/private.mjs +0 -19
  144. package/lib/pod/root.mjs +0 -104
  145. package/lib/pod/state.mjs +0 -40
  146. package/lib/pod/transport.mjs +0 -525
  147. package/lib/pod/urls.mjs +0 -85
  148. package/lib/server/embed.mjs +0 -423
  149. package/lib/session/README.md +0 -137
  150. package/lib/session/demo.html +0 -94
  151. package/lib/session/fedi-account.mjs +0 -408
  152. package/lib/session/fedi-login.mjs +0 -123
  153. package/lib/session/oidc-session.mjs +0 -233
  154. package/lib/session/package.json +0 -49
  155. package/lib/shared/guard.mjs +0 -213
  156. package/lib/shared/links.mjs +0 -9
  157. package/lib/shared/safefetch.mjs +0 -235
  158. package/lib/shared/ua.mjs +0 -29
  159. package/phanpy/dist/404.html +0 -40
  160. package/phanpy/dist/_headers +0 -2
  161. package/phanpy/dist/apple-touch-icon.png +0 -0
  162. package/phanpy/dist/assets/ICONS-DIPJeU0C.js +0 -2
  163. package/phanpy/dist/assets/ICONS-DIPJeU0C.js.map +0 -1
  164. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  165. package/phanpy/dist/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  166. package/phanpy/dist/assets/Temml-CCjoacWt.woff2 +0 -0
  167. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js +0 -2
  168. package/phanpy/dist/assets/__vite-browser-external-C7iut881.js.map +0 -1
  169. package/phanpy/dist/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  170. package/phanpy/dist/assets/catch-up-O5q5C75Z.png +0 -0
  171. package/phanpy/dist/assets/chunk-aKtaBQYM.js +0 -1
  172. package/phanpy/dist/assets/compose-CFEx7wb4.js +0 -2
  173. package/phanpy/dist/assets/compose-CFEx7wb4.js.map +0 -1
  174. package/phanpy/dist/assets/compose-ZJN5xSb4.js +0 -35
  175. package/phanpy/dist/assets/compose-ZJN5xSb4.js.map +0 -1
  176. package/phanpy/dist/assets/debug.module-YFQgwnIr.js +0 -52
  177. package/phanpy/dist/assets/debug.module-YFQgwnIr.js.map +0 -1
  178. package/phanpy/dist/assets/dom-p1YcJ5Rw.js +0 -2
  179. package/phanpy/dist/assets/dom-p1YcJ5Rw.js.map +0 -1
  180. package/phanpy/dist/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  181. package/phanpy/dist/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  182. package/phanpy/dist/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  183. package/phanpy/dist/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  184. package/phanpy/dist/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  185. package/phanpy/dist/assets/icons/alert-line-CpFUMf9s.js +0 -1
  186. package/phanpy/dist/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  187. package/phanpy/dist/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  188. package/phanpy/dist/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  189. package/phanpy/dist/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  190. package/phanpy/dist/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  191. package/phanpy/dist/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  192. package/phanpy/dist/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  193. package/phanpy/dist/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  194. package/phanpy/dist/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  195. package/phanpy/dist/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  196. package/phanpy/dist/assets/icons/at-line-CF66Bznk.js +0 -1
  197. package/phanpy/dist/assets/icons/attachment-line-BY8It-l9.js +0 -1
  198. package/phanpy/dist/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  199. package/phanpy/dist/assets/icons/board-line-C0UWXyA6.js +0 -1
  200. package/phanpy/dist/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  201. package/phanpy/dist/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  202. package/phanpy/dist/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  203. package/phanpy/dist/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  204. package/phanpy/dist/assets/icons/calendar-month-line-vommts2C.js +0 -1
  205. package/phanpy/dist/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  206. package/phanpy/dist/assets/icons/camera-line-Cv69MEei.js +0 -1
  207. package/phanpy/dist/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  208. package/phanpy/dist/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  209. package/phanpy/dist/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  210. package/phanpy/dist/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  211. package/phanpy/dist/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  212. package/phanpy/dist/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  213. package/phanpy/dist/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  214. package/phanpy/dist/assets/icons/close-line-DYrFWcjv.js +0 -1
  215. package/phanpy/dist/assets/icons/cloud-line-tiQAbah8.js +0 -1
  216. package/phanpy/dist/assets/icons/code-line-fAl8iiV3.js +0 -1
  217. package/phanpy/dist/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  218. package/phanpy/dist/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  219. package/phanpy/dist/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  220. package/phanpy/dist/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  221. package/phanpy/dist/assets/icons/document-line-C7mb9sb7.js +0 -1
  222. package/phanpy/dist/assets/icons/down-line-BGqSSThd.js +0 -1
  223. package/phanpy/dist/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  224. package/phanpy/dist/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  225. package/phanpy/dist/assets/icons/exit-line-Dc07BS-x.js +0 -1
  226. package/phanpy/dist/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  227. package/phanpy/dist/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  228. package/phanpy/dist/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  229. package/phanpy/dist/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  230. package/phanpy/dist/assets/icons/filter-line-C_nm-3cU.js +0 -1
  231. package/phanpy/dist/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  232. package/phanpy/dist/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  233. package/phanpy/dist/assets/icons/formula-line-DLrt2d6j.js +0 -1
  234. package/phanpy/dist/assets/icons/grid-line-CgUmEikf.js +0 -1
  235. package/phanpy/dist/assets/icons/group-line-C5fnX0wU.js +0 -1
  236. package/phanpy/dist/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  237. package/phanpy/dist/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  238. package/phanpy/dist/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  239. package/phanpy/dist/assets/icons/heart-line-CJ7K47J4.js +0 -1
  240. package/phanpy/dist/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  241. package/phanpy/dist/assets/icons/history-line-bGQiwbTH.js +0 -1
  242. package/phanpy/dist/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  243. package/phanpy/dist/assets/icons/information-line-iNk6-sOY.js +0 -1
  244. package/phanpy/dist/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  245. package/phanpy/dist/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  246. package/phanpy/dist/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  247. package/phanpy/dist/assets/icons/left-line-eUw0tya4.js +0 -1
  248. package/phanpy/dist/assets/icons/lightning-line-DaKoDdix.js +0 -1
  249. package/phanpy/dist/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  250. package/phanpy/dist/assets/icons/list-check-line-BAxosBh9.js +0 -1
  251. package/phanpy/dist/assets/icons/lock-line-CPoaXeUW.js +0 -1
  252. package/phanpy/dist/assets/icons/mail-line-B0P8aa1L.js +0 -1
  253. package/phanpy/dist/assets/icons/moon-line-CEqNAToP.js +0 -1
  254. package/phanpy/dist/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  255. package/phanpy/dist/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  256. package/phanpy/dist/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  257. package/phanpy/dist/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  258. package/phanpy/dist/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  259. package/phanpy/dist/assets/icons/pin-line-DpTolyhs.js +0 -1
  260. package/phanpy/dist/assets/icons/play-fill-B0-G_8lX.js +0 -1
  261. package/phanpy/dist/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  262. package/phanpy/dist/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  263. package/phanpy/dist/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  264. package/phanpy/dist/assets/icons/radar-line-CKyroTth.js +0 -1
  265. package/phanpy/dist/assets/icons/react-line-CoIKhhtK.js +0 -1
  266. package/phanpy/dist/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  267. package/phanpy/dist/assets/icons/right-line-B3KWJaqc.js +0 -1
  268. package/phanpy/dist/assets/icons/rocket-line-4KZl537D.js +0 -1
  269. package/phanpy/dist/assets/icons/round-fill-C69NTrZ0.js +0 -1
  270. package/phanpy/dist/assets/icons/round-line-B9k_1uo-.js +0 -1
  271. package/phanpy/dist/assets/icons/route-line-B28ReHcE.js +0 -1
  272. package/phanpy/dist/assets/icons/rows-4-line-CrBniagM.js +0 -1
  273. package/phanpy/dist/assets/icons/scan-line-DSf74YdP.js +0 -1
  274. package/phanpy/dist/assets/icons/search-2-line-B6geIU1z.js +0 -1
  275. package/phanpy/dist/assets/icons/settings-3-line-azJwK47w.js +0 -1
  276. package/phanpy/dist/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  277. package/phanpy/dist/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  278. package/phanpy/dist/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  279. package/phanpy/dist/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  280. package/phanpy/dist/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  281. package/phanpy/dist/assets/icons/time-line-BF3eet1v.js +0 -1
  282. package/phanpy/dist/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  283. package/phanpy/dist/assets/icons/translate-line-BFWol2Ce.js +0 -1
  284. package/phanpy/dist/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  285. package/phanpy/dist/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  286. package/phanpy/dist/assets/icons/user-4-line-BVSynZCp.js +0 -1
  287. package/phanpy/dist/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  288. package/phanpy/dist/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  289. package/phanpy/dist/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  290. package/phanpy/dist/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  291. package/phanpy/dist/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  292. package/phanpy/dist/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  293. package/phanpy/dist/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  294. package/phanpy/dist/assets/icons/volume-line-Bs390KQt.js +0 -1
  295. package/phanpy/dist/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  296. package/phanpy/dist/assets/icons/walk-line-yNXfB-md.js +0 -1
  297. package/phanpy/dist/assets/icons/world-2-line-CenkGIwj.js +0 -1
  298. package/phanpy/dist/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  299. package/phanpy/dist/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  300. package/phanpy/dist/assets/instances-BNPptnn-.json +0 -333
  301. package/phanpy/dist/assets/locales/ar-SA-CfheRbCu.js +0 -1
  302. package/phanpy/dist/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  303. package/phanpy/dist/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  304. package/phanpy/dist/assets/locales/de-DE-ByRPMRFy.js +0 -1
  305. package/phanpy/dist/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  306. package/phanpy/dist/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  307. package/phanpy/dist/assets/locales/eu-ES-C3djlPR2.js +0 -1
  308. package/phanpy/dist/assets/locales/fa-IR-DTT490Ck.js +0 -1
  309. package/phanpy/dist/assets/locales/fi-FI-B23MCPuz.js +0 -1
  310. package/phanpy/dist/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  311. package/phanpy/dist/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  312. package/phanpy/dist/assets/locales/he-IL-CfheRbCu.js +0 -1
  313. package/phanpy/dist/assets/locales/hu-HU-CfheRbCu.js +0 -1
  314. package/phanpy/dist/assets/locales/it-IT-C1136UFV.js +0 -1
  315. package/phanpy/dist/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  316. package/phanpy/dist/assets/locales/kab-Cz8xH_TT.js +0 -1
  317. package/phanpy/dist/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  318. package/phanpy/dist/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  319. package/phanpy/dist/assets/locales/nb-NO-CfheRbCu.js +0 -1
  320. package/phanpy/dist/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  321. package/phanpy/dist/assets/locales/oc-FR-CfheRbCu.js +0 -1
  322. package/phanpy/dist/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  323. package/phanpy/dist/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  324. package/phanpy/dist/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  325. package/phanpy/dist/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  326. package/phanpy/dist/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  327. package/phanpy/dist/assets/locales/th-TH-CfheRbCu.js +0 -1
  328. package/phanpy/dist/assets/locales/tok-CfheRbCu.js +0 -1
  329. package/phanpy/dist/assets/locales/tr-TR-CfheRbCu.js +0 -1
  330. package/phanpy/dist/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  331. package/phanpy/dist/assets/locales/zh-CN-BHJi7_et.js +0 -1
  332. package/phanpy/dist/assets/locales/zh-TW-CfheRbCu.js +0 -1
  333. package/phanpy/dist/assets/main-BdqNbG-a.js +0 -26
  334. package/phanpy/dist/assets/main-BdqNbG-a.js.map +0 -1
  335. package/phanpy/dist/assets/mock-home-DGhR__He.js +0 -2
  336. package/phanpy/dist/assets/mock-home-DGhR__He.js.map +0 -1
  337. package/phanpy/dist/assets/multi-column-ROck0NVt.jpg +0 -0
  338. package/phanpy/dist/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  339. package/phanpy/dist/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  340. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js +0 -2
  341. package/phanpy/dist/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  342. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js +0 -20
  343. package/phanpy/dist/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  344. package/phanpy/dist/assets/style-B1iLPTPR.css +0 -2
  345. package/phanpy/dist/assets/temml-DuyIQMei.js +0 -97
  346. package/phanpy/dist/assets/temml-DuyIQMei.js.map +0 -1
  347. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  348. package/phanpy/dist/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  349. package/phanpy/dist/assets/year-in-posts-B2lywqdx.png +0 -0
  350. package/phanpy/dist/assets/year-in-posts-DJv_star.js +0 -3
  351. package/phanpy/dist/assets/year-in-posts-DJv_star.js.map +0 -1
  352. package/phanpy/dist/compose/index.html +0 -20
  353. package/phanpy/dist/favicon.ico +0 -0
  354. package/phanpy/dist/index.html +0 -73
  355. package/phanpy/dist/logo-192.png +0 -0
  356. package/phanpy/dist/logo-512.png +0 -0
  357. package/phanpy/dist/logo-badge-72.png +0 -0
  358. package/phanpy/dist/logo-maskable-512.png +0 -0
  359. package/phanpy/dist/logo-monochrome-512.png +0 -0
  360. package/phanpy/dist/logo-monochrome-maskable-512.png +0 -0
  361. package/phanpy/dist/manifest.webmanifest +0 -1
  362. package/phanpy/dist/og-image-2.jpg +0 -0
  363. package/phanpy/dist/og-image.png +0 -0
  364. package/phanpy/dist/robots.txt +0 -2
  365. package/phanpy/dist/sw.js +0 -2
  366. package/phanpy/dist/sw.js.map +0 -1
  367. package/phanpy/dist/version.json +0 -1
  368. package/run-agent.mjs +0 -897
  369. package/vendor/gate.cjs +0 -138
  370. package/vendor/idp-grant.cjs +0 -394
  371. package/vendor/jfetch.cjs +0 -16
  372. package/web/admin/actors.js +0 -145
  373. package/web/admin/bar.css +0 -126
  374. package/web/admin/bar.js +0 -99
  375. package/web/admin/client/client.js +0 -66
  376. package/web/admin/client/index.html +0 -69
  377. package/web/admin/client-pick.js +0 -79
  378. package/web/admin/common.js +0 -23
  379. package/web/admin/connections.js +0 -112
  380. package/web/admin/gateway.js +0 -133
  381. package/web/admin/group.js +0 -258
  382. package/web/admin/index.html +0 -603
  383. package/web/admin/notices-bar.js +0 -90
  384. package/web/admin/oauth-signin.mjs +0 -37
  385. package/web/admin/record.js +0 -390
  386. package/web/admin/setup/index.html +0 -241
  387. package/web/admin/setup/setup.js +0 -326
  388. package/web/admin/tokens.css +0 -68
  389. package/web/admin/upkeep.js +0 -177
  390. package/web/admin/window.css +0 -55
  391. package/web/admin/window.js +0 -136
  392. package/web/app/README.md +0 -81
  393. package/web/app/admin-facade.mjs +0 -588
  394. package/web/app/agent.mjs +0 -663
  395. package/web/app/atproto-browser.mjs +0 -86
  396. package/web/app/authorize_interaction.html +0 -56
  397. package/web/app/authorize_interaction.js +0 -69
  398. package/web/app/boot.mjs +0 -576
  399. package/web/app/deliver-relay.mjs +0 -129
  400. package/web/app/dist/boot.js +0 -34218
  401. package/web/app/dist/boot.js.map +0 -7
  402. package/web/app/dist/sw.js +0 -72810
  403. package/web/app/dist/sw.js.map +0 -7
  404. package/web/app/fediacct-browser.mjs +0 -146
  405. package/web/app/gateway-move.mjs +0 -60
  406. package/web/app/idb-kv.mjs +0 -35
  407. package/web/app/index.html +0 -242
  408. package/web/app/keys-browser.mjs +0 -71
  409. package/web/app/keystore.mjs +0 -82
  410. package/web/app/oidc-session.mjs +0 -6
  411. package/web/app/pod-auth.mjs +0 -248
  412. package/web/app/pod-remote.mjs +0 -84
  413. package/web/app/shims/_globals.mjs +0 -2
  414. package/web/app/shims/fedify-sig.mjs +0 -77
  415. package/web/app/shims/node-crypto.mjs +0 -113
  416. package/web/app/shims/node-fs.mjs +0 -17
  417. package/web/app/shims/node-path.mjs +0 -19
  418. package/web/app/shims/node-url.mjs +0 -7
  419. package/web/app/shims/prelude.js +0 -58
  420. package/web/app/shims/safefetch.mjs +0 -58
  421. package/web/app/shims/shapes-text.mjs +0 -8
  422. package/web/app/shims/web-push.mjs +0 -14
  423. package/web/app/signup.mjs +0 -318
  424. package/web/app/sw-src.mjs +0 -220
  425. package/web/app/update.js +0 -70
  426. package/web/front/admin.html +0 -55
  427. package/web/front/admin.js +0 -89
  428. package/web/front/install.sh +0 -69
  429. package/web/front/new-account.html +0 -35
  430. package/web/front/new-account.js +0 -13
  431. package/web/front/notices.html +0 -69
  432. package/web/front/notices.js +0 -107
  433. package/web/front/run.html +0 -58
  434. package/web/front/run.js +0 -195
  435. package/web/front/solid-oidc-client.js +0 -6
  436. package/web/icons/forum.svg +0 -11
  437. package/web/icons/gateway.svg +0 -14
  438. package/web/icons/local.svg +0 -11
@@ -1,561 +0,0 @@
1
- // state.mjs — where things live and moving them: state (this identity's
2
- // private half, or every identity's), upgrade, profiles, home, export.
3
-
4
- import fs from 'node:fs';
5
- import os from 'node:os';
6
- import path from 'node:path';
7
- import { spawn } from 'node:child_process';
8
- import { fileURLToPath, pathToFileURL } from 'node:url';
9
- import { identityHomes, isLegacyRoot, CURRENT_ROOT, tildify, defaultProfile, profileHome, rootHoldsIdentity, recordLastUsed, writeJsonAtomic } from '../../home.mjs';
10
- import { insecureUrlReason } from '../../../shared/safefetch.mjs';
11
- import { localFetch } from '../../../client/localapi.mjs';
12
- import { args, flag, has, PROFILE, AP_ROOT, HOME, PORT, requireHandle, requireIdentity, somethingOn, agentOn, isInside } from '../context.mjs';
13
-
14
- export async function state() {
15
- if (has('all') || has('drop-remote')) return stateAll();
16
- requireIdentity();
17
- // Where the private half lives, and how to move it. Copy, verify, THEN
18
- // repoint — a pointer moved on its own leaves the agent reading one
19
- // container and writing another, which is the divergence this avoids.
20
- // The old copy is left behind on purpose; delete it when you are satisfied.
21
- const credPath = path.join(HOME, 'credential.json');
22
- let cred;
23
- try { cred = JSON.parse(fs.readFileSync(credPath, 'utf8')); }
24
- catch { console.error(`no identity in ${HOME} — run setup first`); process.exit(2); }
25
-
26
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
27
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
28
- const where = (c) => (c.privateRoot ? tildify(c.privateRoot) : `${apUrls(c.remotePod, c.root).home}(on the pod)`);
29
-
30
- const to = flag('to');
31
- if (!to) {
32
- console.log(`private data: ${where(cred)}`);
33
- console.log(`public face: ${apUrls(cred.remotePod, cred.root).home}`);
34
- console.log('\nTo move it: fedipod state --to ~/somewhere/private/');
35
- console.log(' fedipod state --to <container-url>');
36
- console.log(' fedipod state --to pod');
37
- process.exit(0);
38
- }
39
- if (await localFetch(HOME, PORT, `/status`).then(() => true).catch(() => false)) {
40
- console.error(`an agent is running on port ${PORT} — stop it first: fedipod stop`);
41
- process.exit(1);
42
- }
43
- // A path or a URL. `state` prints the path form, so refusing it here would
44
- // mean what the command shows you is not what it takes back — two chars before
45
- // the colon, so a Windows drive letter is a path rather than a scheme.
46
- let target = null;
47
- if (to !== 'pod') {
48
- const asPath = !/^[a-z][a-z0-9+.-]+:/i.test(to);
49
- const raw = asPath
50
- ? pathToFileURL(path.resolve(to.replace(/^~(?=[/\\]|$)/, os.homedir()))).href
51
- : to;
52
- target = raw.endsWith('/') ? raw : raw + '/';
53
- try { new URL(target); } catch { console.error(`"${to}" is not a container URL or a path`); process.exit(2); }
54
- }
55
- if ((cred.privateRoot || null) === target) { console.log(`already there: ${where(cred)}`); process.exit(0); }
56
- // Before anything is built or sent, not after. This check used to sit at the
57
- // very bottom, past the copy — so `--to http://nas.local/private/`, a typo
58
- // for https or a plaintext box on the LAN, wrote every state document
59
- // (masto-tokens.json included) and every RDF note to that host in the clear,
60
- // and only then said the address was refused. The messages around it, which
61
- // say nothing was repointed and the old copy was left where it was, were
62
- // true and read as "nothing happened".
63
- if (/^https?:/i.test(target || '')) {
64
- const bad = insecureUrlReason(target, 'private-data address');
65
- if (bad) { console.error(bad); process.exit(2); }
66
- }
67
-
68
- const agent = new Agent({ home: HOME, log: (...a) => console.log('[state]', ...a) });
69
- agent.urls = apUrls(cred.remotePod, cred.root);
70
- // Only one of the two sides can be the pod, and moving between two local
71
- // pods needs no credential at all — so do not spend a token grant on it.
72
- if (!cred.privateRoot || !target) {
73
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
74
- agent.remote = new RemotePod(cred, { log: () => {}, home: HOME });
75
- // A pod that is not there is the ordinary case for an identity nobody has
76
- // run in a while, and it used to arrive as an unhandled rejection — 20
77
- // lines of undici internals ending in ECONNREFUSED, with the reason on the
78
- // last line. Say which pod and why, and stop.
79
- try { await agent.remote.warmup(); }
80
- catch (e) {
81
- const why = e?.cause?.code === 'ECONNREFUSED' ? 'nothing is listening there' : (e.message || String(e));
82
- console.error(`cannot reach the pod this identity keeps its private half on:`);
83
- console.error(` ${cred.remotePod} — ${why}`);
84
- console.error('Nothing was copied and nothing was repointed. Start the pod and try again.');
85
- process.exit(1);
86
- }
87
- }
88
- const destCred = { ...cred, privateRoot: target };
89
- const from = agent.privateUrls(cred);
90
- const dest = agent.privateUrls(destCred);
91
- console.log(`moving the private half\n from ${from.state.replace(/ap-state\/$/, '')}\n to ${dest.state.replace(/ap-state\/$/, '')}\n`);
92
-
93
- const { copyPrivateHalf } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
94
- let copied;
95
- try {
96
- copied = await copyPrivateHalf({
97
- from: { state: agent.privateStorage(cred, 'state') },
98
- to: { state: agent.privateStorage(destCred, 'state') },
99
- log: (...a) => console.log('[state]', ...a),
100
- });
101
- } catch (e) { console.error(e.message); process.exit(1); }
102
- console.log(`copied ${copied.docs} state document(s)`);
103
-
104
- // An empty source produces an empty destination, and every check above
105
- // passes: nothing failed to land because nothing was sent. The command then
106
- // repointed the credential and said it had moved your private data. Say what
107
- // actually happened instead — an empty move is usually a wrong --from, and
108
- // finding that out later means looking for a timeline that was never there.
109
- if (copied.docs === 0 && copied.notes === 0) {
110
- console.log('\nNOTHING WAS COPIED — the source held no state documents and no notes.');
111
- console.log(` from: ${where(cred)}`);
112
- console.log('The pointer is being moved anyway, which is right for a fresh identity');
113
- console.log('and wrong if you expected a timeline here. Check the source if so.\n');
114
- }
115
-
116
- if (target) cred.privateRoot = target; else delete cred.privateRoot;
117
- // Stamp what this install now IS, so `upgrade` stops naming it and the agent
118
- // stops saying it is behind. Moving back onto the pod un-stamps it, which is
119
- // honest rather than punitive: that is the old shape, and it should read as
120
- // the old shape whoever chose it.
121
- {
122
- const { CURRENT_LAYOUT, isCurrent } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
123
- if (isCurrent(cred)) cred.layout = CURRENT_LAYOUT; else delete cred.layout;
124
- }
125
- writeJsonAtomic(credPath, cred);
126
- console.log(`\nprivate data now: ${where(cred)}`);
127
- console.log('The old copy was left where it was — `state --drop-remote` removes it');
128
- console.log('once you are satisfied, or delete it by hand.');
129
- process.exit(0);
130
- }
131
-
132
- export async function stateAll() {
133
- // The root-wide half. `state --to` moves ONE identity, with the right AP_HOME
134
- // set by hand; this runs over every identity under the root.
135
- //
136
- // Per identity, in its own process. HOME, PORT and the root are resolved at
137
- // module load from the environment, so doing several in one process would
138
- // mean re-deriving all of it — and a failure part way would be sharing state
139
- // with the next one. A spawn per identity is a handful of processes for a
140
- // one-shot migration, and each is exactly the command you could have typed.
141
- const { execFile } = await import('node:child_process');
142
- const { needsStateMove, pendingSteps } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
143
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
144
-
145
- const homes = identityHomes(AP_ROOT);
146
- if (!homes.length) {
147
- console.log(`no identities under ${tildify(AP_ROOT)} — nothing to move`);
148
- process.exit(0);
149
- }
150
-
151
- // The same refusal `--to` and `home --restructure` make, for the same reason,
152
- // and it has to cover ALL of them: a running agent holds its state
153
- // write-through in memory, so a copy taken underneath one is overwritten by
154
- // its next write.
155
- // Only when something is actually going to be written. A dry run reads
156
- // credential files and prints what it found, and refusing to do THAT while
157
- // the agents are up defeats the whole point of leading with the inventory:
158
- // you would have to stop everything to find out whether you needed to.
159
- if (has('apply')) {
160
- const live = [];
161
- for (const { name, dir } of homes) {
162
- let port = null;
163
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch { continue; }
164
- if (!port) continue;
165
- const why = await somethingOn(port);
166
- if (why) live.push(`${name} on ${port} (${why})`);
167
- }
168
- if (live.length) {
169
- console.error(`still answering: ${live.join(', ')}`);
170
- console.error('stop them first — a running agent would overwrite the copy with what it holds');
171
- process.exit(2);
172
- }
173
- }
174
-
175
- const rows = [];
176
- for (const { name, dir } of homes) {
177
- let cred = null;
178
- try { cred = JSON.parse(fs.readFileSync(path.join(dir, 'credential.json'), 'utf8')); } catch { continue; }
179
- rows.push({ name, dir, cred, pending: pendingSteps(cred) });
180
- }
181
- if (!rows.length) { console.log('no identities with a credential yet'); process.exit(0); }
182
-
183
- if (has('drop-remote')) {
184
- // Deliberately separate from the move, and second. While both copies exist
185
- // the move is reversible; this is the step that ends that, so it is never
186
- // something you get by accident.
187
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
188
- const { classifyRemoteState } = await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
189
- const apply = has('apply');
190
- for (const { name, dir, cred } of rows) {
191
- if (needsStateMove(cred)) {
192
- console.log(`${name}: still on the pod — run \`state --all --apply\` first`);
193
- continue;
194
- }
195
- const urls = apUrls(cred.remotePod, cred.root);
196
- const remote = new RemotePod(cred, { log: () => {}, home: dir });
197
- try { await remote.warmup(); } catch (e) { console.error(`${name}: ${e.message}`); continue; }
198
- const children = (await remote.listContainer(urls.state)).map(c => c.url);
199
- const { drop, keep } = classifyRemoteState(children, urls.state);
200
- console.log(`${name}: ${drop.length} document(s) to remove, ${keep.length} kept`);
201
- for (const k of keep) console.log(` keep ${k.name} — ${k.why}`);
202
- for (const d of drop) {
203
- if (!apply) { console.log(` would remove ${d.name}`); continue; }
204
- try { await remote.delete(d.url); console.log(` removed ${d.name}`); }
205
- catch (e) { console.error(` ${d.name}: ${e.message}`); }
206
- }
207
- }
208
- if (!apply) console.log('\nThis was a dry run. Add --apply to remove them.');
209
- process.exit(0);
210
- }
211
-
212
- const apply = has('apply');
213
- console.log(apply ? 'Moving the private half onto this machine.\n'
214
- : 'What a move would do. Nothing is written without --apply.\n');
215
- let moved = 0;
216
- for (const { name, dir, cred, pending } of rows) {
217
- const home = cred.privateRoot ? tildify(cred.privateRoot)
218
- : `${apUrls(cred.remotePod, cred.root).home} (ON THE POD)`;
219
- if (!pending.length) { console.log(`${name}: already current — ${home}`); continue; }
220
- const dest = pathToFileURL(path.join(dir, 'private')).href + '/';
221
- if (!apply) {
222
- console.log(`${name}: ${home}\n → would move to ${tildify(dest)}`);
223
- continue;
224
- }
225
- const out = await new Promise((resolve) => {
226
- execFile(process.execPath, [process.argv[1], 'state', '--to', dest],
227
- { env: { ...process.env, AP_HOME: dir, AP_PROFILE: '' } },
228
- (err, stdout, stderr) => resolve({ ok: !err, text: String(stdout) + String(stderr) }));
229
- });
230
- console.log(`${name}: ${out.ok ? 'moved' : 'FAILED'}`);
231
- for (const line of out.text.split('\n').filter(Boolean)) console.log(` ${line}`);
232
- if (out.ok) moved++;
233
- }
234
- if (apply) {
235
- console.log(`\n${moved} identit(ies) moved. The pod still holds the old copy —`);
236
- console.log('`state --drop-remote` removes it once you are satisfied.');
237
- } else {
238
- console.log('\nRe-run with --apply to do it.');
239
- }
240
- process.exit(0);
241
- }
242
-
243
- export async function upgrade() {
244
- // One runner, every identity. The point is that being behind is a thing you
245
- // can ASK about rather than something you find out from a pod bill.
246
- const { pendingSteps, layoutOf, CURRENT_LAYOUT, isCurrent } =
247
- await import(new URL('../../../../lib/device/migrate.mjs', import.meta.url));
248
- const homes = identityHomes(AP_ROOT);
249
- const behind = [];
250
- for (const { name, dir } of homes) {
251
- let cred = null;
252
- try { cred = JSON.parse(fs.readFileSync(path.join(dir, 'credential.json'), 'utf8')); } catch { continue; }
253
- const pending = pendingSteps(cred);
254
- console.log(`${name}: layout ${layoutOf(cred)} of ${CURRENT_LAYOUT}${pending.length ? '' : ' — current'}`);
255
- for (const s of pending) console.log(` ${s.id}: ${s.what}\n (${s.why})`);
256
- // Nothing to do and never stamped: an install that was already in the right
257
- // shape. Record it, so `upgrade` stops asking and the agent stops warning.
258
- if (isCurrent(cred) && layoutOf(cred) < CURRENT_LAYOUT) {
259
- writeJsonAtomic(path.join(dir, 'credential.json'), { ...cred, layout: CURRENT_LAYOUT });
260
- console.log(' stamped as current');
261
- }
262
- if (pending.length) behind.push(name);
263
- }
264
- if (!homes.length) console.log(`no identities under ${tildify(AP_ROOT)}`);
265
- else if (behind.length) {
266
- console.log(`\n${behind.length} identit(ies) behind: ${behind.join(', ')}`);
267
- console.log('The only step is the state move. See what it would do:');
268
- console.log(` ${path.basename(process.argv[1])} state --all`);
269
- console.log('then re-run it with --apply.');
270
- } else if (homes.length) console.log('\nEverything here is at the current layout.');
271
- process.exit(0);
272
- }
273
-
274
- export async function profiles() {
275
- // Local files only, plus a quick liveness probe: nothing here needs the pod.
276
- const homes = identityHomes(AP_ROOT);
277
-
278
- const rows = [];
279
- for (const { name, dir } of homes) {
280
- let pod = null, port = null;
281
- try { pod = JSON.parse(fs.readFileSync(path.join(dir, 'credential.json'), 'utf8')).remotePod; } catch {}
282
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch {}
283
- if (!pod && !port) continue; // not an identity, just a directory
284
- let live = null;
285
- if (port) {
286
- live = await localFetch(HOME, port, `/status`, { signal: AbortSignal.timeout(1500) })
287
- .then(r => r.json()).catch(() => null);
288
- }
289
- // The kind lives in pod state, so it is only knowable from the live probe —
290
- // a stopped identity honestly shows nothing rather than a guess.
291
- rows.push({ name, pod: pod ? new URL(pod).host : '(no credential)', port: port || '—',
292
- // A home can hold a forum, which says so itself; anything else that
293
- // answers is a person unless it says group.
294
- kind: live?.kind === 'group' ? 'group' : live?.kind === 'forum' ? 'forum' : live ? 'person' : '—',
295
- state: live ? `${live.mode}${live.podRequests ? ` · ${live.podRequests.perMinuteNow}/min` : ''}` : 'not running' });
296
- }
297
-
298
- // Which one answers with no --profile. A property of the ROOT, not of any
299
- // identity — which is the whole point of it being a pointer.
300
- const theDefault = (() => { const d = defaultProfile(AP_ROOT); return typeof d === 'string' ? d : null; })();
301
- if (!rows.length) console.log('no identities yet — fedipod setup');
302
- else {
303
- const w = (k, min) => Math.max(min, ...rows.map(r => String(r[k]).length));
304
- const [wn, wp, wo, wk] = [w('name', 7), w('pod', 3), w('port', 4), w('kind', 4)];
305
- console.log(`${'PROFILE'.padEnd(wn)} ${'POD'.padEnd(wp)} ${'PORT'.padEnd(wo)} ${'KIND'.padEnd(wk)} STATE`);
306
- for (const r of rows) {
307
- console.log(`${r.name.padEnd(wn)} ${String(r.pod).padEnd(wp)} ${String(r.port).padEnd(wo)}`
308
- + ` ${String(r.kind).padEnd(wk)} ${r.state}${r.name === theDefault ? ' (default)' : ''}`);
309
- }
310
- }
311
- console.log(`\nIdentities under a custom AP_HOME are not listed — only ${AP_ROOT}`
312
- + ' and its profiles/*.');
313
- process.exit(0);
314
- }
315
-
316
- export async function home() {
317
- if (has('restructure')) return homeRestructure();
318
- // The root holds the credential and the signing keys of every identity on
319
- // this machine, so taking the post-rename name is a command you run, never
320
- // something an upgrade does behind you. Resolution is in lib/home.mjs.
321
- const to = flag('to');
322
- const overridden = !!(process.env.AP_HOME || flag('home'));
323
-
324
- if (!to) {
325
- console.log(`\nroot: ${tildify(AP_ROOT)}${isLegacyRoot(AP_ROOT) ? ' (the name from before the rename)' : ''}`);
326
- console.log(`this home: ${tildify(HOME)}`);
327
- const d = defaultProfile(AP_ROOT);
328
- for (const { name, dir } of identityHomes(AP_ROOT)) {
329
- if (fs.existsSync(path.join(dir, 'credential.json'))) {
330
- console.log(` · ${name}${name === d ? ' (default)' : ''}`);
331
- }
332
- }
333
- if (rootHoldsIdentity(AP_ROOT)) {
334
- console.log('\nThis root still keeps an identity at its top level, from before every');
335
- console.log('identity moved under profiles/. Move it down with:\n');
336
- console.log(` ${process.argv[1]} home --restructure\n`);
337
- }
338
- if (overridden) {
339
- console.log('\nAP_HOME / --home is set, so this run is not using the root above.');
340
- } else if (isLegacyRoot(AP_ROOT)) {
341
- console.log('\nTake the current name with:\n');
342
- console.log(` ${process.argv[1]} home --to ${path.join(os.homedir(), CURRENT_ROOT)}\n`);
343
- console.log('That moves the whole root — the default identity and every profile — and');
344
- console.log('refuses while any of them is answering.');
345
- }
346
- process.exit(0);
347
- }
348
-
349
- if (overridden) {
350
- console.error('AP_HOME / --home is set. That is an explicit directory, not the root this');
351
- console.error('command moves — unset it and run again, or move the directory yourself.');
352
- process.exit(2);
353
- }
354
- const target = path.resolve(to.replace(/^~(?=[/\\]|$)/, os.homedir()));
355
- if (target === AP_ROOT) { console.log(`already there: ${AP_ROOT}`); process.exit(0); }
356
- if (!fs.existsSync(AP_ROOT)) { console.error(`nothing to move — ${AP_ROOT} does not exist`); process.exit(2); }
357
- if (fs.existsSync(target) && fs.readdirSync(target).length) {
358
- console.error(`${target} exists and is not empty — refusing to merge two roots`);
359
- process.exit(2);
360
- }
361
-
362
- // A running agent holds its pidfile and log by path; moving out from under it
363
- // strands both and leaves `stop` with nothing to find.
364
- const live = [];
365
- for (const { name, dir } of identityHomes(AP_ROOT)) {
366
- let port = null;
367
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch { continue; }
368
- if (port && await agentOn(port)) live.push(`${name} on ${port}`);
369
- }
370
- if (live.length) {
371
- console.error(`still answering: ${live.join(', ')}`);
372
- console.error('stop them first — a move would strand the pidfile and log they hold');
373
- process.exit(2);
374
- }
375
-
376
- fs.mkdirSync(path.dirname(target), { recursive: true });
377
- try {
378
- fs.renameSync(AP_ROOT, target);
379
- } catch (e) {
380
- if (e.code !== 'EXDEV') throw e; // a different filesystem
381
- fs.cpSync(AP_ROOT, target, { recursive: true, preserveTimestamps: true });
382
- fs.rmSync(AP_ROOT, { recursive: true, force: true });
383
- }
384
- console.log(`moved ${AP_ROOT} → ${target}`);
385
-
386
- // privateRoot is recorded as an absolute path. One that pointed inside the
387
- // root we just moved now points at nothing, and an agent finding an empty
388
- // store reports itself unconfigured rather than saying why.
389
- for (const { name, dir } of identityHomes(target)) {
390
- const credPath = path.join(dir, 'credential.json');
391
- let cred;
392
- try { cred = JSON.parse(fs.readFileSync(credPath, 'utf8')); } catch { continue; }
393
- if (!cred.privateRoot || /^https?:/i.test(cred.privateRoot)) continue; // a pod, not a directory
394
- const was = cred.privateRoot.startsWith('file:')
395
- ? fileURLToPath(cred.privateRoot) : path.resolve(cred.privateRoot);
396
- if (!isInside(AP_ROOT, was)) continue; // somewhere else entirely
397
- const now = path.join(target, path.relative(AP_ROOT, was));
398
- cred.privateRoot = pathToFileURL(now).href + '/';
399
- writeJsonAtomic(credPath, cred);
400
- console.log(` · ${name}: private data now ${cred.privateRoot}`);
401
- }
402
-
403
- console.log('\nIf you installed the service, its unit has the old path baked in as');
404
- console.log('Environment=AP_HOME — re-run install-service to update it.');
405
- process.exit(0);
406
- }
407
-
408
- export async function homeRestructure() {
409
- // One-time: move the identity that lives AT the root down into
410
- // profiles/<name>/, so every identity is a named folder and none of them
411
- // contains the others. Its own files only — profiles/ stays where it is.
412
- if (process.env.AP_HOME || flag('home')) {
413
- console.error('AP_HOME / --home is set. That is an explicit identity directory, not the');
414
- console.error('root this restructures — unset it and run again.');
415
- process.exit(2);
416
- }
417
- if (!rootHoldsIdentity(AP_ROOT)) {
418
- console.log(`nothing to move — ${tildify(AP_ROOT)} keeps no identity at its top level`);
419
- const d = defaultProfile(AP_ROOT);
420
- if (typeof d === 'string') console.log(`default identity: ${d}`);
421
- process.exit(0);
422
- }
423
- // Its name is its handle, which agent.json records and pod state confirms.
424
- // Falling back to the credential's pod host keeps a half-set-up root movable.
425
- let name = null;
426
- try { name = JSON.parse(fs.readFileSync(path.join(AP_ROOT, 'agent.json'), 'utf8')).handle || null; } catch {}
427
- if (!name) {
428
- try {
429
- const cfg = JSON.parse(fs.readFileSync(path.join(AP_ROOT, 'private/ap-state/config.json'), 'utf8'));
430
- name = cfg.handle || null;
431
- } catch {}
432
- }
433
- name = flag('name', name);
434
- if (!name) {
435
- console.error('cannot tell what this identity is called — no handle in agent.json or pod state.');
436
- console.error(`Name it: ${process.argv[1]} home --restructure --name <name>`);
437
- process.exit(2);
438
- }
439
- requireHandle(name);
440
- const dest = profileHome(AP_ROOT, name);
441
- if (fs.existsSync(dest) && fs.readdirSync(dest).length) {
442
- console.error(`${tildify(dest)} exists and is not empty — refusing to merge two identities`);
443
- console.error(`Give the moved one another name: ${process.argv[1]} home --restructure --name <name>`);
444
- process.exit(2);
445
- }
446
-
447
- // A running agent holds its pidfile and log by path. Same refusal `--to` makes.
448
- const live = [];
449
- for (const { name: n, dir } of [{ name, dir: AP_ROOT }, ...identityHomes(AP_ROOT)]) {
450
- let port = null;
451
- try { port = JSON.parse(fs.readFileSync(path.join(dir, 'agent.json'), 'utf8')).port; } catch { continue; }
452
- if (!port) continue;
453
- // somethingOn, not agentOn: a gated agent answers 401 to an un-tokened
454
- // /status, and this moves its private key out from under it.
455
- const why = await somethingOn(port);
456
- if (why) live.push(`${n} on ${port} (${why})`);
457
- }
458
- if (live.length) {
459
- console.error(`still answering: ${live.join(', ')}`);
460
- console.error('stop them first — a move would strand the pidfile and log they hold');
461
- process.exit(2);
462
- }
463
-
464
- // Its own files, named explicitly. Everything else at the root — profiles/,
465
- // and root.json once it exists — belongs to the root and stays.
466
- const MOVE = ['credential.json', 'keys.json', 'agent.json', 'agent.log', 'token.json',
467
- 'backoff.json', 'private'];
468
- fs.mkdirSync(dest, { recursive: true, mode: 0o700 });
469
- const moved = [];
470
- for (const f of MOVE) {
471
- const from = path.join(AP_ROOT, f);
472
- if (!fs.existsSync(from)) continue;
473
- fs.renameSync(from, path.join(dest, f));
474
- moved.push(f);
475
- }
476
- // A pidfile names a process that was told to stop. Carrying it forward would
477
- // point `stop` at a pid nobody owns.
478
- fs.rmSync(path.join(AP_ROOT, 'agent.pid'), { force: true });
479
- console.log(`moved ${moved.length} item(s) → ${tildify(dest)}`);
480
- console.log(` ${moved.join(', ')}`);
481
-
482
- // privateRoot is an absolute path; one that pointed at the root's private/
483
- // now points at nothing, and an agent finding an empty store reports itself
484
- // unconfigured rather than saying why.
485
- const credPath = path.join(dest, 'credential.json');
486
- try {
487
- const cred = JSON.parse(fs.readFileSync(credPath, 'utf8'));
488
- if (cred.privateRoot && !/^https?:/i.test(cred.privateRoot)) {
489
- const was = cred.privateRoot.startsWith('file:')
490
- ? fileURLToPath(cred.privateRoot) : path.resolve(cred.privateRoot);
491
- if (isInside(AP_ROOT, was) && !isInside(dest, was)) {
492
- cred.privateRoot = pathToFileURL(path.join(dest, path.relative(AP_ROOT, was))).href + '/';
493
- writeJsonAtomic(credPath, cred);
494
- console.log(` private data now ${tildify(cred.privateRoot)}`);
495
- }
496
- }
497
- } catch { /* no credential to repoint */ }
498
-
499
- recordLastUsed(AP_ROOT, name);
500
- console.log(`\n${name} is what a plain command means now. Start another with`);
501
- console.log(`\`${path.basename(process.argv[1])} --profile <name> start\` and that becomes the one instead.`);
502
- process.exit(0);
503
- }
504
-
505
- export async function exportCollectionsCmd() {
506
- // The account's collections as paged Turtle AS2 collections,
507
- // produced on demand: outbox and followers from the pod, inbox from the
508
- // local archive. See lib/export-collections.mjs.
509
- requireIdentity();
510
- const format = flag('format') || args[1];
511
- const to = flag('to');
512
- if (format !== 'as-collections' || !to) {
513
- console.error('usage: fedipod export --format as-collections --to <directory-or-container-url>');
514
- process.exit(2);
515
- }
516
- const { Agent } = await import(new URL('../../../../run-agent.mjs', import.meta.url));
517
- const { RemotePod } = await import(new URL('../../../../lib/device/remote.mjs', import.meta.url));
518
- const { apUrls } = await import(new URL('../../../../lib/core/wire.mjs', import.meta.url));
519
- const { exportCollections, DIR_BASE } = await import(new URL('../../../../lib/device/export-collections.mjs', import.meta.url));
520
- const { storageFor } = await import(new URL('../../../../lib/core/storage.mjs', import.meta.url));
521
- const agent = new Agent({ home: HOME, log: () => {} });
522
- const cred = agent.readCredential();
523
- if (!cred) { console.error('no credential — run setup first'); process.exit(2); }
524
- agent.remote = new RemotePod(cred);
525
- await agent.remote.warmup();
526
- agent.urls = apUrls(cred.remotePod, cred.root);
527
- agent.store.attach(agent.privateStorage(cred, 'state'));
528
- await agent.store.load();
529
- const { Publisher } = await import(new URL('../../../../lib/core/publisher/index.mjs', import.meta.url));
530
- const outboxItems = (await Publisher.prototype.readPublishedOutbox.call(
531
- { remote: agent.remote, urls: agent.urls })) || [];
532
- // Only real AP actors, like the published followers collection.
533
- const contacts = agent.store.getContacts();
534
- const followers = contacts.followers.filter(f => !f.bsky).map(f => f.actor);
535
- const archive = agent.privateStorage(cred, 'archive');
536
- const inboxEntries = [];
537
- const months = (await archive.list('').catch(() => ({ names: [] }))).names || [];
538
- for (const m of months.filter(n => n.endsWith('/'))) {
539
- const files = (await archive.list(m).catch(() => ({ names: [] }))).names || [];
540
- for (const f of files) {
541
- const r = await archive.read(m + f);
542
- if (!r.ok) continue;
543
- try { inboxEntries.push(JSON.parse(r.body)); } catch { /* not an archive record */ }
544
- }
545
- }
546
- const isUrl = /^https?:/i.test(to);
547
- const storage = storageFor(to, (u, i) => agent.remote.fetch(u, i));
548
- const base = isUrl ? (to.endsWith('/') ? to : to + '/') : DIR_BASE;
549
- try {
550
- const out = await exportCollections({
551
- outboxItems, followers, inboxEntries, storage, base, log: console.log,
552
- resolve: (u) => agent.remote.getJson(u),
553
- });
554
- console.log(`outbox: ${out.outbox.items} item(s) in ${out.outbox.pages} page(s); `
555
- + `followers: ${out.followers.items}; inbox: ${out.inbox.items} archived item(s) in ${out.inbox.pages} page(s)`);
556
- console.log(`${out.written} Turtle document(s) written to ${to}`);
557
- } catch (e) {
558
- console.error(`export failed: ${e.message}`);
559
- process.exit(1);
560
- }
561
- }