fedipod-server 0.21.0 → 0.28.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 (332) hide show
  1. package/README.md +5 -4
  2. package/dist/claims.d.ts +3 -1
  3. package/dist/claims.js +20 -7
  4. package/dist/components/context.jsonld +6 -0
  5. package/dist/handler.d.ts +29 -1
  6. package/dist/handler.js +89 -4
  7. package/dist/handler.jsonld +36 -1
  8. package/lib/client/c2s.mjs +100 -3
  9. package/lib/client/masto/accounts.mjs +44 -4
  10. package/lib/client/masto/body.mjs +90 -3
  11. package/lib/client/masto/index.mjs +5 -1
  12. package/lib/client/masto/instance.mjs +11 -3
  13. package/lib/client/masto/media.mjs +3 -57
  14. package/lib/client/masto/oauth.mjs +66 -9
  15. package/lib/client/masto/render.mjs +62 -5
  16. package/lib/client/masto/statuses.mjs +25 -1
  17. package/lib/client/masto/timelines.mjs +128 -6
  18. package/lib/connections/tagfeed.mjs +42 -5
  19. package/lib/core/as2.mjs +36 -5
  20. package/lib/core/contexts/index.mjs +14 -0
  21. package/lib/core/contexts/litepub-0.1.json +60 -0
  22. package/lib/core/contexts/map.json +3 -1
  23. package/lib/core/contexts/quotes.json +18 -0
  24. package/lib/core/graphview.mjs +41 -3
  25. package/lib/core/intake/activities.mjs +136 -2
  26. package/lib/core/intake/activity.mjs +79 -1
  27. package/lib/core/intake/group.mjs +37 -3
  28. package/lib/core/intake/index.mjs +32 -2
  29. package/lib/core/intake/notes.mjs +60 -3
  30. package/lib/core/lease.mjs +12 -2
  31. package/lib/core/profile-page.mjs +104 -0
  32. package/lib/core/publisher/collections.mjs +6 -1
  33. package/lib/core/publisher/index.mjs +35 -17
  34. package/lib/core/publisher/notes.mjs +104 -3
  35. package/lib/core/shapes/activitystreams.ttl +28 -0
  36. package/lib/core/shapes/index.mjs +26 -1
  37. package/lib/core/wire-quotes.mjs +71 -0
  38. package/lib/core/wire.mjs +59 -103
  39. package/lib/device/admin/routes/lifecycle.mjs +9 -0
  40. package/lib/device/admin/static.mjs +4 -1
  41. package/lib/device/admin/surface.mjs +26 -2
  42. package/lib/device/certs.mjs +18 -2
  43. package/lib/device/cli/commands/setup.mjs +6 -2
  44. package/lib/device/cli/commands/state.mjs +3 -1
  45. package/lib/device/gateway-move.mjs +58 -0
  46. package/lib/device/migrate.mjs +3 -1
  47. package/lib/device/setup.mjs +67 -7
  48. package/lib/gateway/front-core.mjs +307 -36
  49. package/lib/gateway/gateway-core.mjs +15 -6
  50. package/lib/gateway/notices.mjs +84 -0
  51. package/lib/gateway/quiet.mjs +184 -0
  52. package/lib/pod/root.mjs +6 -3
  53. package/lib/pod/state.mjs +8 -7
  54. package/lib/pod/transport.mjs +5 -1
  55. package/lib/session/README.md +123 -0
  56. package/lib/session/demo.html +94 -0
  57. package/lib/session/fedi-account.mjs +346 -0
  58. package/lib/session/fedi-login.mjs +123 -0
  59. package/lib/session/oidc-session.mjs +233 -0
  60. package/lib/session/package.json +41 -0
  61. package/package.json +1 -1
  62. package/run-agent.mjs +28 -0
  63. package/vendor/gate.cjs +6 -3
  64. package/web/admin/bar.css +66 -0
  65. package/web/admin/bar.js +38 -0
  66. package/web/admin/client/index.html +31 -3
  67. package/web/admin/client-pick.js +79 -0
  68. package/web/admin/gateway.js +22 -0
  69. package/web/admin/index.html +54 -13
  70. package/web/admin/notices-bar.js +90 -0
  71. package/web/admin/oauth-signin.mjs +37 -0
  72. package/web/admin/record.js +13 -1
  73. package/web/admin/setup/index.html +31 -3
  74. package/web/admin/tokens.css +15 -3
  75. package/web/admin/upkeep.js +4 -5
  76. package/web/app/README.md +14 -10
  77. package/web/app/admin-facade.mjs +51 -12
  78. package/web/app/agent.mjs +157 -19
  79. package/web/app/authorize_interaction.html +56 -0
  80. package/web/app/authorize_interaction.js +69 -0
  81. package/web/app/boot.mjs +233 -95
  82. package/web/app/dist/boot.js +477 -569
  83. package/web/app/dist/boot.js.map +4 -4
  84. package/web/app/dist/sw.js +1861 -532
  85. package/web/app/dist/sw.js.map +4 -4
  86. package/web/app/gateway-move.mjs +60 -0
  87. package/web/app/index.html +40 -49
  88. package/web/app/keys-browser.mjs +12 -15
  89. package/web/app/keystore.mjs +19 -36
  90. package/web/app/oidc-session.mjs +5 -188
  91. package/web/app/signup.mjs +172 -132
  92. package/web/app/sw-src.mjs +1 -1
  93. package/web/app/update.js +66 -0
  94. package/web/front/admin.html +5 -3
  95. package/web/front/new-account.html +2 -2
  96. package/web/front/notices.html +69 -0
  97. package/web/front/notices.js +107 -0
  98. package/web/front/run.html +15 -8
  99. package/web/front/run.js +124 -36
  100. package/web/icons/forum.svg +11 -0
  101. package/web/icons/gateway.svg +14 -0
  102. package/web/icons/local.svg +11 -0
  103. package/web/app/index.html~ +0 -152
  104. package/web/app/site/_headers +0 -9
  105. package/web/app/site/_redirects +0 -22
  106. package/web/app/site/admin/actors.js +0 -145
  107. package/web/app/site/admin/bar.css +0 -60
  108. package/web/app/site/admin/bar.js +0 -61
  109. package/web/app/site/admin/client/client.js +0 -66
  110. package/web/app/site/admin/client/index.html +0 -43
  111. package/web/app/site/admin/common.js +0 -23
  112. package/web/app/site/admin/connections.js +0 -112
  113. package/web/app/site/admin/gateway.js +0 -111
  114. package/web/app/site/admin/group.js +0 -258
  115. package/web/app/site/admin/index.html +0 -564
  116. package/web/app/site/admin/record.js +0 -378
  117. package/web/app/site/admin/setup/index.html +0 -215
  118. package/web/app/site/admin/setup/setup.js +0 -326
  119. package/web/app/site/admin/tokens.css +0 -56
  120. package/web/app/site/admin/upkeep.js +0 -178
  121. package/web/app/site/admin/window.css +0 -55
  122. package/web/app/site/admin/window.js +0 -136
  123. package/web/app/site/app/404.html +0 -40
  124. package/web/app/site/app/_headers +0 -2
  125. package/web/app/site/app/apple-touch-icon.png +0 -0
  126. package/web/app/site/app/assets/ICONS-DIPJeU0C.js +0 -2
  127. package/web/app/site/app/assets/ICONS-DIPJeU0C.js.map +0 -1
  128. package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js +0 -183
  129. package/web/app/site/app/assets/ScheduledAtField-D-Abfo4J.js.map +0 -1
  130. package/web/app/site/app/assets/Temml-CCjoacWt.woff2 +0 -0
  131. package/web/app/site/app/assets/__vite-browser-external-C7iut881.js +0 -2
  132. package/web/app/site/app/assets/__vite-browser-external-C7iut881.js.map +0 -1
  133. package/web/app/site/app/assets/boosts-carousel-BiOaNdMT.jpg +0 -0
  134. package/web/app/site/app/assets/catch-up-O5q5C75Z.png +0 -0
  135. package/web/app/site/app/assets/chunk-aKtaBQYM.js +0 -1
  136. package/web/app/site/app/assets/compose-CFEx7wb4.js +0 -2
  137. package/web/app/site/app/assets/compose-CFEx7wb4.js.map +0 -1
  138. package/web/app/site/app/assets/compose-ZJN5xSb4.js +0 -35
  139. package/web/app/site/app/assets/compose-ZJN5xSb4.js.map +0 -1
  140. package/web/app/site/app/assets/debug.module-YFQgwnIr.js +0 -52
  141. package/web/app/site/app/assets/debug.module-YFQgwnIr.js.map +0 -1
  142. package/web/app/site/app/assets/dom-p1YcJ5Rw.js +0 -2
  143. package/web/app/site/app/assets/dom-p1YcJ5Rw.js.map +0 -1
  144. package/web/app/site/app/assets/home-mobile-dark@2x-Dc-J8-SM.png +0 -0
  145. package/web/app/site/app/assets/home-mobile-light@2x-Bd3fod8m.png +0 -0
  146. package/web/app/site/app/assets/home-tablet-dark@2x-BgcNI8le.png +0 -0
  147. package/web/app/site/app/assets/home-tablet-light@2x-BW2RV9T6.png +0 -0
  148. package/web/app/site/app/assets/icons/add-circle-line-WD0mwORD.js +0 -1
  149. package/web/app/site/app/assets/icons/alert-line-CpFUMf9s.js +0 -1
  150. package/web/app/site/app/assets/icons/android-2-line-Bzxnrd3S.js +0 -1
  151. package/web/app/site/app/assets/icons/announcement-line-5nwaJFJm.js +0 -1
  152. package/web/app/site/app/assets/icons/arrow-down-circle-line-a7Id9-Iv.js +0 -1
  153. package/web/app/site/app/assets/icons/arrow-down-line-B8uzXzq6.js +0 -1
  154. package/web/app/site/app/assets/icons/arrow-left-line-CGrGT9C-.js +0 -1
  155. package/web/app/site/app/assets/icons/arrow-right-line-CE-HERfX.js +0 -1
  156. package/web/app/site/app/assets/icons/arrow-to-up-line-CvdQjmcy.js +0 -1
  157. package/web/app/site/app/assets/icons/arrow-up-circle-line-DEparSNF.js +0 -1
  158. package/web/app/site/app/assets/icons/arrow-up-line-C7yBeugc.js +0 -1
  159. package/web/app/site/app/assets/icons/arrows-right-line-BtbXmJGP.js +0 -1
  160. package/web/app/site/app/assets/icons/at-line-CF66Bznk.js +0 -1
  161. package/web/app/site/app/assets/icons/attachment-line-BY8It-l9.js +0 -1
  162. package/web/app/site/app/assets/icons/blockquote-line-BS6pU_hm.js +0 -1
  163. package/web/app/site/app/assets/icons/board-line-C0UWXyA6.js +0 -1
  164. package/web/app/site/app/assets/icons/bookmark-line-1CtX5JLF.js +0 -1
  165. package/web/app/site/app/assets/icons/building-5-line-Dd59MzbO.js +0 -1
  166. package/web/app/site/app/assets/icons/bus-2-line-6_dvA0GG.js +0 -1
  167. package/web/app/site/app/assets/icons/calendar-day-line-Crpl_fmu.js +0 -1
  168. package/web/app/site/app/assets/icons/calendar-month-line-vommts2C.js +0 -1
  169. package/web/app/site/app/assets/icons/calendar-time-add-line-BU_DTlQk.js +0 -1
  170. package/web/app/site/app/assets/icons/camera-line-Cv69MEei.js +0 -1
  171. package/web/app/site/app/assets/icons/celebrate-line-B8DvIoi0.js +0 -1
  172. package/web/app/site/app/assets/icons/chart-bar-line-FK-QOmtF.js +0 -1
  173. package/web/app/site/app/assets/icons/chart-line-line-BGcJAFWw.js +0 -1
  174. package/web/app/site/app/assets/icons/chat-3-line-YFK2-hwz.js +0 -1
  175. package/web/app/site/app/assets/icons/check-circle-line-DsAxFr5-.js +0 -1
  176. package/web/app/site/app/assets/icons/clipboard-line-BBp364gJ.js +0 -1
  177. package/web/app/site/app/assets/icons/close-circle-line-CICdiuGz.js +0 -1
  178. package/web/app/site/app/assets/icons/close-line-DYrFWcjv.js +0 -1
  179. package/web/app/site/app/assets/icons/cloud-line-tiQAbah8.js +0 -1
  180. package/web/app/site/app/assets/icons/code-line-fAl8iiV3.js +0 -1
  181. package/web/app/site/app/assets/icons/comment-2-line-CR3g7WeB.js +0 -1
  182. package/web/app/site/app/assets/icons/copy-2-line-CLW69yF5.js +0 -1
  183. package/web/app/site/app/assets/icons/delete-2-line-B8xmbr4n.js +0 -1
  184. package/web/app/site/app/assets/icons/document-3-line-DBGNhAg2.js +0 -1
  185. package/web/app/site/app/assets/icons/document-line-C7mb9sb7.js +0 -1
  186. package/web/app/site/app/assets/icons/down-line-BGqSSThd.js +0 -1
  187. package/web/app/site/app/assets/icons/edit-4-line-DcgGaEhx.js +0 -1
  188. package/web/app/site/app/assets/icons/emoji-2-line-D8YgnM-y.js +0 -1
  189. package/web/app/site/app/assets/icons/exit-line-Dc07BS-x.js +0 -1
  190. package/web/app/site/app/assets/icons/external-link-line-BvpSkmjO.js +0 -1
  191. package/web/app/site/app/assets/icons/eye-2-line-CiWXx-f_.js +0 -1
  192. package/web/app/site/app/assets/icons/eye-close-line-BgTaSJ4P.js +0 -1
  193. package/web/app/site/app/assets/icons/filter-2-line-B_mR2usy.js +0 -1
  194. package/web/app/site/app/assets/icons/filter-line-C_nm-3cU.js +0 -1
  195. package/web/app/site/app/assets/icons/flag-1-line-C2HB05I0.js +0 -1
  196. package/web/app/site/app/assets/icons/forbid-circle-line-D3LTT9yd.js +0 -1
  197. package/web/app/site/app/assets/icons/formula-line-DLrt2d6j.js +0 -1
  198. package/web/app/site/app/assets/icons/grid-line-CgUmEikf.js +0 -1
  199. package/web/app/site/app/assets/icons/group-line-C5fnX0wU.js +0 -1
  200. package/web/app/site/app/assets/icons/hand-finger-2-line-BGgxbuL9.js +0 -1
  201. package/web/app/site/app/assets/icons/hashtag-line-CyTEEXBb.js +0 -1
  202. package/web/app/site/app/assets/icons/heart-crack-line-BZddbO2C.js +0 -1
  203. package/web/app/site/app/assets/icons/heart-line-CJ7K47J4.js +0 -1
  204. package/web/app/site/app/assets/icons/history-2-line-kWWvFzqv.js +0 -1
  205. package/web/app/site/app/assets/icons/history-line-bGQiwbTH.js +0 -1
  206. package/web/app/site/app/assets/icons/home-3-line-fRU1zeLG.js +0 -1
  207. package/web/app/site/app/assets/icons/information-line-iNk6-sOY.js +0 -1
  208. package/web/app/site/app/assets/icons/keyboard-line-DsCyuQNz.js +0 -1
  209. package/web/app/site/app/assets/icons/layout-4-line-CZkOX52Z.js +0 -1
  210. package/web/app/site/app/assets/icons/layout-5-line-B_znt5wO.js +0 -1
  211. package/web/app/site/app/assets/icons/left-line-eUw0tya4.js +0 -1
  212. package/web/app/site/app/assets/icons/lightning-line-DaKoDdix.js +0 -1
  213. package/web/app/site/app/assets/icons/link-2-line-DCqLmMA7.js +0 -1
  214. package/web/app/site/app/assets/icons/list-check-line-BAxosBh9.js +0 -1
  215. package/web/app/site/app/assets/icons/lock-line-CPoaXeUW.js +0 -1
  216. package/web/app/site/app/assets/icons/mail-line-B0P8aa1L.js +0 -1
  217. package/web/app/site/app/assets/icons/moon-line-CEqNAToP.js +0 -1
  218. package/web/app/site/app/assets/icons/more-1-fill-Dw2e5xab.js +0 -1
  219. package/web/app/site/app/assets/icons/more-3-line-BIiVjYTz.js +0 -1
  220. package/web/app/site/app/assets/icons/notification-line-BZZq2Gtu.js +0 -1
  221. package/web/app/site/app/assets/icons/pencil-line-CKh8-A1v.js +0 -1
  222. package/web/app/site/app/assets/icons/photo-album-line-Bnfg2u40.js +0 -1
  223. package/web/app/site/app/assets/icons/pin-line-DpTolyhs.js +0 -1
  224. package/web/app/site/app/assets/icons/play-fill-B0-G_8lX.js +0 -1
  225. package/web/app/site/app/assets/icons/qrcode-2-line-B6SPCaHn.js +0 -1
  226. package/web/app/site/app/assets/icons/quill-pen-line-B6LUrnCP.js +0 -1
  227. package/web/app/site/app/assets/icons/quote-left-fill-hQZ1cj_6.js +0 -1
  228. package/web/app/site/app/assets/icons/radar-line-CKyroTth.js +0 -1
  229. package/web/app/site/app/assets/icons/react-line-CoIKhhtK.js +0 -1
  230. package/web/app/site/app/assets/icons/refresh-2-line-D0mTF97S.js +0 -1
  231. package/web/app/site/app/assets/icons/right-line-B3KWJaqc.js +0 -1
  232. package/web/app/site/app/assets/icons/rocket-line-4KZl537D.js +0 -1
  233. package/web/app/site/app/assets/icons/round-fill-C69NTrZ0.js +0 -1
  234. package/web/app/site/app/assets/icons/round-line-B9k_1uo-.js +0 -1
  235. package/web/app/site/app/assets/icons/route-line-B28ReHcE.js +0 -1
  236. package/web/app/site/app/assets/icons/rows-4-line-CrBniagM.js +0 -1
  237. package/web/app/site/app/assets/icons/scan-line-DSf74YdP.js +0 -1
  238. package/web/app/site/app/assets/icons/search-2-line-B6geIU1z.js +0 -1
  239. package/web/app/site/app/assets/icons/settings-3-line-azJwK47w.js +0 -1
  240. package/web/app/site/app/assets/icons/settings-6-line-C_5zc5YR.js +0 -1
  241. package/web/app/site/app/assets/icons/share-2-line-D5MxWjrm.js +0 -1
  242. package/web/app/site/app/assets/icons/share-forward-line-Cp61fZzZ.js +0 -1
  243. package/web/app/site/app/assets/icons/sparkles-2-line-DYYyXTaW.js +0 -1
  244. package/web/app/site/app/assets/icons/sparkles-line-C2hY1s6I.js +0 -1
  245. package/web/app/site/app/assets/icons/time-line-BF3eet1v.js +0 -1
  246. package/web/app/site/app/assets/icons/transfer-4-line-oisfvTBw.js +0 -1
  247. package/web/app/site/app/assets/icons/translate-line-BFWol2Ce.js +0 -1
  248. package/web/app/site/app/assets/icons/unlock-line-X_x5vwv3.js +0 -1
  249. package/web/app/site/app/assets/icons/upload-3-line-DgzwUJeW.js +0 -1
  250. package/web/app/site/app/assets/icons/user-4-line-BVSynZCp.js +0 -1
  251. package/web/app/site/app/assets/icons/user-add-2-line-BlGS5Q8q.js +0 -1
  252. package/web/app/site/app/assets/icons/user-add-line-BbXdHG4z.js +0 -1
  253. package/web/app/site/app/assets/icons/user-edit-line-BFAHOV0X.js +0 -1
  254. package/web/app/site/app/assets/icons/user-follow-line-BXux0wSd.js +0 -1
  255. package/web/app/site/app/assets/icons/user-star-line-DdYlpHLU.js +0 -1
  256. package/web/app/site/app/assets/icons/user-warning-line-Cj43j0_E.js +0 -1
  257. package/web/app/site/app/assets/icons/user-x-line-DIDgNlPH.js +0 -1
  258. package/web/app/site/app/assets/icons/volume-line-Bs390KQt.js +0 -1
  259. package/web/app/site/app/assets/icons/volume-mute-line-DzlzIqFZ.js +0 -1
  260. package/web/app/site/app/assets/icons/walk-line-yNXfB-md.js +0 -1
  261. package/web/app/site/app/assets/icons/world-2-line-CenkGIwj.js +0 -1
  262. package/web/app/site/app/assets/icons/zoom-in-line-CaENUphf.js +0 -1
  263. package/web/app/site/app/assets/icons/zoom-out-line-BDNk0EWo.js +0 -1
  264. package/web/app/site/app/assets/instances-BNPptnn-.json +0 -333
  265. package/web/app/site/app/assets/locales/ar-SA-CfheRbCu.js +0 -1
  266. package/web/app/site/app/assets/locales/ca-ES-DHRW86Tz.js +0 -1
  267. package/web/app/site/app/assets/locales/cs-CZ-CKoqEuA1.js +0 -1
  268. package/web/app/site/app/assets/locales/de-DE-ByRPMRFy.js +0 -1
  269. package/web/app/site/app/assets/locales/eo-UY-CPC7wLCS.js +0 -1
  270. package/web/app/site/app/assets/locales/es-ES-dJa0Fd9t.js +0 -1
  271. package/web/app/site/app/assets/locales/eu-ES-C3djlPR2.js +0 -1
  272. package/web/app/site/app/assets/locales/fa-IR-DTT490Ck.js +0 -1
  273. package/web/app/site/app/assets/locales/fi-FI-B23MCPuz.js +0 -1
  274. package/web/app/site/app/assets/locales/fr-FR-BcaQsO5C.js +0 -1
  275. package/web/app/site/app/assets/locales/gl-ES-BR-CVKBN.js +0 -1
  276. package/web/app/site/app/assets/locales/he-IL-CfheRbCu.js +0 -1
  277. package/web/app/site/app/assets/locales/hu-HU-CfheRbCu.js +0 -1
  278. package/web/app/site/app/assets/locales/it-IT-C1136UFV.js +0 -1
  279. package/web/app/site/app/assets/locales/ja-JP-CRZmRAhD.js +0 -1
  280. package/web/app/site/app/assets/locales/kab-Cz8xH_TT.js +0 -1
  281. package/web/app/site/app/assets/locales/ko-KR-CG9UiY4o.js +0 -1
  282. package/web/app/site/app/assets/locales/lt-LT-CJcI6sHZ.js +0 -1
  283. package/web/app/site/app/assets/locales/nb-NO-CfheRbCu.js +0 -1
  284. package/web/app/site/app/assets/locales/nl-NL-DxN4Yc1t.js +0 -1
  285. package/web/app/site/app/assets/locales/oc-FR-CfheRbCu.js +0 -1
  286. package/web/app/site/app/assets/locales/pl-PL-DkwGXf6P.js +0 -1
  287. package/web/app/site/app/assets/locales/pseudo-LOCALE-CQ4XxkQ0.js +0 -1
  288. package/web/app/site/app/assets/locales/pt-BR-nGL0HdFS.js +0 -1
  289. package/web/app/site/app/assets/locales/pt-PT-Cp17aj2z.js +0 -1
  290. package/web/app/site/app/assets/locales/ru-RU-0Y8cIoaK.js +0 -1
  291. package/web/app/site/app/assets/locales/th-TH-CfheRbCu.js +0 -1
  292. package/web/app/site/app/assets/locales/tok-CfheRbCu.js +0 -1
  293. package/web/app/site/app/assets/locales/tr-TR-CfheRbCu.js +0 -1
  294. package/web/app/site/app/assets/locales/uk-UA-C5E3dFBf.js +0 -1
  295. package/web/app/site/app/assets/locales/zh-CN-BHJi7_et.js +0 -1
  296. package/web/app/site/app/assets/locales/zh-TW-CfheRbCu.js +0 -1
  297. package/web/app/site/app/assets/main-BdqNbG-a.js +0 -26
  298. package/web/app/site/app/assets/main-BdqNbG-a.js.map +0 -1
  299. package/web/app/site/app/assets/mock-home-DGhR__He.js +0 -2
  300. package/web/app/site/app/assets/mock-home-DGhR__He.js.map +0 -1
  301. package/web/app/site/app/assets/multi-column-ROck0NVt.jpg +0 -0
  302. package/web/app/site/app/assets/multi-hashtag-timeline-DH5INVHi.jpg +0 -0
  303. package/web/app/site/app/assets/nested-comments-thread-hv59kZLc.jpg +0 -0
  304. package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js +0 -2
  305. package/web/app/site/app/assets/polyfill-force-H8sUkLGp.js.map +0 -1
  306. package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js +0 -20
  307. package/web/app/site/app/assets/pwa-viewport-ogKbF51K.js.map +0 -1
  308. package/web/app/site/app/assets/style-B1iLPTPR.css +0 -2
  309. package/web/app/site/app/assets/temml-DuyIQMei.js +0 -97
  310. package/web/app/site/app/assets/temml-DuyIQMei.js.map +0 -1
  311. package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js +0 -2
  312. package/web/app/site/app/assets/tinyld.light.node-DtbBhLYC.js.map +0 -1
  313. package/web/app/site/app/assets/year-in-posts-B2lywqdx.png +0 -0
  314. package/web/app/site/app/assets/year-in-posts-DJv_star.js +0 -3
  315. package/web/app/site/app/assets/year-in-posts-DJv_star.js.map +0 -1
  316. package/web/app/site/app/compose/index.html +0 -20
  317. package/web/app/site/app/favicon.ico +0 -0
  318. package/web/app/site/app/index.html +0 -73
  319. package/web/app/site/app/logo-192.png +0 -0
  320. package/web/app/site/app/logo-512.png +0 -0
  321. package/web/app/site/app/logo-badge-72.png +0 -0
  322. package/web/app/site/app/logo-maskable-512.png +0 -0
  323. package/web/app/site/app/logo-monochrome-512.png +0 -0
  324. package/web/app/site/app/logo-monochrome-maskable-512.png +0 -0
  325. package/web/app/site/app/manifest.webmanifest +0 -1
  326. package/web/app/site/app/og-image-2.jpg +0 -0
  327. package/web/app/site/app/og-image.png +0 -0
  328. package/web/app/site/app/robots.txt +0 -2
  329. package/web/app/site/app/version.json +0 -1
  330. package/web/app/site/boot.js +0 -34277
  331. package/web/app/site/index.html +0 -251
  332. package/web/app/site/sw.js +0 -71331
@@ -0,0 +1,107 @@
1
+ // notices.js — the notices page's script: the admin signs in, then writes,
2
+ // changes and removes the notices every account here sees behind the bell.
3
+ // Served by the front at /notices.js, like admin.js for the roster.
4
+ const $ = (id) => document.getElementById(id);
5
+ const note = (text) => { const n = $('notices-note'); n.hidden = !text; n.textContent = text || ''; };
6
+
7
+ let session = null;
8
+ try {
9
+ const { SessionCore } = await import('/solid-oidc-client.js');
10
+ session = new SessionCore({ redirect_uris: [location.origin + '/notices'], client_name: 'FediPod admin' });
11
+ } catch { /* leave null — the "did not load" note fires */ }
12
+
13
+ $('notices-issuer').addEventListener('input', () => {
14
+ $('notices-signin').disabled = !/^https?:\/\/\S+/.test($('notices-issuer').value.trim());
15
+ });
16
+
17
+ $('notices-form').addEventListener('submit', (ev) => {
18
+ ev.preventDefault();
19
+ if (!session) { note('the sign-in library did not load — reload and try again'); return; }
20
+ session.login($('notices-issuer').value.trim(), location.origin + '/notices')
21
+ .catch((e) => note('sign-in failed to start: ' + e.message));
22
+ });
23
+
24
+ (async () => {
25
+ if (!session) return;
26
+ await session.handleRedirectFromLogin().catch(() => {});
27
+ if (!session.isActive) return;
28
+ const webId = session.webId;
29
+ let editing = null; // the notice being changed, or null for a new one
30
+
31
+ const when = (iso) => { try { return new Date(iso).toLocaleString(); } catch { return iso; } };
32
+
33
+ const send = async (body) => {
34
+ let res;
35
+ try {
36
+ res = await session.authFetch(location.origin + '/api/notices', {
37
+ method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body),
38
+ });
39
+ } catch (e) { note('the request failed: ' + e.message); return null; }
40
+ const d = await res.json().catch(() => ({}));
41
+ if (res.status === 403) { note('signed in as ' + webId + ', which is not this server’s admin'); return null; }
42
+ if (res.status === 501) { note('this server keeps no notices'); return null; }
43
+ if (res.status >= 400) { note('refused: ' + (d.error || 'HTTP ' + res.status)); return null; }
44
+ return d;
45
+ };
46
+
47
+ const startEdit = (n) => {
48
+ editing = n;
49
+ $('editor-title').textContent = n ? 'Change this notice' : 'New notice';
50
+ $('notice-title').value = n ? n.title : '';
51
+ $('notice-body').value = n ? n.body : '';
52
+ $('notice-save').textContent = n ? 'Save changes' : 'Publish';
53
+ $('notice-cancel').hidden = !n;
54
+ $('notice-title').focus();
55
+ };
56
+
57
+ const load = async () => {
58
+ let res;
59
+ try { res = await fetch(location.origin + '/api/notices', { headers: { accept: 'application/json' }, cache: 'no-store' }); }
60
+ catch (e) { note('the notices could not be read: ' + e.message); return; }
61
+ if (res.status === 501) { note('this server keeps no notices'); return; }
62
+ const d = await res.json().catch(() => ({}));
63
+ const ul = $('notices-list');
64
+ ul.textContent = '';
65
+ for (const n of d.notices || []) {
66
+ const li = document.createElement('li');
67
+ const head = document.createElement('div');
68
+ const t = document.createElement('span'); t.className = 'title'; t.textContent = n.title;
69
+ const w = document.createElement('span'); w.className = 'when';
70
+ w.textContent = when(n.at) + (n.updatedAt && n.updatedAt !== n.at ? ' (changed ' + when(n.updatedAt) + ')' : '');
71
+ head.append(t, w);
72
+ const b = document.createElement('p'); b.className = 'body'; b.textContent = n.body;
73
+ const acts = document.createElement('p'); acts.className = 'actions';
74
+ const edit = document.createElement('button'); edit.type = 'button'; edit.textContent = 'Change';
75
+ edit.onclick = () => startEdit(n);
76
+ const rm = document.createElement('button'); rm.type = 'button'; rm.textContent = 'Remove'; rm.className = 'danger';
77
+ rm.onclick = async () => {
78
+ if (!confirm('Remove the notice “' + n.title + '”? Everyone stops seeing it.')) return;
79
+ if (await send({ action: 'delete', id: n.id })) { note('removed “' + n.title + '”'); await load(); }
80
+ };
81
+ acts.append(edit, rm);
82
+ li.append(head, b, acts);
83
+ ul.append(li);
84
+ }
85
+ if (!(d.notices || []).length) { const li = document.createElement('li'); li.textContent = 'No notices yet.'; ul.append(li); }
86
+ $('notices-editor').hidden = false;
87
+ };
88
+
89
+ $('editor-form').addEventListener('submit', async (ev) => {
90
+ ev.preventDefault();
91
+ const title = $('notice-title').value.trim();
92
+ const body = $('notice-body').value.trim();
93
+ if (!title || !body) { note('a title and a text are both needed'); return; }
94
+ $('notice-save').disabled = true;
95
+ const r = await send(editing ? { action: 'update', id: editing.id, title, body } : { action: 'create', title, body });
96
+ $('notice-save').disabled = false;
97
+ if (!r) return;
98
+ note(editing ? 'changed “' + title + '”' : 'published “' + title + '” — everyone sees it within a minute');
99
+ startEdit(null);
100
+ await load();
101
+ });
102
+ $('notice-cancel').addEventListener('click', () => startEdit(null));
103
+
104
+ note('signed in as ' + webId);
105
+ $('notices-form').hidden = true;
106
+ await load();
107
+ })();
@@ -3,31 +3,39 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>FediPod — run your identity on this server</title>
6
+ <title>FediPod — turn your pod into a Fediverse account</title>
7
+ <link rel="icon" href="/icons/gateway.svg" type="image/svg+xml">
7
8
  <style>
8
9
  :root { color-scheme: light dark; --line:#d9d4c7; --dim:#45443d; --accent:#6a8a5a; }
9
10
  @media (prefers-color-scheme: dark) { :root { --dim:#c2c0b4; } }
10
- body { font: 19px/1.6 system-ui, sans-serif; max-width: 44rem; margin: 2rem auto; padding: 0 1.1rem; }
11
+ body { font: 20px/1.6 Arial, Helvetica, sans-serif; max-width: 44rem; margin: 2rem auto; padding: 0 1.1rem; }
11
12
  h1 { font-size: 1.7rem; margin: 0 0 .2rem; }
12
13
  p.lede { color: var(--dim); margin-top: 0; }
13
14
  label { display: block; font-weight: 600; margin: .8rem 0 .2rem; }
14
15
  input[type=text], input[type=url] { width: 100%; padding: .5rem .6rem; font: inherit;
15
16
  border: 1px solid var(--line); border-radius: 8px; box-sizing: border-box; }
16
17
  .hint { color: var(--dim); font-size: .95rem; }
18
+ .pod { border: 1px solid var(--line); border-radius: 9px; padding: .9rem 1.1rem; margin: .8rem 0; }
19
+ .pod p { margin: .3rem 0; }
20
+ .pod .actions { margin-top: .8rem; }
17
21
  .primary { background: var(--accent); color: #fff; border: none; border-radius: 9px;
18
22
  padding: .6rem 1.1rem; font: inherit; cursor: pointer; }
19
23
  button { font: inherit; }
20
24
  .primary[disabled], button[disabled] { opacity: .5; cursor: not-allowed; }
21
25
  [hidden] { display: none !important; }
22
26
  code { background: rgba(120,120,120,.12); padding: .05em .35em; border-radius: 4px; }
27
+ .pod code { background: #fff3c4; color: #1a1a1a; font-size: 16px; }
28
+ @media (prefers-color-scheme: dark) { .pod code { background: #5a4a00; color: #fff; } }
23
29
  pre { background: rgba(120,120,120,.12); padding: .7rem .9rem; border-radius: 8px; overflow-x: auto; }
24
30
  </style>
25
31
  </head>
26
32
  <body>
27
- <h1>Run your identity on this server</h1>
28
- <p class="lede">If your pod is hosted by this server, the server can run your Fediverse identity
29
- for you: it accepts follows, delivers your posts and serves your Mastodon app, with nothing for
30
- you to keep running. Sign in with your pod to prove it is yours.</p>
33
+ <h1>Turn your pod into a Fediverse account</h1>
34
+ <p class="lede">Users with pods on this server may opt-in below to create a Fediverse account
35
+ that stores your data on your pod. You'll be able to interact with Mastodon and users of other
36
+ Fediverse services straight from your pod.</p>
37
+
38
+ <section id="run-known" hidden aria-live="polite"></section>
31
39
 
32
40
  <form id="run-form">
33
41
  <p class="field">
@@ -42,10 +50,9 @@ you to keep running. Sign in with your pod to prove it is yours.</p>
42
50
  <button type="button" id="run-continue" class="primary" disabled>Sign in with your pod &amp; opt in</button>
43
51
  <button type="button" id="run-leave">Stop running it here</button>
44
52
  </p>
45
- <p class="hint" id="run-note" hidden></p>
46
53
  </form>
54
+ <p class="hint" id="run-note" hidden></p>
47
55
 
48
56
  <script type="module" src="/run.js"></script>
49
- <i>(cc) 4.0 By, Jeff Zucker, 2026</i>
50
57
  </body>
51
58
  </html>
package/web/front/run.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // It lived inline in run.html until 2026-09-09. Out here the page can be served
4
4
  // under `script-src 'self'`, which is what stops a stray bit of markup from
5
5
  // becoming running code; inline script cannot be told apart from injected
6
- // script by any policy. Served by the front at /run.js.
6
+ // script by any policy. Served by the front beside the page it belongs to.
7
7
  //
8
8
  // A module, because it awaits an import of /solid-oidc-client.js at the top
9
9
  // level — which is itself the proof this mechanism works: that file has been
@@ -13,28 +13,90 @@ const $ = (id) => document.getElementById(id);
13
13
  // The Solid-OIDC client for the sign-in round trip. Constructed once; the
14
14
  // redirect state (PKCE, csrf) lives in this tab's sessionStorage, so the same
15
15
  // session finishes the login on the way back.
16
+ // This page's own address. The identity provider is told it and sends the
17
+ // reader back to it, so a hard-coded name would end the sign-in on a page that
18
+ // does not exist wherever the operator put this one.
19
+ const HERE = location.origin + location.pathname.replace(/\/$/u, '');
16
20
  let session = null;
17
21
  try {
18
22
  const { SessionCore } = await import('/solid-oidc-client.js');
19
- session = new SessionCore({ redirect_uris: [location.origin + '/run'], client_name: 'FediPod gateway' });
23
+ session = new SessionCore({ redirect_uris: [HERE], client_name: 'FediPod gateway' });
20
24
  } catch { /* leave null — the "did not load" notes below fire */ }
21
25
 
22
- // Offered only where this server actually runs identities. An
23
- // unauthenticated probe tells the two apart: 501 = not offered here,
24
- // anything else = offered (a real opt-in still needs the signed-in proof).
26
+ // What this server knows before anything is typed. 501: it runs no
27
+ // identities. A pod server that issued the reader's session names their pod
28
+ // and its address, and the page shows one button per pod. Not signed in
29
+ // there: one button, to its login. A Gateway knows nothing: the form below.
25
30
  let offered = true;
31
+ const say = (tag, text) => { const e = document.createElement(tag); e.textContent = text; return e; };
26
32
  (async () => {
27
- const res = await fetch('/api/agent', { method: 'POST',
28
- headers: { 'content-type': 'application/json' }, body: '{}' }).catch(() => null);
33
+ const res = await fetch('/api/agent', { credentials: 'same-origin', headers: { accept: 'application/json' } }).catch(() => null);
34
+ const d = res && res.ok ? await res.json().catch(() => ({})) : {};
35
+ const n = $('run-note');
29
36
  if (!res || res.status === 501) {
30
37
  offered = false;
31
- const n = $('run-note');
32
38
  n.hidden = false;
33
39
  n.textContent = 'This server does not run identities. Your agent stays where it is.';
34
- runFormCheck();
40
+ } else if (d.session === 'none') {
41
+ $('run-form').hidden = true;
42
+ showSignIn(d.loginUrl);
43
+ } else if (d.session === 'ok' && Array.isArray(d.pods) && d.pods.length) {
44
+ $('run-form').hidden = true;
45
+ showPods(d.pods);
35
46
  }
47
+ runFormCheck();
36
48
  })();
37
49
 
50
+ async function refreshKnown() {
51
+ const res = await fetch('/api/agent', { credentials: 'same-origin', headers: { accept: 'application/json' } }).catch(() => null);
52
+ const d = res && res.ok ? await res.json().catch(() => ({})) : {};
53
+ if (d.session === 'ok' && Array.isArray(d.pods) && d.pods.length) showPods(d.pods);
54
+ }
55
+
56
+ function showSignIn(loginUrl) {
57
+ const k = $('run-known');
58
+ k.hidden = false;
59
+ k.replaceChildren();
60
+ k.append(say('p', 'You are not signed in at this server.'));
61
+ if (loginUrl) {
62
+ const go = say('button', 'Sign in');
63
+ go.type = 'button'; go.className = 'primary';
64
+ go.onclick = () => { location.href = loginUrl; };
65
+ const p = document.createElement('p'); p.className = 'actions'; p.append(go);
66
+ k.append(p, say('p', 'Sign in, then come back to this page.'));
67
+ k.lastChild.className = 'hint';
68
+ }
69
+ }
70
+
71
+ function showPods(pods) {
72
+ const k = $('run-known');
73
+ k.hidden = false;
74
+ k.replaceChildren();
75
+ for (const pod of pods) {
76
+ const box = document.createElement('div'); box.className = 'pod';
77
+ // The names stand out from the sentences around them.
78
+ const line = (before, id, after = '.') => { const p = say('p', before); p.append(say('code', id), after); return p; };
79
+ box.append(line('Solid Identity (WebID): ', pod.webId, ''));
80
+ const actions = document.createElement('p'); actions.className = 'actions';
81
+ box.append(line('Fediverse Identity: ', pod.address, ''));
82
+ if (pod.running) {
83
+ const links = say('p', 'Manage your account: ');
84
+ const m = say('a', pod.manage.split('?')[0]); m.href = pod.manage;
85
+ links.append(m);
86
+ box.append(links);
87
+ const stop = say('button', 'Close this Fediverse account'); stop.type = 'button'; stop.className = 'primary';
88
+ stop.onclick = () => runStart('opt-out', pod.podBase);
89
+ actions.append(stop);
90
+ } else {
91
+ const go = say('button', 'Create a Fediverse account'); go.type = 'button'; go.className = 'primary';
92
+ go.onclick = () => runStart('opt-in', pod.podBase);
93
+ actions.append(go);
94
+ }
95
+ box.append(actions);
96
+ k.append(box);
97
+ }
98
+ }
99
+
38
100
  function runFormCheck() {
39
101
  let ok = false;
40
102
  try { ok = /^https?:$/.test(new URL($('run-pod-url').value.trim()).protocol); } catch { /* not yet */ }
@@ -53,22 +115,67 @@ $('run-pod-url').addEventListener('input', () => {
53
115
  runFormCheck();
54
116
  });
55
117
  $('run-issuer').addEventListener('input', runFormCheck);
118
+ // A browser that puts back what was in these boxes — a reload, the back
119
+ // button, its own remembered values — fills them without anybody typing, and
120
+ // no typing meant the button was never asked to wake up. It stayed grey over
121
+ // a filled-in form, with nothing to say why.
122
+ runFormCheck();
56
123
 
57
- const runStart = (action) => {
124
+ const runStart = async (action, podBase = null) => {
58
125
  const n = $('run-note');
59
- if (!session) { n.hidden = false; n.textContent = 'the sign-in library did not load — reload and try again'; return; }
60
- const u = new URL($('run-pod-url').value.trim());
126
+ const u = new URL(podBase || $('run-pod-url').value.trim());
61
127
  if (u.pathname === '') u.pathname = '/';
62
128
  if (!u.pathname.endsWith('/')) u.pathname += '/';
63
129
  u.search = ''; u.hash = '';
64
- sessionStorage.setItem('fp-run', JSON.stringify({ podBase: u.href, action }));
65
- session.login($('run-issuer').value.trim(), location.origin + '/run')
66
- .catch((e) => { n.hidden = false; n.textContent = 'sign-in failed to start: ' + e.message; });
130
+ const p = { podBase: u.href, action };
131
+
132
+ // A pod server issued the session this page is being read with, so ask it
133
+ // first: where it knows who you are, there is nothing to sign in to again.
134
+ // A Gateway fronting somebody else's pod answers 401 here and the login
135
+ // below is the only way.
136
+ n.hidden = false;
137
+ n.textContent = 'asking the server…';
138
+ const known = await fetch('/api/agent', {
139
+ method: 'POST', credentials: 'same-origin',
140
+ headers: { 'content-type': 'application/json' },
141
+ body: JSON.stringify(p),
142
+ }).catch(() => null);
143
+ if (known && known.status !== 401) { await showReply(known, p); return; }
144
+
145
+ if (!session) { n.textContent = 'the sign-in library did not load — reload and try again'; return; }
146
+ sessionStorage.setItem('fp-run', JSON.stringify(p));
147
+ session.login($('run-issuer').value.trim(), HERE)
148
+ .catch((e) => { n.textContent = 'sign-in failed to start: ' + e.message; });
67
149
  };
68
150
  $('run-continue').onclick = () => runStart('opt-in');
69
151
  $('run-leave').onclick = () => runStart('opt-out');
70
152
 
71
- // Back from the identity provider: finish the opt-in with the proven login.
153
+ // What came of it, however the server was satisfied — the session it already
154
+ // had, or a login proved afterwards.
155
+ async function showReply(res, p) {
156
+ const n = $('run-note');
157
+ n.hidden = false;
158
+ const d = res ? await res.json().catch(() => ({})) : {};
159
+ if (res && res.status === 201 && d.doorSecret) {
160
+ // Built as nodes, not as a string of HTML. Three of the pieces below come
161
+ // back from the server and one comes from sessionStorage, and pasting any
162
+ // of them into innerHTML means whatever markup they contain is rendered.
163
+ // Only the fixed wording is markup here; everything variable is text.
164
+ const manage = `${p.podBase.replace(/\/$/, '')}${d.doorPath}?dk-token=${encodeURIComponent(d.doorSecret)}`;
165
+ n.textContent = 'Your Fediverse account is ready. Manage it at ';
166
+ const a = say('a', p.podBase.replace(/\/$/, '') + d.doorPath); a.href = manage;
167
+ n.append(a, '.');
168
+ refreshKnown();
169
+ } else if (res && res.status === 200) {
170
+ n.textContent = 'Your Fediverse account is closed. Your pod and its data are untouched.';
171
+ refreshKnown();
172
+ } else {
173
+ n.textContent = (p.action === 'opt-in' ? 'opt-in' : 'opt-out') + ' failed: '
174
+ + (d.error || (res ? 'HTTP ' + res.status : 'no response'));
175
+ }
176
+ }
177
+
178
+ // Back from the identity provider: finish with the proven login.
72
179
  (async () => {
73
180
  if (!session) return;
74
181
  await session.handleRedirectFromLogin().catch(() => {});
@@ -84,24 +191,5 @@ $('run-leave').onclick = () => runStart('opt-out');
84
191
  method: 'POST', headers: { 'content-type': 'application/json' },
85
192
  body: JSON.stringify({ action: p.action, podBase: p.podBase }),
86
193
  }).catch(() => null);
87
- const d = res ? await res.json().catch(() => ({})) : {};
88
- if (res && res.status === 201 && d.doorSecret) {
89
- // Built as nodes, not as a string of HTML. Three of the pieces below come
90
- // back from the server and one comes from sessionStorage, and pasting any
91
- // of them into innerHTML means whatever markup they contain is rendered.
92
- // Only the fixed wording is markup here; everything variable is text.
93
- const say = (tag, text) => { const e = document.createElement(tag); e.textContent = text; return e; };
94
- n.textContent = 'Your identity runs here now. This is your door secret — ';
95
- n.append(say('b', 'save it now'));
96
- n.append(', it is shown only this once. It opens your admin pages at ');
97
- n.append(say('code', p.podBase.replace(/\/$/, '') + d.doorPath));
98
- n.append(':', say('pre', d.doorSecret));
99
- n.append('To check it works:', say('pre', d.command));
100
- n.append('Lost it? Opt in again — that mints a fresh one and retires this one.');
101
- } else if (res && res.status === 200) {
102
- n.textContent = 'Done — this server no longer runs that identity. Your pod and its data are untouched.';
103
- } else {
104
- n.textContent = (p.action === 'opt-in' ? 'opt-in' : 'opt-out') + ' failed: '
105
- + (d.error || (res ? 'HTTP ' + res.status : 'no response'));
106
- }
194
+ await showReply(res, p);
107
195
  })();
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <!-- The forum: more than one person talking. Icon "messages-square" from
3
+ Lucide (lucide.dev), ISC licence, © Lucide Contributors. -->
4
+ <title>Federated Solid Forum</title>
5
+ <rect width="32" height="32" rx="7" fill="#3b5bb5"/>
6
+ <g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
7
+ stroke-linecap="round" stroke-linejoin="round">
8
+ <path d="M16 10a2 2 0 0 1-2 2H6.828a2 2 0 0 0-1.414.586l-2.202 2.202A.71.71 0 0 1 2 14.286V4a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/>
9
+ <path d="M20 9a2 2 0 0 1 2 2v10.286a.71.71 0 0 1-1.212.502l-2.202-2.202A2 2 0 0 0 17.172 19H10a2 2 0 0 1-2-2v-1"/>
10
+ </g>
11
+ </svg>
@@ -0,0 +1,14 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <!-- The gateway: the door your mail comes through. Icon "door-open" from
3
+ Lucide (lucide.dev), ISC licence, © Lucide Contributors. -->
4
+ <title>FediPod gateway</title>
5
+ <rect width="32" height="32" rx="7" fill="#b4531a"/>
6
+ <g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
7
+ stroke-linecap="round" stroke-linejoin="round">
8
+ <path d="M10 21H2"/>
9
+ <path d="M10 3H7a2 2 0 00-2 2v16"/>
10
+ <path d="M14 12h.01"/>
11
+ <path d="M19 21V5a2 2 0 00-1.675-1.974l-6.163-1.013A1 1 0 0010 3v18a1 1 0 001.124.992z"/>
12
+ <path d="M22 21h-3"/>
13
+ </g>
14
+ </svg>
@@ -0,0 +1,11 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
2
+ <!-- Your own pod and your own posts. Icon "house" from Lucide (lucide.dev),
3
+ ISC licence, © Lucide Contributors. -->
4
+ <title>FediPod</title>
5
+ <rect width="32" height="32" rx="7" fill="#2f7d4f"/>
6
+ <g transform="translate(4 4)" fill="none" stroke="#ffffff" stroke-width="2"
7
+ stroke-linecap="round" stroke-linejoin="round">
8
+ <path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/>
9
+ <path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/>
10
+ </g>
11
+ </svg>
@@ -1,152 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <meta http-equiv="Content-Security-Policy" content="default-src 'none'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self' https://solidcommunity.net https://*.solidcommunity.net; form-action 'self' https://solidcommunity.net https://*.solidcommunity.net; base-uri 'none'">
7
- <title>FediPod</title>
8
- <style>
9
- :root { color-scheme: light dark; font-size: 112.5%; --heading: #1a4f8a; --sub: #666; --line: #bbb; --accent: #1a4f8a; }
10
- @media (prefers-color-scheme: dark) { :root { --heading: #7fb3e8; --sub: #aaa; --line: #555; --accent: #7fb3e8; } }
11
- body { font: 1rem/1.5 system-ui, sans-serif; margin: 0; }
12
- #page { max-width: 42rem; margin: 0 auto; padding: 1.75rem 1rem 4rem; box-sizing: border-box; }
13
- h1, h2, h3 { color: var(--heading); }
14
- h1 { font-size: 1.5rem; margin: 0 0 .5rem; }
15
- #brand { margin: 0 0 1.25rem; }
16
- h2 { font-size: 1.1rem; margin: 2rem 0 .5rem; }
17
- p { margin: .6rem 0; }
18
- code { background: rgba(120,120,120,.14); padding: .05em .35em; border-radius: 4px; }
19
- .sub { color: var(--sub); margin-top: 0; }
20
- .hint { color: var(--sub); font-size: .9rem; margin: .15rem 0 0; }
21
- fieldset { border: 1px solid var(--line); border-radius: .4rem; margin: 1rem 0; padding: .75rem 1rem 1rem; }
22
- legend { padding: 0 .3rem; font-weight: 600; }
23
- label { display: block; margin: .75rem 0 .2rem; }
24
- input[type=text], input[type=email], input[type=url], input[type=password], select {
25
- font: inherit; width: 100%; padding: .5rem; box-sizing: border-box;
26
- border: 1px solid #767676; border-radius: .3rem; background: Field; color: FieldText; }
27
- .choice { display: block; margin: .35rem 0; font-weight: normal; }
28
- .choice input { margin-right: .4rem; width: auto; }
29
- button { font: inherit; padding: .6rem 1.2rem; border-radius: .3rem; border: 1px solid #666;
30
- background: ButtonFace; color: ButtonText; cursor: pointer; }
31
- button.primary { font-weight: 600; }
32
- button:disabled { opacity: .5; cursor: default; }
33
- .row { display: flex; gap: .5rem; align-items: center; }
34
- .row input { flex: 1; }
35
- .row button { white-space: nowrap; }
36
- .address { font-size: 1.2rem; font-weight: 600; word-break: break-all; }
37
- .warn { border-left: .25rem solid #c60; padding-left: .75rem; }
38
- .err { border-left: .25rem solid #b00020; padding-left: .75rem; color: #b00020; }
39
- @media (prefers-color-scheme: dark) { .err { color: #ff8a8a; border-left-color: #ff8a8a; } }
40
- #form-error:empty, #signin-error:empty { display: none; }
41
- .steps { list-style: none; padding: 0; }
42
- .steps li { padding: .3rem 0; }
43
- a { color: var(--accent); }
44
- [hidden] { display: none !important; }
45
- </style>
46
- </head>
47
- <body>
48
- <main id="page">
49
-
50
- <!-- The marketing hero: shown on the landing, hidden once a form is up. -->
51
- <header id="hero">
52
- <h1>FediPod - join the Fediverse from a Solid pod.</h1>
53
- <p>Welcome to <b>fedipod.net</b>! By creating an account here, you can get a free Solid pod
54
- and Fediverse identity or link to your existing pod/identity. Your <code>fedipod.net</code>
55
- account provides you a portal to the Fediverse and filters unverified mail but does not tie
56
- you to anything. All of your data lives on your pod and your Fediverse identity is yours
57
- forever regardless of what happens to fedipod.net.</p>
58
- <p>There is nothing to install, once you've setup an account, just point any browser at
59
- <code>https://fedipod.net</code> and sign in.</p>
60
- </header>
61
-
62
- <!-- The short brand: shown only when a form is up, so the form stands alone. -->
63
- <h1 id="brand" hidden>FediPod</h1>
64
-
65
- <p id="loading">Loading…</p>
66
-
67
- <section id="landing" hidden>
68
- <h2>Already have an account?</h2>
69
- <p class="row">
70
- <input type="text" id="signin-address" autocapitalize="off" spellcheck="false" placeholder="@me@mypod">
71
- <button type="button" class="primary" id="signin">sign in</button>
72
- </p>
73
- <p class="err" id="signin-error" role="alert"></p>
74
- <h2>New user?</h2>
75
- <p><button type="button" class="primary" id="create">create an account</button></p>
76
- <p class="hint">For more information, see
77
- <a href="https://github.com/jeff-zucker/FediPod">github.com/jeff-zucker/FediPod</a></p>
78
- </section>
79
-
80
- <section id="pane-form" hidden>
81
- <form id="form">
82
-
83
- <!-- Screen 1: Your Solid Pod -->
84
- <div class="step" id="step-1">
85
- <fieldset>
86
- <legend>Your Solid Pod</legend>
87
-
88
- <label>Pod type</label>
89
- <label class="choice"><input type="radio" name="mode" value="existing"> An existing pod</label>
90
- <label class="choice"><input type="radio" name="mode" value="new" checked> A new pod</label>
91
-
92
- <label for="provider">Pod provider</label>
93
- <input type="url" id="provider" name="provider" autocomplete="url" placeholder="https://solidcommunity.net">
94
-
95
- <label for="podName">Pod username/subdomain</label>
96
- <input type="text" id="podName" name="podName" autocomplete="off" aria-describedby="podname-hint">
97
- <p class="hint" id="podname-hint">The subdomain of your pod: your pod address becomes
98
- https://YOUR-USERNAME.your-provider.</p>
99
-
100
- <label for="email">Pod email</label>
101
- <input type="email" id="email" name="email" autocomplete="email" placeholder="you@example.org">
102
-
103
- <label for="password">Pod password</label>
104
- <input type="password" id="password" name="password" autocomplete="current-password"
105
- aria-describedby="password-hint">
106
- <p class="hint" id="password-hint">The password is sent once in return for a credential stored
107
- in this browser. The password itself is never stored, and you can revoke the credential
108
- without changing it.</p>
109
- </fieldset>
110
- <p class="err" id="err-1" role="alert"></p>
111
- <p>
112
- <button type="button" id="cancel">Cancel</button>
113
- <button type="button" class="primary" id="to-2">Continue</button>
114
- </p>
115
- </div>
116
-
117
- <!-- Screen 2: Your Fediverse Identity -->
118
- <div class="step" id="step-2" hidden>
119
- <fieldset>
120
- <legend>Your Fediverse Identity</legend>
121
-
122
- <label for="handle">Fediverse handle</label>
123
- <input type="text" id="handle" name="handle" autocomplete="off"
124
- placeholder="the handle part of your address: @HANDLE@server" aria-describedby="handle-hint">
125
- <p class="hint" id="handle-hint">The name in your Fediverse address. This is permanent.
126
- Letters, digits, and hyphens only.</p>
127
-
128
- <label>Your Fediverse address</label>
129
- <p class="address" id="preview">@…@…</p>
130
- </fieldset>
131
- <p class="hint">The handle and the pod cannot be changed afterwards. Everything else — display
132
- name, bio, pictures — you set later in the client.</p>
133
- <p class="err" id="form-error" role="alert"></p>
134
- <p>
135
- <button type="button" id="back-1">Back</button>
136
- <button type="submit" class="primary" id="submit">Create Pod and Fediverse accounts</button>
137
- </p>
138
- </div>
139
-
140
- </form>
141
- </section>
142
-
143
- <section id="running" hidden>
144
- <h2>Setting up…</h2>
145
- <ul class="steps" id="steps"></ul>
146
- <p class="err" id="run-error" role="alert"></p>
147
- </section>
148
-
149
- </main>
150
- <script type="module" src="/boot.js"></script>
151
- </body>
152
- </html>
@@ -1,9 +0,0 @@
1
- /app/*
2
- Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data: blob:; media-src 'self' https: blob:; connect-src 'self' https:; font-src 'self' data:; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'
3
- X-Content-Type-Options: nosniff
4
- Referrer-Policy: same-origin
5
-
6
- /admin/*
7
- Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' https: data: blob:; connect-src 'self'; object-src 'none'; base-uri 'none'; frame-ancestors 'self'; form-action 'self'
8
- X-Content-Type-Options: nosniff
9
- Referrer-Policy: same-origin
@@ -1,22 +0,0 @@
1
- # gateway + front API → the function
2
- /api/handle /.netlify/functions/front 200
3
- /api/attach /.netlify/functions/front 200
4
- /api/relay /.netlify/functions/front 200
5
- /api/roster /.netlify/functions/front 200
6
- /api/revoke /.netlify/functions/front 200
7
- /api/agent /.netlify/functions/front 200
8
- /u/* /.netlify/functions/front 200
9
- /.well-known/* /.netlify/functions/front 200
10
- /@* /.netlify/functions/front 200
11
- /install /.netlify/functions/front 200
12
- /run /.netlify/functions/front 200
13
- /roster /.netlify/functions/front 200
14
- /solid-oidc-client.js /.netlify/functions/front 200
15
- # the in-browser app, served static (these win over the project catch-all)
16
- / /index.html 200
17
- /sw.js /sw.js 200
18
- /boot.js /boot.js 200
19
- /app /app/ 301
20
- /app/* /app/:splat 200
21
- /admin /admin/ 301
22
- /admin/* /admin/:splat 200