Commit Graph

131 Commits

Author SHA1 Message Date
Sven
8b1b5d990a Add AP inbox diagnostics: surface signature errors and request logging
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m20s
- patch-ap-inbox-delivery-debug: two fixes for diagnosing missing inbound
  AP interactions (likes, boosts, replies not appearing in notifications)

  Fix A (federation-setup.js): change ["fedify","federation","inbox"] log
  category from lowestLevel "fatal" → "error" so HTTP Signature verification
  failures are now visible in server logs instead of being silently swallowed.
  The original "fatal" level was hiding real delivery rejections (401s) that
  cause remote servers to stop retrying.

  Fix B (federation-bridge.js): add a pre-signature-check console.info for
  every inbox POST when AP_DEBUG=1 or AP_LOG_LEVEL=debug. Confirms whether
  remote servers are reaching our inbox at all (nginx/routing check).

- memory/project_activitypub.md: document full inbound activity pipeline,
  _publicationUrl dependency, body buffering, and how to use new diagnostics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 16:32:06 +02:00
Sven
e791c06b79 feat: propagate Micropub deletes to ActivityPub and Bluesky
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m13s
When a post is deleted from the web backend (Micropub action=delete),
call each registered syndicator's delete() method so the post is also
removed from the Fediverse (AP Delete/Tombstone) and Bluesky
(com.atproto.repo.deleteRecord).

- patch-bluesky-syndicator-delete: adds Bluesky#deletePost(bskyUrl) to
  lib/bluesky.js and BlueskySyndicator#delete(url, syndication) to
  index.js; the bsky.app URL is resolved from the syndication array
  that postData.delete() preserves in _deletedProperties
- patch-micropub-delete-propagation: patches action.js case "delete"
  to iterate publication.syndicationTargets after postContent.delete()
  and fire syndicator.delete() fire-and-forget for any syndicator that
  exposes the method (errors logged, never break the 200 response)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:41:00 +02:00
Sven
63bc41ebb5 fix(activitypub): inbound replies/notifications broken — publicationUrl missing in inbox handlers
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m14s
collections._publicationUrl was never set, so every pubUrl guard in
handleCreate/handleAnnounce evaluated to undefined:
  - Reply notifications were never created (if pubUrl && ...) always false
  - Boost notifications for our content never created
  - Replies from non-followed accounts never stored in ap_timeline

Fix A: set collections._publicationUrl = publicationUrl before
registerInboxListeners() in federation-setup.js.

Fix B: in handleCreate, add an else-if branch that stores replies to
our own posts in ap_timeline even when the sender is not in ap_following,
so they appear in Mastodon client conversation/notification views.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:28:24 +02:00
Sven
12ee80f4a4 fix(activitypub): populate in_reply_to_id in Mastodon status serializer
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m11s
- status.js: in_reply_to_id was always null (both branches of ternary
  returned null — TODO left unfilled). Changed to item.inReplyToId || null.
- statuses.js POST handler: timeline insert now stores inReplyToId from
  the in_reply_to_id cursor the client already sent, so own replies are
  threaded correctly in Phanpy/Elk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 15:01:55 +02:00
Sven
71a8b60d96 fix(activitypub) delete request - Added broadcastDelete to mastodonPluginOptions
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m13s
2026-04-01 14:46:56 +02:00
Sven
c0f847c96f fix(activitypub) dedup: query ap_activities for an existing outbound Create/Announce/Update
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m18s
2026-04-01 14:38:12 +02:00
Sven
2211b1d6f7 fix: activitypun fav/boost
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m14s
2026-04-01 14:27:45 +02:00
Sven
f28552a5b2 fix: activitypub -> time confusion created / published times
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m17s
2026-04-01 14:17:42 +02:00
Sven
720487edb3 fix: activitypub/mastodon posting reenabled
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m19s
2026-04-01 13:51:28 +02:00
Sven
bc661282c7 fix: del gitea dispatch
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 3m17s
2026-03-31 18:24:49 +02:00
Sven
5342cd1ff0 fix: skip workflow_dispatch for delete — Gitea DELETE commits trigger on:push
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m11s
Gitea Contents API DELETE commits fire on:push CI; POST/PUT do not.
delete was triggering both on:push and workflow_dispatch → 2 CI runs.
Now dispatch is skipped for delete; on:push handles the rebuild.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 17:19:34 +02:00
Sven
40ec8dbce3 fix: add Content-Type: application/json to store-github requests
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m15s
GitHub API infers JSON without Content-Type; Gitea requires it explicitly.
Without the header, Gitea cannot parse the POST/PUT body and returns 422
Unprocessable Entity on all content write operations.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 17:09:15 +02:00
Sven
302316c8d0 fix: use POST for file create in Gitea Contents API
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m14s
Gitea's Contents API differs from GitHub's:
  POST /contents/{path} = create new file (no SHA)
  PUT  /contents/{path} = update existing file (SHA required)

store-github used PUT for createFile() because GitHub accepts PUT for
both — Gitea's PUT without SHA returns 422. Also updates the
update-fallback patch to bail to createFile() instead of falling through
to PUT-without-SHA when the file doesn't exist in the store.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:58:14 +02:00
Sven
53102a03b0 fix: fall back to create when updateFile gets 404 from Gitea
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m15s
Posts that exist in MongoDB but not in Gitea (e.g. due to a previous
failed write) caused HTTP 500 on re-publish: updateFile() tried to read
the file's SHA, got 404, and threw instead of creating. Now detects
Not Found and falls through to a create-style PUT (no sha field).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:37:53 +02:00
Sven
263e6e081a feat: dispatch Gitea workflow_dispatch after each Micropub action
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m15s
Gitea Contents API commits don't trigger on:push CI workflows.
Patches action.js to fire a workflow_dispatch to giersig.eu/indiekit-blog
after every create/update/delete/undelete so the Eleventy build runs
immediately after a post is published.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:24:39 +02:00
Sven
0bac69090d fix: rewrite gitea.giersig.eu to internal IP before npm install
All checks were successful
Deploy Indiekit Server / deploy (push) Successful in 1m15s
npm fetches git deps before node_modules exist, so git URL rewriting
must happen in preinstall. Detects jail env via INDIEKIT_BIND_HOST /
INTERNAL_FETCH_URL — no-ops on local dev.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 15:09:14 +02:00
Sven
2d5b713b7d chore: point svemagie fork deps and docs at Gitea
Some checks failed
Deploy Indiekit Server / deploy (push) Failing after 7s
- Switch 4 svemagie fork deps from github: shorthand to git+https://gitea.giersig.eu/svemagie/...
- Add patch-store-github-error-message.mjs to replace hardcoded github.com token URL with gitea.giersig.eu
- Update CLAUDE.md and README.md fork dependency docs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 15:05:49 +02:00
Sven
97d99976ea fix(ap): fix reply threading — pre-check AP syndication and resolve in_reply_to_id immediately
Two bugs caused replies-to-replies to be posted as 'note' type without
ActivityPub federation:

1. patch-ap-compose-default-checked: The AP reader compose form had
   defaultChecked hardcoded to '@rick@rmendes.net' (original dev's handle),
   so the AP syndication checkbox was never pre-checked. Fixed to use
   target.checked from the Micropub q=config response, which already
   carries checked: true for the AP syndicator.

2. patch-ap-mastodon-reply-threading: POST /api/v1/statuses deferred
   ap_timeline insertion until the Eleventy build webhook fired (30–120 s).
   If the user replied to their own new post before the build finished,
   findTimelineItemById returned null → inReplyTo = null → no in-reply-to
   in JF2 → post-type-discovery returned 'note' → reply saved at /notes/
   and sent without inReplyTo in the AP activity, breaking thread display
   on remote servers. Fixed by eagerly inserting the provisional timeline
   item immediately after postContent.create() ($setOnInsert — idempotent;
   syndicator upsert later is a no-op).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 08:12:43 +02:00
Sven
b4fc7ffb4f fix(bluesky): guard uploadMedia() against non-image HTTP responses
uploadMedia() had no content-type check, so an HTML login-redirect response
from an auth-protected internal endpoint was uploaded to Bluesky as a blob
with encoding "text/html". uploadBlob() accepts it, but record validation
rejects the post with 'Expected "image/*" (got "text/html")'.

The patch mirrors the guard already present in uploadImageFromUrl() and also
wraps per-photo uploads in try/catch so one bad photo doesn't abort the
entire syndication — other photos and the post text are still published.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 09:53:46 +02:00
Sven
4aa1554f3a fix(ap): patch federation-bridge to use publication URL as Fedify base URL
Without nginx forwarding Host/X-Forwarded-Proto headers, fromExpressRequest()
builds a wrong URL (e.g. http://127.0.0.1:3000/...) that Fedify doesn't
recognise as its own base URL — so it calls next() and requests fall through
to auth middleware, returning 302 to the login page. This breaks webfinger,
actor lookups, and AP inbox delivery.

The patch overrides the URL construction in createFedifyMiddleware() and
fromExpressRequest() to use the configured publicationUrl as the base,
bypassing the dependency on proxy headers entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 09:51:00 +02:00
Claude
7c404a19ed fix(ap): add og-image and webfinger patches dropped during conflict resolution
The Gitea conflict resolution kept main's prom-client/metrics-shim/microsub
changes but dropped our two new AP patch registrations. Re-add them to both
postinstall and serve.

https://claude.ai/code/session_0124D41vdLYE3DkJxhPqYthX
2026-03-28 18:35:29 +00:00
Sven
c9084f0586 feat: add Prometheus metrics shim for Indiekit process monitoring
Preloads metrics-shim.cjs via `node --require` into the Indiekit process
so heap, GC, event loop lag, CPU and handle metrics are exposed at
:9209/metrics for Prometheus scraping. Uses prom-client collectDefaultMetrics.

- Add metrics-shim.cjs (prom-client HTTP server, port 9209)
- Add prom-client ^15.1.3 to dependencies
- Wire --require ./metrics-shim.cjs into start.example.sh and npm serve script
- Grafana: NodeJS Application Dashboard (11159) at console.giersig.eu

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 16:06:21 +01:00
Sven
0cc5187990 fix(media-browser): fix mixed-content error causing 'Browse media' to fail
`getEndpointUrls()` resolved relative endpoint paths (e.g. `/media`) using
`getUrl(request)`, which returns `http://` because Express sees HTTP from nginx
without trust proxy. This produced `http://blog.giersig.eu/media` as the
endpoint attribute in the file-input component, causing Safari to block the
fetch as mixed content ('Load failed').

Fix: prefer `application.url` (the configured HTTPS base URL) over
`getUrl(request)` when resolving relative endpoint paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 10:29:02 +01:00
Sven
02f7db46e1 fix(media): fix image upload size limit and session token bug
- nginx: add client_max_body_size 20M to blog vhost (default 1MB was
  silently killing uploads, returning 413 as a JSON parse error in UI)
- patch: fix session.token → session.access_token in micropub action
  controller; caused Bearer undefined on internal /media fetch, giving
  500s for Micropub clients that upload files directly (OwnYourSwarm)
- npmrc: add sharp_from_source=true to survive future npm install on
  FreeBSD without breaking sharp's native bindings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 10:13:30 +01:00
Sven
18a946c9ea chore(patches): remove 10 obsolete AP patches now baked into fork
All of the following are now native in svemagie/indiekit-endpoint-activitypub:
- patch-ap-url-lookup-api (AP URL lookup endpoint)
- patch-ap-allow-private-address (allowPrivateAddress in federation-setup)
- patch-ap-like-note-dispatcher (fake-Note revert)
- patch-ap-like-activity-id (canonical Like activity id URI)
- patch-ap-like-activity-dispatcher (Like setObjectDispatcher)
- patch-ap-url-lookup-api-like (likeOf URL in /api/ap-url)
- patch-ap-remove-federation-diag (inbox diagnostic log removed)
- patch-ap-og-image (orphan, not in package.json)
- patch-ap-normalize-nested-tags (orphan, no-op)
- patch-ap-object-url-trailing-slash (orphan, no-op)

patch-ap-skip-draft-syndication kept — draft guard in syndicate() not yet in fork.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:21:26 +01:00
Sven
81abaee160 chore(patches): remove patch-ap-repost-commentary (baked into fork)
Repost commentary changes are now native in svemagie/indiekit-endpoint-activitypub.
Patch is no longer needed and was causing a duplicate repost block on every deploy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 20:16:22 +01:00
Sven
599312ba2f fix: bookmark main version 2026-03-22 16:27:44 +01:00
Sven
2a674c8eea feat(draft): prevent draft posts from being syndicated or federated
Add two new patches:
- patch-ap-skip-draft-syndication: guards the AP syndicator's syndicate()
  method against draft posts (mirrors existing unlisted visibility check)
- patch-microsub-compose-draft-guard: forwards post-status from microsub
  compose to Micropub and suppresses mp-syndicate-to targets for drafts

The syndicate endpoint DB queries already filter post-status != draft
(patch-federation-unlisted-guards). These patches add defence in depth
at the AP syndicator and at the microsub compose submission layer.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 11:10:23 +01:00
Sven
2548825793 chore: silence github contribution log 2026-03-21 17:31:01 +01:00
Sven
109d39dd25 fix(activitypub): remove federation-diag inbox logging
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 15:47:23 +01:00
Sven
99d2e38066 fix(activitypub): serve AP-likes with canonical id and proper Like dispatcher
Replace the semantically incorrect fake-Note approach with strict AP protocol compliance:

- patch-ap-like-note-dispatcher: rewritten to revert the fake-Note block
- patch-ap-like-activity-id: adds canonical id URI to Like activities (AP §6.2.1)
- patch-ap-like-activity-dispatcher: registers setObjectDispatcher(Like, ...) so
  /activitypub/activities/like/{id} is dereferenceable (AP §3.1)
- patch-ap-url-lookup-api-like: /api/ap-url now returns the likeOf URL for AP-likes
  so the "Also on: Fediverse" widget's authorize_interaction flow opens the
  original Mastodon post on the remote instance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 08:58:15 +01:00
Sven
34d5fde54d fix(syndicate): normalize syndication property to array before dedup check
Micropub's replaceEntries() stores single-value arrays as plain strings
(JF2 normalization). Spreading a string into [...str] gives individual
characters, so hasSyndicationUrl() never matches existing syndication URLs
and alreadySyndicated is always false — causing re-syndication on every
webhook trigger.

Fix: use [].concat() which safely handles both string and array values.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 07:49:18 +01:00
Sven
fe0f347e49 chore(ai): remove custom AI patches superseded by upstream endpoint-posts@beta.44
- Remove patch-preset-eleventy-ai-frontmatter: upstream now writes AI
  frontmatter natively using hyphenated keys (ai-text-level etc.)
- Remove patch-endpoint-posts-ai-cleanup: upstream beta.44 natively
  removes empty ai-text-level/ai-code-level/ai-tools/ai-description fields
- Remove patch-endpoint-posts-ai-fields: upstream beta.44 has AI form UI
  inline in post-form.njk; our separate templates would have duplicated fields
- Remove patch-micropub-ai-block-resync: one-time stale-block migration,
  no longer relevant
- Remove patch-endpoint-posts-prefill-url: upstream beta.44 has native
  prefill from query params; our patch would have conflicted
- Remove patch-endpoint-posts-search-tags: upstream beta.44 has native
  search/filter/sort UI; patch already detected this and was a no-op
- Bump @rmdes/indiekit-endpoint-posts beta.25→beta.44,
  override beta.41→beta.44
- Update indiekit.config.mjs: remove camelCase ai field names from
  all postTypes.fields (ai-* fields now rendered inline by upstream)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 14:37:04 +01:00
Sven
b53afe2ed3 fix(ap): include commentary in repost ActivityPub activities
Reposts with a body (commentary) were silently broken in two ways:

1. jf2ToAS2Activity() always emitted a bare Announce pointing at the
   external URL (e.g. fromjason.xyz). That URL doesn't serve AP JSON,
   so Mastodon couldn't fetch the object and dropped the activity from
   followers' timelines — the post only appeared when explicitly searched.

2. jf2ToActivityStreams() (content negotiation / search) hard-coded the
   Note content to just '🔁 <url>', completely ignoring properties.content.

Fix via patch-ap-repost-commentary.mjs (4 targeted replacements):
- jf2ToAS2Activity(): skip the Announce early-return when commentary is
  present and fall through to the existing Create(Note) path instead.
  Pure reposts (no body) keep the Announce behaviour unchanged.
- jf2ToAS2Activity() content block: add a repost branch that formats
  the Note as '<commentary><br><br>🔁 <url>' (mirrors bookmark/like).
- jf2ToActivityStreams(): extract commentary and prepend it to the Note
  content when present.

Patch registered in both postinstall and serve chains.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 12:02:16 +01:00
svemagie
c6b0e7025a fix: patch webmention-sender syntax error (h-entry double quote)
Adds patch-webmention-sender-hentry-syntax.mjs to fix a typo in
@rmdes/indiekit-endpoint-webmention-sender@1.0.8 that prevents the
module from loading:

  _html.includes("h-entry"")  →  _html.includes("h-entry")

The extra closing quote causes a SyntaxError at startup, which means
the webmention sender never runs and the background sync never starts.
Patch runs before the other webmention-sender patches in both
postinstall and serve so the file is valid JS before further transforms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:33:37 +01:00
Sven
e7bc37f282 chore: merge upstream AP fork v2.13–v2.15.4, remove 5 obsolete patches
Upstream features merged into svemagie/indiekit-endpoint-activitypub:
- v2.13.0: FEP-8fcf/fe34, custom emoji, manual follow approval
- v2.14.0: server blocking, Redis caching, key refresh, async inbox
- v2.15.0-4: outbox failure handling, reply forwarding, CW property,
  soft-delete filtering, as:Endpoints stripping

Patches removed (now baked into fork):
- patch-ap-object-url-trailing-slash
- patch-ap-normalize-nested-tags
- patch-ap-like-announce-addressing
- patch-inbox-skip-view-activity-parse
- patch-inbox-ignore-view-activity

Patches updated:
- patch-ap-allow-private-address: match v2.15 comment style

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 00:49:13 +01:00
Sven
bee8df214d fix: add cc:followers addressing to AP Like/Announce activities
Like and Announce activities were missing the followers collection in
their to/cc addressing. Mastodon shared inboxes silently drop activities
without cc:followers, so likes and reposts were delivered but never
appeared on remote instances.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 00:11:48 +01:00
Sven
f7e8eba46a feat: integrate YouTube likes sync via forked endpoint
Switch @rmdes/indiekit-endpoint-youtube to forked repo with OAuth 2.0
liked-videos sync. Add OAuth client config and likes sync settings.
Also document outgoing webmentions architecture in README.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 21:05:15 +01:00
Sven
1ad3bae3fc fix(patches): restore lost AP patches and fix broken patch chain
The signatureTimeWindow patch was deleted in e52e98c5c (assumed fixed
in fork), but the lockfile still pins the fork to v2.10.1 which lacks
it. This broke the patch-ap-allow-private-address patch chain: it
expected signatureTimeWindow in its OLD_SNIPPET, never matched, and
silently skipped — leaving the server without both signatureTimeWindow
AND allowPrivateAddress. Without allowPrivateAddress, Fedify's SSRF
guard blocks own-site URL resolution (blog.giersig.eu → 10.100.0.10),
breaking federation delivery.

- Fix patch-ap-allow-private-address to handle fresh v2.10.1 (adds
  both signatureTimeWindow and allowPrivateAddress in one step)
- Restore patch-ap-object-url-trailing-slash (also lost in e52e98c5c)
- Add both patches to postinstall and serve scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 19:18:40 +01:00
Sven
af683d8bb4 chore(patches): restore webmention-sender-retry patch and add to postinstall
Retry behavior is already covered by the livefetch patch, but keeping
this patch ensures the skip-on-failure guard applies even if livefetch
is removed or the upstream code changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 11:57:52 +01:00
Sven
c9c958e9f5 chore: point blogroll dependency to main branch
The bookmark-import branch has been merged to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:38:34 +01:00
Sven
2bfaa27702 fix(webmention-sender): show 'no external links' message for empty detail rows
When a post was processed but had no discoverable external links, the
expanded detail row rendered completely blank — result.details was
truthy ({}) so the 'noDetails' fallback never fired, but all three
arrays were empty so no tables rendered either.

Adds a patch script for the template that shows "No external links
discovered in this post." in that case, and wires it into both
postinstall and serve scripts.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 08:33:29 +01:00
Sven
42db9d85b6 fix(patches): rewrite Bluesky syndicator fetch URLs to localhost for jailed setup
uploadMedia, uploadImageFromUrl, and fetchOpenGraphData all fetch from
the blog's public URL which is unreachable behind the nginx jail. Rewrite
own-domain URLs to http://localhost:PORT, same as micropub-fetch-internal-url.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:19:24 +01:00
Sven
3beac515cd feat: add indiekit-endpoint-readlater 2026-03-17 12:26:40 +01:00
Sven
d501d70e1d fix(patches): restore livefetch patch so webmentions use live page HTML
The webmention sender was using stored post content (just the body text)
instead of the live page, missing template-rendered links like
u-in-reply-to, u-like-of, u-bookmark-of. This caused reply/like/bookmark
posts to be marked as sent with 0 webmentions. Bump reset-stale migration
to v4 so affected posts are retried.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 09:56:35 +01:00
Sven
733c00b1b3 fix(patches): rewrite micropub self-fetch to localhost for jailed setup
Node can't reach its own public HTTPS URL (ECONNREFUSED 127.0.0.1:443)
because port 443 only exists on the nginx jail. Rewrite self-referential
fetch URLs to http://localhost:3000 in endpoint-posts, endpoint-syndicate,
and endpoint-share.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 20:24:46 +01:00
Sven
24a9fb8f6b fix(patches): restore PeerTube View patches and add fetch diagnostic
Re-add PeerTube View activity patches that were prematurely removed in
e52e98c5c — the upstream fork doesn't reliably include these fixes on
all server deployments, causing noisy "Unsupported activity type" errors.

Also add fetch diagnostic patch to surface the real cause of
"TypeError: fetch failed" when posting articles via the form controller.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 20:14:26 +01:00
Sven
117aa2f577 fix(patches): normalize nested tags before syndicating to fediverse
Tags like `on/art/music` are reduced to their last segment (`#music`)
in both buildPlainTags and buildFedifyTags so ActivityPub hashtags are
valid on Mastodon and other platforms.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 13:01:36 +01:00
Sven
e52e98c5c5 chore(patches): remove patches now fixed in forks
Fixes implemented upstream in svemagie/indiekit-endpoint-activitypub
and svemagie/indiekit-endpoint-microsub; postinstall patches no longer
needed:

- patch-microsub-feed-discovery (HTML <link> discovery in fetcher.js)
- patch-inbox-skip-view-activity-parse (PeerTube View buffering in federation-bridge.js)
- patch-ap-inbox-raw-body-digest (raw body preservation for HTTP Signature Digest)
- patch-ap-object-url-trailing-slash (trailing slash $in fix in federation-setup.js)
- patch-ap-signature-time-window (12h signatureTimeWindow in federation-setup.js)
- patch-inbox-ignore-view-activity (View no-op handler in inbox-listeners.js)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 12:19:18 +01:00
Sven
dac2411a08 test: delete patch-microsub-reader-ap-dispatch 2026-03-16 11:47:06 +01:00