Changeset 1a2f206 in Klonkt
- Timestamp:
- 07/30/2026 11:17:05 PM (6 weeks ago)
- Branches:
- main
- Children:
- ef519a3
- Parents:
- 55eca8b
- Files:
-
- 5 edited
-
package-lock.json (modified) (20 diffs)
-
package.json (modified) (1 diff)
-
src/routes/activitypub.js (modified) (1 diff)
-
src/services/ActivityPubService.js (modified) (3 diffs)
-
test/c2s-compose.test.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
package-lock.json
r55eca8b r1a2f206 29 29 "node-webpmux": "^3.2.1", 30 30 "nodemailer": "^6.9.15", 31 "qrcode": "^1.5.4", 31 32 "sanitize-html": "^2.17.3", 32 33 "uuid": "^9.0.1", … … 540 541 "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 541 542 "license": "MIT" 543 }, 544 "node_modules/ansi-regex": { 545 "version": "5.0.1", 546 "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 547 "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 548 "license": "MIT", 549 "engines": { 550 "node": ">=8" 551 } 552 }, 553 "node_modules/ansi-styles": { 554 "version": "4.3.0", 555 "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 556 "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 557 "license": "MIT", 558 "dependencies": { 559 "color-convert": "^2.0.1" 560 }, 561 "engines": { 562 "node": ">=8" 563 }, 564 "funding": { 565 "url": "https://github.com/chalk/ansi-styles?sponsor=1" 566 } 542 567 }, 543 568 "node_modules/append-field": { … … 772 797 } 773 798 }, 799 "node_modules/camelcase": { 800 "version": "5.3.1", 801 "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 802 "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 803 "license": "MIT", 804 "engines": { 805 "node": ">=6" 806 } 807 }, 774 808 "node_modules/caseless": { 775 809 "version": "0.12.0", … … 783 817 "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", 784 818 "license": "ISC" 819 }, 820 "node_modules/cliui": { 821 "version": "6.0.0", 822 "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 823 "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 824 "license": "ISC", 825 "dependencies": { 826 "string-width": "^4.2.0", 827 "strip-ansi": "^6.0.0", 828 "wrap-ansi": "^6.2.0" 829 } 830 }, 831 "node_modules/color-convert": { 832 "version": "2.0.1", 833 "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 834 "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 835 "license": "MIT", 836 "dependencies": { 837 "color-name": "~1.1.4" 838 }, 839 "engines": { 840 "node": ">=7.0.0" 841 } 842 }, 843 "node_modules/color-name": { 844 "version": "1.1.4", 845 "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 846 "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 847 "license": "MIT" 785 848 }, 786 849 "node_modules/concat-stream": { … … 880 943 } 881 944 }, 945 "node_modules/decamelize": { 946 "version": "1.2.0", 947 "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 948 "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", 949 "license": "MIT", 950 "engines": { 951 "node": ">=0.10.0" 952 } 953 }, 882 954 "node_modules/decompress-response": { 883 955 "version": "6.0.0", … … 940 1012 "node": ">=8" 941 1013 } 1014 }, 1015 "node_modules/dijkstrajs": { 1016 "version": "1.0.3", 1017 "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", 1018 "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", 1019 "license": "MIT" 942 1020 }, 943 1021 "node_modules/dom-serializer": { … … 1063 1141 "node": ">=0.10.0" 1064 1142 } 1143 }, 1144 "node_modules/emoji-regex": { 1145 "version": "8.0.0", 1146 "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1147 "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1148 "license": "MIT" 1065 1149 }, 1066 1150 "node_modules/encodeurl": { … … 1317 1401 } 1318 1402 }, 1403 "node_modules/find-up": { 1404 "version": "4.1.0", 1405 "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1406 "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1407 "license": "MIT", 1408 "dependencies": { 1409 "locate-path": "^5.0.0", 1410 "path-exists": "^4.0.0" 1411 }, 1412 "engines": { 1413 "node": ">=8" 1414 } 1415 }, 1319 1416 "node_modules/fluent-ffmpeg": { 1320 1417 "version": "2.1.3", … … 1367 1464 "funding": { 1368 1465 "url": "https://github.com/sponsors/ljharb" 1466 } 1467 }, 1468 "node_modules/get-caller-file": { 1469 "version": "2.0.5", 1470 "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 1471 "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 1472 "license": "ISC", 1473 "engines": { 1474 "node": "6.* || 8.* || >= 10.*" 1369 1475 } 1370 1476 }, … … 1609 1715 } 1610 1716 }, 1717 "node_modules/is-fullwidth-code-point": { 1718 "version": "3.0.0", 1719 "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1720 "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1721 "license": "MIT", 1722 "engines": { 1723 "node": ">=8" 1724 } 1725 }, 1611 1726 "node_modules/is-plain-object": { 1612 1727 "version": "5.0.0", … … 1666 1781 "jwa": "^2.0.1", 1667 1782 "safe-buffer": "^5.0.1" 1783 } 1784 }, 1785 "node_modules/locate-path": { 1786 "version": "5.0.0", 1787 "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1788 "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1789 "license": "MIT", 1790 "dependencies": { 1791 "p-locate": "^4.1.0" 1792 }, 1793 "engines": { 1794 "node": ">=8" 1668 1795 } 1669 1796 }, … … 1942 2069 } 1943 2070 }, 2071 "node_modules/p-limit": { 2072 "version": "2.3.0", 2073 "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 2074 "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 2075 "license": "MIT", 2076 "dependencies": { 2077 "p-try": "^2.0.0" 2078 }, 2079 "engines": { 2080 "node": ">=6" 2081 }, 2082 "funding": { 2083 "url": "https://github.com/sponsors/sindresorhus" 2084 } 2085 }, 2086 "node_modules/p-locate": { 2087 "version": "4.1.0", 2088 "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 2089 "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 2090 "license": "MIT", 2091 "dependencies": { 2092 "p-limit": "^2.2.0" 2093 }, 2094 "engines": { 2095 "node": ">=8" 2096 } 2097 }, 2098 "node_modules/p-try": { 2099 "version": "2.2.0", 2100 "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 2101 "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 2102 "license": "MIT", 2103 "engines": { 2104 "node": ">=6" 2105 } 2106 }, 1944 2107 "node_modules/parse-cache-control": { 1945 2108 "version": "1.0.1", … … 1960 2123 "engines": { 1961 2124 "node": ">= 0.8" 2125 } 2126 }, 2127 "node_modules/path-exists": { 2128 "version": "4.0.0", 2129 "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 2130 "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 2131 "license": "MIT", 2132 "engines": { 2133 "node": ">=8" 1962 2134 } 1963 2135 }, … … 1973 2145 "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", 1974 2146 "license": "ISC" 2147 }, 2148 "node_modules/pngjs": { 2149 "version": "5.0.0", 2150 "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", 2151 "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", 2152 "license": "MIT", 2153 "engines": { 2154 "node": ">=10.13.0" 2155 } 1975 2156 }, 1976 2157 "node_modules/postcss": { … … 2085 2266 } 2086 2267 }, 2268 "node_modules/qrcode": { 2269 "version": "1.5.4", 2270 "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", 2271 "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", 2272 "license": "MIT", 2273 "dependencies": { 2274 "dijkstrajs": "^1.0.1", 2275 "pngjs": "^5.0.0", 2276 "yargs": "^15.3.1" 2277 }, 2278 "bin": { 2279 "qrcode": "bin/qrcode" 2280 }, 2281 "engines": { 2282 "node": ">=10.13.0" 2283 } 2284 }, 2087 2285 "node_modules/qs": { 2088 2286 "version": "6.15.1", … … 2167 2365 "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==", 2168 2366 "license": "Apache-2.0" 2367 }, 2368 "node_modules/require-directory": { 2369 "version": "2.1.1", 2370 "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 2371 "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", 2372 "license": "MIT", 2373 "engines": { 2374 "node": ">=0.10.0" 2375 } 2376 }, 2377 "node_modules/require-main-filename": { 2378 "version": "2.0.0", 2379 "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 2380 "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 2381 "license": "ISC" 2169 2382 }, 2170 2383 "node_modules/safe-buffer": { … … 2265 2478 } 2266 2479 }, 2480 "node_modules/set-blocking": { 2481 "version": "2.0.0", 2482 "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 2483 "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", 2484 "license": "ISC" 2485 }, 2267 2486 "node_modules/setprototypeof": { 2268 2487 "version": "1.2.0", … … 2423 2642 } 2424 2643 }, 2644 "node_modules/string-width": { 2645 "version": "4.2.3", 2646 "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2647 "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2648 "license": "MIT", 2649 "dependencies": { 2650 "emoji-regex": "^8.0.0", 2651 "is-fullwidth-code-point": "^3.0.0", 2652 "strip-ansi": "^6.0.1" 2653 }, 2654 "engines": { 2655 "node": ">=8" 2656 } 2657 }, 2658 "node_modules/strip-ansi": { 2659 "version": "6.0.1", 2660 "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2661 "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2662 "license": "MIT", 2663 "dependencies": { 2664 "ansi-regex": "^5.0.1" 2665 }, 2666 "engines": { 2667 "node": ">=8" 2668 } 2669 }, 2425 2670 "node_modules/strip-json-comments": { 2426 2671 "version": "2.0.1", … … 2658 2903 } 2659 2904 }, 2905 "node_modules/which-module": { 2906 "version": "2.0.1", 2907 "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", 2908 "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", 2909 "license": "ISC" 2910 }, 2911 "node_modules/wrap-ansi": { 2912 "version": "6.2.0", 2913 "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 2914 "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 2915 "license": "MIT", 2916 "dependencies": { 2917 "ansi-styles": "^4.0.0", 2918 "string-width": "^4.1.0", 2919 "strip-ansi": "^6.0.0" 2920 }, 2921 "engines": { 2922 "node": ">=8" 2923 } 2924 }, 2660 2925 "node_modules/wrappy": { 2661 2926 "version": "1.0.2", … … 2672 2937 "node": ">=0.4" 2673 2938 } 2939 }, 2940 "node_modules/y18n": { 2941 "version": "4.0.3", 2942 "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", 2943 "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", 2944 "license": "ISC" 2945 }, 2946 "node_modules/yargs": { 2947 "version": "15.4.1", 2948 "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", 2949 "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", 2950 "license": "MIT", 2951 "dependencies": { 2952 "cliui": "^6.0.0", 2953 "decamelize": "^1.2.0", 2954 "find-up": "^4.1.0", 2955 "get-caller-file": "^2.0.1", 2956 "require-directory": "^2.1.1", 2957 "require-main-filename": "^2.0.0", 2958 "set-blocking": "^2.0.0", 2959 "string-width": "^4.2.0", 2960 "which-module": "^2.0.0", 2961 "y18n": "^4.0.0", 2962 "yargs-parser": "^18.1.2" 2963 }, 2964 "engines": { 2965 "node": ">=8" 2966 } 2967 }, 2968 "node_modules/yargs-parser": { 2969 "version": "18.1.3", 2970 "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 2971 "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 2972 "license": "ISC", 2973 "dependencies": { 2974 "camelcase": "^5.0.0", 2975 "decamelize": "^1.2.0" 2976 }, 2977 "engines": { 2978 "node": ">=6" 2979 } 2674 2980 } 2675 2981 } -
package.json
r55eca8b r1a2f206 34 34 "node-webpmux": "^3.2.1", 35 35 "nodemailer": "^6.9.15", 36 "qrcode": "^1.5.4", 36 37 "sanitize-html": "^2.17.3", 37 38 "uuid": "^9.0.1", -
src/routes/activitypub.js
r55eca8b r1a2f206 121 121 } 122 122 AP.sendAP(res, ob, audience === 'friend' ? 'private, no-store' : undefined); 123 }); 124 125 // ── Follow-QR (Robins verzoek, 31-7) ────────────────────────────── 126 // A PNG QR of share:social/follow/AP/@slug@host: the ward shows it in 127 // Account, a friend scans the SCREEN with the ordinary camera app and their 128 // Shaer opens with the follow question. Public on purpose: it encodes only 129 // the public handle, and the app's plain image loaders carry no bearer. 130 router.get('/ap/users/:slug/follow-qr.png', async (req, res) => { 131 const site = db.prepare('SELECT slug FROM sites WHERE slug = ?').get(req.params.slug); 132 if (!site) return res.status(404).end(); 133 try { 134 const host = new URL(baseUrl(req)).host; 135 const { default: QRCode } = await import('qrcode'); 136 const png = await QRCode.toBuffer(`share:social/follow/AP/@${site.slug}@${host}`, { width: 600, margin: 1 }); 137 res.set('Content-Type', 'image/png'); 138 res.set('Cache-Control', 'public, max-age=86400'); 139 res.send(png); 140 } catch (e) { 141 console.warn('[AP] follow-qr failed:', e && e.message); 142 res.status(500).end(); 143 } 123 144 }); 124 145 -
src/services/ActivityPubService.js
r55eca8b r1a2f206 2383 2383 const actorUri = c2sIdOf(object); 2384 2384 if (!actorUri) return { status: 400, error: 'missing_object' }; 2385 await followActor(site, actorUri); 2385 // The error REACHES the app (Robins melding, 31-7): swallowing it 2386 // made a failed follow look exactly like a successful one. 2387 const r = await followActor(site, actorUri); 2388 if (r && r.error) return { status: 502, error: 'follow_failed', detail: r.error }; 2386 2389 return { status: 202, url: actorUri }; 2387 2390 } … … 3645 3648 else actorUrl = null; 3646 3649 if (!actorUrl) return { error: 'not_found' }; 3647 const actor = await fetchActor(actorUrl).catch(() => null); 3650 // SIGNED, as this actor: an authorized-fetch instance refuses an anonymous 3651 // GET of the actor doc, which made following from a boost silently fail 3652 // (Robins melding, 31-7). Signed, the other side sees who asks. 3653 const actor = await signedGetJson(site.slug, actorUrl); 3648 3654 if (!actor || !actor.id || !actor.inbox) return { error: 'unreachable' }; 3649 3655 const ai = actorInfo(actor, actor.id); … … 3660 3666 // Follow + feature in one step → backfill their recent posts into the Cirkel right away. 3661 3667 if (autoBoost) backfillFromOutbox(site.slug, actor.id).catch(() => {}); 3668 // A ward's guardians are TOLD about a new follow (Robins verzoek, 31-7): 3669 // a follow brings new content into the child's feed, and the village 3670 // should know the door opened. A direct note per guardian, best-effort; 3671 // FEP-633c 5.3 gates inbound follows, the outbound notice is Shaer policy 3672 // for now (bead: spec-vraag). 3673 try { 3674 const guardians = Guardianship.listGuardians(site.slug); 3675 if (guardians.length) { 3676 const meRef = actorId(base, site.slug); 3677 const esc = (t) => String(t).replace(/[<>&]/g, (c) => ({ '<': '<', '>': '>', '&': '&' }[c])); 3678 const label = esc(ai.name || ai.handle || actor.id); 3679 for (const g of guardians) { 3680 const note = { 3681 id: `${meRef}/follow-notice/${Date.now().toString(36)}${rid()}`, 3682 type: 'Note', attributedTo: meRef, to: [g.other_uri], 3683 tag: [{ type: 'Mention', href: g.other_uri }], 3684 content: `<p>👀 ${esc(site.title || site.slug)} is now following ${label}.</p>`, 3685 }; 3686 deliverToActor(site, g.other_uri, { id: `${note.id}#create`, type: 'Create', actor: meRef, to: [g.other_uri], object: note }) 3687 .catch(() => { /* retried by the queue */ }); 3688 } 3689 console.log('[AP] follow notice →', guardians.length, 'guardian(s) of', site.slug); 3690 } 3691 } catch { /* geen guardians is geen fout */ } 3662 3692 return { ok: true, name: ai.name, handle: ai.handle, actor: actor.id }; 3663 3693 } -
test/c2s-compose.test.js
r55eca8b r1a2f206 208 208 }); 209 209 210 test('a failed follow REACHES the app as an error, not a fake 202', async () => { 211 // Following from a boost silently failed (Robins melding, 31-7): the C2S 212 // ingest swallowed followActor's error. An unreachable actor must say so. 213 const r = await AP.ingestOutboxActivity(site, user, { 214 type: 'Follow', object: 'https://unresolvable.invalid/u/niemand', 215 }); 216 assert.equal(r.status, 502); 217 assert.equal(r.error, 'follow_failed'); 218 assert.equal(r.detail, 'unreachable'); 219 }); 220 210 221 test('selfAuthor: the byline for your own outbox notes', () => { 211 222 // The owner's app reads its own posts from the outbox, which carried no
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)