fedipod 0.17.0 → 0.19.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 (323) hide show
  1. package/README.md +23 -0
  2. package/bin/fedipod.mjs +3 -5
  3. package/cli.md +13 -0
  4. package/groups.md +11 -0
  5. package/gui.md +15 -1
  6. package/lib/admin.mjs +3 -3
  7. package/lib/c2s.mjs +27 -2
  8. package/lib/deliver.mjs +6 -0
  9. package/lib/embed.mjs +1 -0
  10. package/lib/export-collections.mjs +1 -1
  11. package/lib/front-core.mjs +272 -49
  12. package/lib/gateway-core.mjs +3 -7
  13. package/lib/httpsig.mjs +33 -2
  14. package/lib/import.mjs +1 -1
  15. package/lib/intake.mjs +357 -118
  16. package/lib/links.mjs +6 -32
  17. package/lib/mastoapi.mjs +449 -38
  18. package/lib/migrate.mjs +4 -18
  19. package/lib/pod/README.md +61 -0
  20. package/lib/pod/actor.mjs +96 -0
  21. package/lib/pod/collection.mjs +77 -0
  22. package/lib/pod/containers.mjs +136 -0
  23. package/lib/pod/discovery.mjs +46 -0
  24. package/lib/pod/featured.mjs +18 -0
  25. package/lib/pod/followers.mjs +24 -0
  26. package/lib/pod/following.mjs +10 -0
  27. package/lib/pod/http.mjs +74 -0
  28. package/lib/pod/inbox.mjs +144 -0
  29. package/lib/pod/links.mjs +35 -0
  30. package/lib/pod/media.mjs +27 -0
  31. package/lib/pod/notes.mjs +80 -0
  32. package/lib/pod/notifications.mjs +89 -0
  33. package/lib/pod/outbox.mjs +18 -0
  34. package/lib/pod/package.json +19 -0
  35. package/lib/pod/policy.mjs +58 -0
  36. package/lib/pod/private.mjs +19 -0
  37. package/lib/pod/root.mjs +63 -0
  38. package/lib/pod/state.mjs +39 -0
  39. package/lib/pod/transport.mjs +477 -0
  40. package/lib/pod/urls.mjs +71 -0
  41. package/lib/polls.mjs +105 -0
  42. package/lib/publisher.mjs +357 -188
  43. package/lib/remote.mjs +30 -395
  44. package/lib/social.mjs +20 -9
  45. package/lib/storage.mjs +2 -2
  46. package/lib/store.mjs +8 -1
  47. package/lib/tagfeed.mjs +19 -2
  48. package/lib/wire.mjs +87 -67
  49. package/package.json +9 -2
  50. package/run-agent.mjs +20 -39
  51. package/scripts/build-app.mjs +64 -0
  52. package/scripts/check-pod-calls.mjs +177 -0
  53. package/scripts/stage-site.mjs +144 -0
  54. package/web/admin/admin.js +141 -74
  55. package/web/admin/bar.css +9 -13
  56. package/web/admin/bar.js +2 -2
  57. package/web/admin/client/client.js +1 -1
  58. package/web/admin/client/index.html +5 -6
  59. package/web/admin/index.html +53 -65
  60. package/web/admin/setup/index.html +2 -1
  61. package/web/admin/setup/setup.js +1 -1
  62. package/web/admin/tokens.css +56 -0
  63. package/web/app/README.md +77 -0
  64. package/web/app/admin-facade.mjs +549 -0
  65. package/web/app/agent.mjs +490 -0
  66. package/web/app/atproto-browser.mjs +86 -0
  67. package/web/app/boot.mjs +340 -0
  68. package/web/app/deliver-relay.mjs +72 -0
  69. package/web/app/dist/boot.js +34067 -0
  70. package/web/app/dist/boot.js.map +7 -0
  71. package/web/app/dist/sw.js +53745 -0
  72. package/web/app/dist/sw.js.map +7 -0
  73. package/web/app/fediacct-browser.mjs +146 -0
  74. package/web/app/idb-kv.mjs +35 -0
  75. package/web/app/index.html +203 -0
  76. package/web/app/index.html~ +152 -0
  77. package/web/app/keys-browser.mjs +46 -0
  78. package/web/app/keystore.mjs +99 -0
  79. package/web/app/oidc-session.mjs +189 -0
  80. package/web/app/pod-auth.mjs +248 -0
  81. package/web/app/pod-remote.mjs +84 -0
  82. package/web/app/shims/_globals.mjs +2 -0
  83. package/web/app/shims/fedify-sig.mjs +77 -0
  84. package/web/app/shims/node-crypto.mjs +113 -0
  85. package/web/app/shims/node-fs.mjs +17 -0
  86. package/web/app/shims/node-path.mjs +19 -0
  87. package/web/app/shims/node-url.mjs +7 -0
  88. package/web/app/shims/prelude.js +58 -0
  89. package/web/app/shims/safefetch.mjs +58 -0
  90. package/web/app/shims/web-push.mjs +14 -0
  91. package/web/app/signup.mjs +248 -0
  92. package/web/app/site/_headers +9 -0
  93. package/web/app/site/_redirects +21 -0
  94. package/web/app/site/admin/admin.js +1181 -0
  95. package/web/app/site/admin/bar.css +60 -0
  96. package/web/app/site/admin/bar.js +61 -0
  97. package/web/app/site/admin/client/client.js +66 -0
  98. package/web/app/site/admin/client/index.html +43 -0
  99. package/web/app/site/admin/index.html +556 -0
  100. package/web/app/site/admin/setup/index.html +191 -0
  101. package/web/app/site/admin/setup/setup.js +308 -0
  102. package/web/app/site/admin/tokens.css +56 -0
  103. package/web/app/site/admin/window.css +55 -0
  104. package/web/app/site/admin/window.js +136 -0
  105. package/web/app/site/app/404.html +40 -0
  106. package/web/app/site/app/_headers +2 -0
  107. package/web/app/site/app/apple-touch-icon.png +0 -0
  108. package/web/app/site/app/assets/ICONS-DIPJeU0C.js +2 -0
  109. package/web/app/site/app/assets/ICONS-DIPJeU0C.js.map +1 -0
  110. package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js +183 -0
  111. package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js.map +1 -0
  112. package/web/app/site/app/assets/Temml-CCjoacWt.woff2 +0 -0
  113. package/web/app/site/app/assets/__vite-browser-external-C7iut881.js +2 -0
  114. package/web/app/site/app/assets/__vite-browser-external-C7iut881.js.map +1 -0
  115. package/web/app/site/app/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  116. package/web/app/site/app/assets/catch-up-O5q5C75Z.png +0 -0
  117. package/web/app/site/app/assets/chunk-aKtaBQYM.js +1 -0
  118. package/web/app/site/app/assets/compose-CFEx7wb4.js +2 -0
  119. package/web/app/site/app/assets/compose-CFEx7wb4.js.map +1 -0
  120. package/web/app/site/app/assets/compose-ZJN5xSb4.js +35 -0
  121. package/web/app/site/app/assets/compose-ZJN5xSb4.js.map +1 -0
  122. package/web/app/site/app/assets/debug.module-YFQgwnIr.js +52 -0
  123. package/web/app/site/app/assets/debug.module-YFQgwnIr.js.map +1 -0
  124. package/web/app/site/app/assets/dom-p1YcJ5Rw.js +2 -0
  125. package/web/app/site/app/assets/dom-p1YcJ5Rw.js.map +1 -0
  126. package/web/app/site/app/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  127. package/web/app/site/app/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  128. package/web/app/site/app/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  129. package/web/app/site/app/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  130. package/web/app/site/app/assets/icons/add-circle-line-WD0mwORD.js +1 -0
  131. package/web/app/site/app/assets/icons/alert-line-CpFUMf9s.js +1 -0
  132. package/web/app/site/app/assets/icons/android-2-line-Bzxnrd3S.js +1 -0
  133. package/web/app/site/app/assets/icons/announcement-line-5nwaJFJm.js +1 -0
  134. package/web/app/site/app/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +1 -0
  135. package/web/app/site/app/assets/icons/arrow-down-line-B8uzXzq6.js +1 -0
  136. package/web/app/site/app/assets/icons/arrow-left-line-CGrGT9C-.js +1 -0
  137. package/web/app/site/app/assets/icons/arrow-right-line-CE-HERfX.js +1 -0
  138. package/web/app/site/app/assets/icons/arrow-to-up-line-CvdQjmcy.js +1 -0
  139. package/web/app/site/app/assets/icons/arrow-up-circle-line-DEparSNF.js +1 -0
  140. package/web/app/site/app/assets/icons/arrow-up-line-C7yBeugc.js +1 -0
  141. package/web/app/site/app/assets/icons/arrows-right-line-BtbXmJGP.js +1 -0
  142. package/web/app/site/app/assets/icons/at-line-CF66Bznk.js +1 -0
  143. package/web/app/site/app/assets/icons/attachment-line-BY8It-l9.js +1 -0
  144. package/web/app/site/app/assets/icons/blockquote-line-BS6pU_hm.js +1 -0
  145. package/web/app/site/app/assets/icons/board-line-C0UWXyA6.js +1 -0
  146. package/web/app/site/app/assets/icons/bookmark-line-1CtX5JLF.js +1 -0
  147. package/web/app/site/app/assets/icons/building-5-line-Dd59MzbO.js +1 -0
  148. package/web/app/site/app/assets/icons/bus-2-line-6_dvA0GG.js +1 -0
  149. package/web/app/site/app/assets/icons/calendar-day-line-Crpl_fmu.js +1 -0
  150. package/web/app/site/app/assets/icons/calendar-month-line-vommts2C.js +1 -0
  151. package/web/app/site/app/assets/icons/calendar-time-add-line-BU_DTlQk.js +1 -0
  152. package/web/app/site/app/assets/icons/camera-line-Cv69MEei.js +1 -0
  153. package/web/app/site/app/assets/icons/celebrate-line-B8DvIoi0.js +1 -0
  154. package/web/app/site/app/assets/icons/chart-bar-line-FK-QOmtF.js +1 -0
  155. package/web/app/site/app/assets/icons/chart-line-line-BGcJAFWw.js +1 -0
  156. package/web/app/site/app/assets/icons/chat-3-line-YFK2-hwz.js +1 -0
  157. package/web/app/site/app/assets/icons/check-circle-line-DsAxFr5-.js +1 -0
  158. package/web/app/site/app/assets/icons/clipboard-line-BBp364gJ.js +1 -0
  159. package/web/app/site/app/assets/icons/close-circle-line-CICdiuGz.js +1 -0
  160. package/web/app/site/app/assets/icons/close-line-DYrFWcjv.js +1 -0
  161. package/web/app/site/app/assets/icons/cloud-line-tiQAbah8.js +1 -0
  162. package/web/app/site/app/assets/icons/code-line-fAl8iiV3.js +1 -0
  163. package/web/app/site/app/assets/icons/comment-2-line-CR3g7WeB.js +1 -0
  164. package/web/app/site/app/assets/icons/copy-2-line-CLW69yF5.js +1 -0
  165. package/web/app/site/app/assets/icons/delete-2-line-B8xmbr4n.js +1 -0
  166. package/web/app/site/app/assets/icons/document-3-line-DBGNhAg2.js +1 -0
  167. package/web/app/site/app/assets/icons/document-line-C7mb9sb7.js +1 -0
  168. package/web/app/site/app/assets/icons/down-line-BGqSSThd.js +1 -0
  169. package/web/app/site/app/assets/icons/edit-4-line-DcgGaEhx.js +1 -0
  170. package/web/app/site/app/assets/icons/emoji-2-line-D8YgnM-y.js +1 -0
  171. package/web/app/site/app/assets/icons/exit-line-Dc07BS-x.js +1 -0
  172. package/web/app/site/app/assets/icons/external-link-line-BvpSkmjO.js +1 -0
  173. package/web/app/site/app/assets/icons/eye-2-line-CiWXx-f_.js +1 -0
  174. package/web/app/site/app/assets/icons/eye-close-line-BgTaSJ4P.js +1 -0
  175. package/web/app/site/app/assets/icons/filter-2-line-B_mR2usy.js +1 -0
  176. package/web/app/site/app/assets/icons/filter-line-C_nm-3cU.js +1 -0
  177. package/web/app/site/app/assets/icons/flag-1-line-C2HB05I0.js +1 -0
  178. package/web/app/site/app/assets/icons/forbid-circle-line-D3LTT9yd.js +1 -0
  179. package/web/app/site/app/assets/icons/formula-line-DLrt2d6j.js +1 -0
  180. package/web/app/site/app/assets/icons/grid-line-CgUmEikf.js +1 -0
  181. package/web/app/site/app/assets/icons/group-line-C5fnX0wU.js +1 -0
  182. package/web/app/site/app/assets/icons/hand-finger-2-line-BGgxbuL9.js +1 -0
  183. package/web/app/site/app/assets/icons/hashtag-line-CyTEEXBb.js +1 -0
  184. package/web/app/site/app/assets/icons/heart-crack-line-BZddbO2C.js +1 -0
  185. package/web/app/site/app/assets/icons/heart-line-CJ7K47J4.js +1 -0
  186. package/web/app/site/app/assets/icons/history-2-line-kWWvFzqv.js +1 -0
  187. package/web/app/site/app/assets/icons/history-line-bGQiwbTH.js +1 -0
  188. package/web/app/site/app/assets/icons/home-3-line-fRU1zeLG.js +1 -0
  189. package/web/app/site/app/assets/icons/information-line-iNk6-sOY.js +1 -0
  190. package/web/app/site/app/assets/icons/keyboard-line-DsCyuQNz.js +1 -0
  191. package/web/app/site/app/assets/icons/layout-4-line-CZkOX52Z.js +1 -0
  192. package/web/app/site/app/assets/icons/layout-5-line-B_znt5wO.js +1 -0
  193. package/web/app/site/app/assets/icons/left-line-eUw0tya4.js +1 -0
  194. package/web/app/site/app/assets/icons/lightning-line-DaKoDdix.js +1 -0
  195. package/web/app/site/app/assets/icons/link-2-line-DCqLmMA7.js +1 -0
  196. package/web/app/site/app/assets/icons/list-check-line-BAxosBh9.js +1 -0
  197. package/web/app/site/app/assets/icons/lock-line-CPoaXeUW.js +1 -0
  198. package/web/app/site/app/assets/icons/mail-line-B0P8aa1L.js +1 -0
  199. package/web/app/site/app/assets/icons/moon-line-CEqNAToP.js +1 -0
  200. package/web/app/site/app/assets/icons/more-1-fill-Dw2e5xab.js +1 -0
  201. package/web/app/site/app/assets/icons/more-3-line-BIiVjYTz.js +1 -0
  202. package/web/app/site/app/assets/icons/notification-line-BZZq2Gtu.js +1 -0
  203. package/web/app/site/app/assets/icons/pencil-line-CKh8-A1v.js +1 -0
  204. package/web/app/site/app/assets/icons/photo-album-line-Bnfg2u40.js +1 -0
  205. package/web/app/site/app/assets/icons/pin-line-DpTolyhs.js +1 -0
  206. package/web/app/site/app/assets/icons/play-fill-B0-G_8lX.js +1 -0
  207. package/web/app/site/app/assets/icons/qrcode-2-line-B6SPCaHn.js +1 -0
  208. package/web/app/site/app/assets/icons/quill-pen-line-B6LUrnCP.js +1 -0
  209. package/web/app/site/app/assets/icons/quote-left-fill-hQZ1cj_6.js +1 -0
  210. package/web/app/site/app/assets/icons/radar-line-CKyroTth.js +1 -0
  211. package/web/app/site/app/assets/icons/react-line-CoIKhhtK.js +1 -0
  212. package/web/app/site/app/assets/icons/refresh-2-line-D0mTF97S.js +1 -0
  213. package/web/app/site/app/assets/icons/right-line-B3KWJaqc.js +1 -0
  214. package/web/app/site/app/assets/icons/rocket-line-4KZl537D.js +1 -0
  215. package/web/app/site/app/assets/icons/round-fill-C69NTrZ0.js +1 -0
  216. package/web/app/site/app/assets/icons/round-line-B9k_1uo-.js +1 -0
  217. package/web/app/site/app/assets/icons/route-line-B28ReHcE.js +1 -0
  218. package/web/app/site/app/assets/icons/rows-4-line-CrBniagM.js +1 -0
  219. package/web/app/site/app/assets/icons/scan-line-DSf74YdP.js +1 -0
  220. package/web/app/site/app/assets/icons/search-2-line-B6geIU1z.js +1 -0
  221. package/web/app/site/app/assets/icons/settings-3-line-azJwK47w.js +1 -0
  222. package/web/app/site/app/assets/icons/settings-6-line-C_5zc5YR.js +1 -0
  223. package/web/app/site/app/assets/icons/share-2-line-D5MxWjrm.js +1 -0
  224. package/web/app/site/app/assets/icons/share-forward-line-Cp61fZzZ.js +1 -0
  225. package/web/app/site/app/assets/icons/sparkles-2-line-DYYyXTaW.js +1 -0
  226. package/web/app/site/app/assets/icons/sparkles-line-C2hY1s6I.js +1 -0
  227. package/web/app/site/app/assets/icons/time-line-BF3eet1v.js +1 -0
  228. package/web/app/site/app/assets/icons/transfer-4-line-oisfvTBw.js +1 -0
  229. package/web/app/site/app/assets/icons/translate-line-BFWol2Ce.js +1 -0
  230. package/web/app/site/app/assets/icons/unlock-line-X_x5vwv3.js +1 -0
  231. package/web/app/site/app/assets/icons/upload-3-line-DgzwUJeW.js +1 -0
  232. package/web/app/site/app/assets/icons/user-4-line-BVSynZCp.js +1 -0
  233. package/web/app/site/app/assets/icons/user-add-2-line-BlGS5Q8q.js +1 -0
  234. package/web/app/site/app/assets/icons/user-add-line-BbXdHG4z.js +1 -0
  235. package/web/app/site/app/assets/icons/user-edit-line-BFAHOV0X.js +1 -0
  236. package/web/app/site/app/assets/icons/user-follow-line-BXux0wSd.js +1 -0
  237. package/web/app/site/app/assets/icons/user-star-line-DdYlpHLU.js +1 -0
  238. package/web/app/site/app/assets/icons/user-warning-line-Cj43j0_E.js +1 -0
  239. package/web/app/site/app/assets/icons/user-x-line-DIDgNlPH.js +1 -0
  240. package/web/app/site/app/assets/icons/volume-line-Bs390KQt.js +1 -0
  241. package/web/app/site/app/assets/icons/volume-mute-line-DzlzIqFZ.js +1 -0
  242. package/web/app/site/app/assets/icons/walk-line-yNXfB-md.js +1 -0
  243. package/web/app/site/app/assets/icons/world-2-line-CenkGIwj.js +1 -0
  244. package/web/app/site/app/assets/icons/zoom-in-line-CaENUphf.js +1 -0
  245. package/web/app/site/app/assets/icons/zoom-out-line-BDNk0EWo.js +1 -0
  246. package/web/app/site/app/assets/instances-BNPptnn-.json +333 -0
  247. package/web/app/site/app/assets/locales/ar-SA-CfheRbCu.js +1 -0
  248. package/web/app/site/app/assets/locales/ca-ES-DHRW86Tz.js +1 -0
  249. package/web/app/site/app/assets/locales/cs-CZ-CKoqEuA1.js +1 -0
  250. package/web/app/site/app/assets/locales/de-DE-ByRPMRFy.js +1 -0
  251. package/web/app/site/app/assets/locales/eo-UY-CPC7wLCS.js +1 -0
  252. package/web/app/site/app/assets/locales/es-ES-dJa0Fd9t.js +1 -0
  253. package/web/app/site/app/assets/locales/eu-ES-C3djlPR2.js +1 -0
  254. package/web/app/site/app/assets/locales/fa-IR-DTT490Ck.js +1 -0
  255. package/web/app/site/app/assets/locales/fi-FI-B23MCPuz.js +1 -0
  256. package/web/app/site/app/assets/locales/fr-FR-BcaQsO5C.js +1 -0
  257. package/web/app/site/app/assets/locales/gl-ES-BR-CVKBN.js +1 -0
  258. package/web/app/site/app/assets/locales/he-IL-CfheRbCu.js +1 -0
  259. package/web/app/site/app/assets/locales/hu-HU-CfheRbCu.js +1 -0
  260. package/web/app/site/app/assets/locales/it-IT-C1136UFV.js +1 -0
  261. package/web/app/site/app/assets/locales/ja-JP-CRZmRAhD.js +1 -0
  262. package/web/app/site/app/assets/locales/kab-Cz8xH_TT.js +1 -0
  263. package/web/app/site/app/assets/locales/ko-KR-CG9UiY4o.js +1 -0
  264. package/web/app/site/app/assets/locales/lt-LT-CJcI6sHZ.js +1 -0
  265. package/web/app/site/app/assets/locales/nb-NO-CfheRbCu.js +1 -0
  266. package/web/app/site/app/assets/locales/nl-NL-DxN4Yc1t.js +1 -0
  267. package/web/app/site/app/assets/locales/oc-FR-CfheRbCu.js +1 -0
  268. package/web/app/site/app/assets/locales/pl-PL-DkwGXf6P.js +1 -0
  269. package/web/app/site/app/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +1 -0
  270. package/web/app/site/app/assets/locales/pt-BR-nGL0HdFS.js +1 -0
  271. package/web/app/site/app/assets/locales/pt-PT-Cp17aj2z.js +1 -0
  272. package/web/app/site/app/assets/locales/ru-RU-0Y8cIoaK.js +1 -0
  273. package/web/app/site/app/assets/locales/th-TH-CfheRbCu.js +1 -0
  274. package/web/app/site/app/assets/locales/tok-CfheRbCu.js +1 -0
  275. package/web/app/site/app/assets/locales/tr-TR-CfheRbCu.js +1 -0
  276. package/web/app/site/app/assets/locales/uk-UA-C5E3dFBf.js +1 -0
  277. package/web/app/site/app/assets/locales/zh-CN-BHJi7_et.js +1 -0
  278. package/web/app/site/app/assets/locales/zh-TW-CfheRbCu.js +1 -0
  279. package/web/app/site/app/assets/main-BdqNbG-a.js +26 -0
  280. package/web/app/site/app/assets/main-BdqNbG-a.js.map +1 -0
  281. package/web/app/site/app/assets/mock-home-DGhR__He.js +2 -0
  282. package/web/app/site/app/assets/mock-home-DGhR__He.js.map +1 -0
  283. package/web/app/site/app/assets/multi-column-ROck0NVt.jpg +0 -0
  284. package/web/app/site/app/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  285. package/web/app/site/app/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  286. package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js +2 -0
  287. package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js.map +1 -0
  288. package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js +20 -0
  289. package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js.map +1 -0
  290. package/web/app/site/app/assets/style-B1iLPTPR.css +2 -0
  291. package/web/app/site/app/assets/temml-DuyIQMei.js +97 -0
  292. package/web/app/site/app/assets/temml-DuyIQMei.js.map +1 -0
  293. package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js +2 -0
  294. package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js.map +1 -0
  295. package/web/app/site/app/assets/year-in-posts-B2lywqdx.png +0 -0
  296. package/web/app/site/app/assets/year-in-posts-DJv_star.js +3 -0
  297. package/web/app/site/app/assets/year-in-posts-DJv_star.js.map +1 -0
  298. package/web/app/site/app/compose/index.html +20 -0
  299. package/web/app/site/app/favicon.ico +0 -0
  300. package/web/app/site/app/index.html +73 -0
  301. package/web/app/site/app/logo-192.png +0 -0
  302. package/web/app/site/app/logo-512.png +0 -0
  303. package/web/app/site/app/logo-badge-72.png +0 -0
  304. package/web/app/site/app/logo-maskable-512.png +0 -0
  305. package/web/app/site/app/logo-monochrome-512.png +0 -0
  306. package/web/app/site/app/logo-monochrome-maskable-512.png +0 -0
  307. package/web/app/site/app/manifest.webmanifest +1 -0
  308. package/web/app/site/app/og-image-2.jpg +0 -0
  309. package/web/app/site/app/og-image.png +0 -0
  310. package/web/app/site/app/robots.txt +2 -0
  311. package/web/app/site/app/version.json +1 -0
  312. package/web/app/site/boot.js +34067 -0
  313. package/web/app/site/index.html +203 -0
  314. package/web/app/site/sw.js +53745 -0
  315. package/web/app/sw-src.mjs +205 -0
  316. package/web/front/#new-account.html# +43 -0
  317. package/web/front/admin.html +1 -81
  318. package/web/front/admin.js +85 -0
  319. package/web/front/new-account.html +1 -9
  320. package/web/front/new-account.js +13 -0
  321. package/web/front/run.html +1 -92
  322. package/web/front/run.js +107 -0
  323. package/lib/podrdf.mjs +0 -132
package/README.md CHANGED
@@ -74,6 +74,23 @@ keyword filters, scheduled posts, pinned posts (visible from other servers),
74
74
  blocking and muting from the client, custom emojis, and web-push
75
75
  notifications that reach you while the client is closed.
76
76
 
77
+ <!-- CLAUDE 2026-09-09 — the browser build does not have three of the things
78
+ this paragraph promises, and it says so honestly now rather than
79
+ advertising them. Written as a first draft in your voice; rework or move
80
+ it wherever you think it belongs. Delete these markers when done. -->
81
+ Two of those are the installed agent only. **Scheduled posts** need something
82
+ running between now and the time you picked, and in the browser build nothing
83
+ is — so it refuses a scheduled post rather than accepting one it would silently
84
+ drop. **Web-push notifications** likewise: the browser build has no push
85
+ service behind it, so it does not advertise one and your client hides the
86
+ toggle instead of showing one that does nothing. Both work on the installed
87
+ agent. **Custom emojis** you receive are rendered everywhere; the picker for
88
+ sending your own is not built yet, on either.
89
+ <!-- /CLAUDE -->
90
+
91
+ Polls: up to four options, one answer or several, running from five minutes to
92
+ a month.
93
+
77
94
  ### Other clients
78
95
 
79
96
  - **Web clients**: drop any static Mastodon client dist into `ui/<name>/`
@@ -82,6 +99,12 @@ notifications that reach you while the client is closed.
82
99
  custom instance.
83
100
  - **Streaming**: the agent serves the Mastodon streaming API
84
101
  (`/api/v1/streaming`, WebSocket) so clients update live instead of polling.
102
+ <!-- CLAUDE 2026-09-09 — true of the installed agent; the browser build is a
103
+ service worker and cannot hold a socket. It advertises no streaming URL,
104
+ so clients fall back to polling on their own. Delete markers when done. -->
105
+ The browser build cannot: a service worker answers fetches, not sockets, so it
106
+ advertises no streaming URL and clients poll instead.
107
+ <!-- /CLAUDE -->
85
108
 
86
109
  ## Bluesky and ATProto
87
110
 
package/bin/fedipod.mjs CHANGED
@@ -964,13 +964,12 @@ if (cmd === 'up') {
964
964
  let copied;
965
965
  try {
966
966
  copied = await copyPrivateHalf({
967
- from: { state: agent.privateStorage(cred, 'state'), fediverse: agent.privateStorage(cred, 'fediverse') },
968
- to: { state: agent.privateStorage(destCred, 'state'), fediverse: agent.privateStorage(destCred, 'fediverse') },
967
+ from: { state: agent.privateStorage(cred, 'state') },
968
+ to: { state: agent.privateStorage(destCred, 'state') },
969
969
  log: (...a) => console.log('[state]', ...a),
970
970
  });
971
971
  } catch (e) { console.error(e.message); process.exit(1); }
972
972
  console.log(`copied ${copied.docs} state document(s)`);
973
- console.log(`copied ${copied.notes} note(s)`);
974
973
 
975
974
  // An empty source produces an empty destination, and every check above
976
975
  // passes: nothing failed to land because nothing was sent. The command then
@@ -2071,8 +2070,7 @@ WantedBy=default.target
2071
2070
  if (res.status >= 400) { console.error(body.error || `HTTP ${res.status}`); process.exit(1); }
2072
2071
  if (body.why) { console.error(body.why); process.exit(1); }
2073
2072
  console.log(`the pod indexed ${body.indexed} post(s); recovered ${body.recovered}`
2074
- + `${body.reblogs ? `, and marked ${body.reblogs} of them boosted` : ''}`
2075
- + `${body.rdf ? ` (${body.rdf} written back to the RDF)` : ''}`);
2073
+ + `${body.reblogs ? `, and marked ${body.reblogs} of them boosted` : ''}`);
2076
2074
  if (body.dropped) console.log(`${body.dropped} fell past the 1000-status cap`);
2077
2075
  if (!body.landed) { console.error('the state write did NOT land — nothing is saved'); process.exit(1); }
2078
2076
  if (!body.recovered && !has('from-notes')) {
package/cli.md CHANGED
@@ -70,6 +70,19 @@ fedipod revoke-credential --email EMAIL # cut this machine off from the pod acc
70
70
  ```
71
71
  A new password takes effect when a running agent restarts.
72
72
 
73
+ <!-- CLAUDE 2026-09-09 — `passwd` stopped being optional for one case, and a
74
+ user who hits it will want to know why here. First draft in your voice;
75
+ delete these markers when done. -->
76
+ **A client hosted somewhere else now needs one.** A client running on its own
77
+ site (Elk, Phanpy on someone's own domain) asks the agent to send the sign-in
78
+ result back to that site. Without a password there is nothing to approve that
79
+ with — and the agent used to do it anyway, which meant any page you happened
80
+ to have open could ask for the same thing and be given a key to your account.
81
+ So: no password, no sending credentials off this machine. Clients that live on
82
+ the agent itself (the bundled one, a dist in `ui/`, anything on
83
+ `https://localhost:<port>`) are unaffected and need no password.
84
+ <!-- /CLAUDE -->
85
+
73
86
  ## Bluesky
74
87
 
75
88
  ```
package/groups.md CHANGED
@@ -14,6 +14,17 @@ and pick group rather than person, or take the group path on a signup page.
14
14
  You can turn on join review as you create it. The group's pod must be the root
15
15
  of its own host, so its handle resolves.
16
16
 
17
+ <!-- CLAUDE 2026-09-09 — nothing anywhere said this, and a browser user who
18
+ went looking for the group option would just not have found it. First
19
+ draft in your voice; move or reword as you like. Delete markers when done. -->
20
+ **Running a group needs the installed agent.** The in-browser build makes
21
+ personal identities only — the sign-up wizard has no group option, and the
22
+ moderation surface (join review, members, muting, the moderation queue) is not
23
+ part of that build. You can *join* a group from the browser exactly as from
24
+ anywhere else: joining is following, and that works everywhere. It is hosting
25
+ one that needs an install.
26
+ <!-- /CLAUDE -->
27
+
17
28
  Being in a group also connects you to the people in it: posts from fellow
18
29
  members reach your timeline even when you do not follow them individually,
19
30
  so a reply in the room is something you see rather than something filed
package/gui.md CHANGED
@@ -91,7 +91,15 @@ is marked **sign in again** rather than quietly dropped.
91
91
  ## Handling follow requests
92
92
 
93
93
  New followers appear under **Follow requests** with **Accept** and **Refuse**
94
- beside them; nothing is accepted without you. Groups are different — joining
94
+ beside them; nothing is accepted without you.
95
+ <!-- CLAUDE 2026-09-09 — these were visible on this page and NOWHERE else
96
+ until today: the client API stubbed the list empty and offered no way to
97
+ answer one, so no Mastodon client could show them. Delete markers when
98
+ read. -->
99
+ They show in any Mastodon client as well, now that the client API serves the
100
+ queue and takes both answers — before this they were visible on this page
101
+ alone.
102
+ <!-- /CLAUDE --> Groups are different — joining
95
103
  follows the group's own moderation settings; see [Groups](groups.md).
96
104
 
97
105
  **Accept all** answers the whole queue at once, and the identity pane's
@@ -123,6 +131,12 @@ account*); your followers arrive by themselves. Removing an alias asks
123
131
  twice — servers still processing the move check it while they retry. The CSV
124
132
  files from the old server's export are imported with the CLI; see
125
133
  [CLI admin](cli.md).
134
+ <!-- CLAUDE 2026-09-09 — the browser build runs the same importer now, so
135
+ "with the CLI" is no longer the whole story. Reword as you like; delete
136
+ these markers when done. -->
137
+ The in-browser build runs the same importer, so a CSV can be handed to it
138
+ there too.
139
+ <!-- /CLAUDE -->
126
140
 
127
141
  ## Protecting & recovering your data
128
142
 
package/lib/admin.mjs CHANGED
@@ -1379,15 +1379,15 @@ export function buildAdminSurface({ agent, gate, allowed, log = console.log,
1379
1379
  await agent.store.flush();
1380
1380
  const destCred = { ...cred, privateRoot: target };
1381
1381
  const copied = await copyPrivateHalf({
1382
- from: { state: agent.privateStorage(cred, 'state'), fediverse: agent.privateStorage(cred, 'fediverse') },
1383
- to: { state: agent.privateStorage(destCred, 'state'), fediverse: agent.privateStorage(destCred, 'fediverse') },
1382
+ from: { state: agent.privateStorage(cred, 'state') },
1383
+ to: { state: agent.privateStorage(destCred, 'state') },
1384
1384
  log,
1385
1385
  });
1386
1386
  if (target) cred.privateRoot = target; else delete cred.privateRoot;
1387
1387
  if (isCurrent(cred)) cred.layout = CURRENT_LAYOUT; else delete cred.layout;
1388
1388
  writeJsonAtomic(path.join(agent.home, 'credential.json'), cred);
1389
1389
  // connect() rebuilds everything that pointed at the old location —
1390
- // store, RDF tree, publisher, intake — and restarts them.
1390
+ // store, publisher, intake — and restarts them.
1391
1391
  agent.store.attach(agent.privateStorage(cred, 'state'));
1392
1392
  agent.stateLoaded = false;
1393
1393
  await agent.connect();
package/lib/c2s.mjs CHANGED
@@ -234,8 +234,9 @@ export class C2S {
234
234
 
235
235
  switch (activity.type) {
236
236
  case 'Create': {
237
- if (!object || (object.type && object.type !== 'Note')) {
238
- return this.send(res, 422, { error: 'only a Note (or a bare Note) can be created here' });
237
+ const makes = object?.type || 'Note';
238
+ if (!object || (makes !== 'Note' && makes !== 'Question')) {
239
+ return this.send(res, 422, { error: 'only a Note or a Question (or a bare Note) can be created here' });
239
240
  }
240
241
  const visibility = this.visibilityOf(activity, object);
241
242
  if (!visibility) {
@@ -246,6 +247,30 @@ export class C2S {
246
247
  // visible characters rather than as markup. Documented v1 limit.
247
248
  const text = String(object.source?.content ?? object.content ?? '');
248
249
  if (!text.trim()) return this.send(res, 422, { error: 'the note has no content' });
250
+
251
+ // A Question is a poll: the choices are in oneOf (pick one) or anyOf
252
+ // (pick several), each naming itself, and endTime is when it shuts.
253
+ if (makes === 'Question') {
254
+ const one = arr(object.oneOf);
255
+ const many = arr(object.anyOf);
256
+ const titles = (one.length ? one : many).map((c) => String(c?.name ?? '').trim()).filter(Boolean);
257
+ try {
258
+ const question = await agent.publisher.publishQuestion(text, {
259
+ options: titles,
260
+ multiple: !one.length && many.length > 0,
261
+ expiresAt: object.endTime || null,
262
+ inReplyTo: idOf(object.inReplyTo) || undefined,
263
+ visibility,
264
+ spoilerText: object.summary || null,
265
+ });
266
+ return this.send(res, 201,
267
+ { id: wire.createActivityId(question.id), object: question.id },
268
+ { location: wire.createActivityId(question.id) });
269
+ } catch (e) {
270
+ return this.send(res, 422, { error: e.message });
271
+ }
272
+ }
273
+
249
274
  const attachments = arr(object.attachment).map((a) => ({
250
275
  url: a?.url, mediaType: a?.mediaType,
251
276
  ...(a?.name ? { description: a.name } : {}),
package/lib/deliver.mjs CHANGED
@@ -107,6 +107,12 @@ export class Deliverer {
107
107
  current = new URL(res.headers.get('location'), current).href;
108
108
  continue;
109
109
  }
110
+ // Where this ended up, which is not always where it was asked to go.
111
+ // Callers compare the document's own id against the URL they REQUESTED,
112
+ // so without this an open redirector on a victim's origin let an
113
+ // attacker's server answer for a victim's URL and be believed.
114
+ try { Object.defineProperty(res, 'finalUrl', { value: current, configurable: true }); }
115
+ catch { /* a frozen Response: the caller falls back to the requested URL */ }
110
116
  return res;
111
117
  }
112
118
  throw new Error(`too many redirects from ${url}`);
package/lib/embed.mjs CHANGED
@@ -202,6 +202,7 @@ export async function startEmbeddedAgent({
202
202
  agent.importer?.stop();
203
203
  clearInterval(agent.schedTimer);
204
204
  clearInterval(agent.refreshTimer);
205
+ agent.publisher?.stopPolls();
205
206
  // Same order the standalone agent's shutdown uses: write what is pending,
206
207
  // then let go of the lease so the next agent need not wait out the TTL.
207
208
  await Promise.allSettled([
@@ -10,7 +10,7 @@
10
10
  // DMs, pins and standalone note documents have no place in that layout and
11
11
  // are not carried.
12
12
  //
13
- // Serialised by rdflib, never by hand — the podrdf.mjs rule.
13
+ // Serialised by rdflib, never by hand.
14
14
 
15
15
  import * as $rdf from 'rdflib';
16
16