Changeset 0cea12b in Klonkt for src/routes/activitypub.js


Ignore:
Timestamp:
07/20/2026 08:19:20 PM (7 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
81b2e1e
Parents:
513ba82
git-author:
Robin <roboburr@…> (07/20/2026 08:18:21 PM)
git-committer:
Robin <roboburr@…> (07/20/2026 08:19:20 PM)
Message:

Feature: owner inbox read over C2S (GET, bearer-gated)

GET /ap/users/:slug/inbox with a bearer scoped to that site returns the
recent timeline (accounts the owner follows) as an OrderedCollection of
Create(Note) items with content, url, published, sensitive and summary
(CW). Anyone else gets 403: the inbox stays write-only for the public.
This is the missing read half for a connected app's unified feed
(Shaer HomeBase, bead shaer-n4h); same gate pattern as the owner
followers/following read.

Changed files:
src/routes/activitypub.js

  • GET /ap/users/:slug/inbox (owner only) mapping ap_timeline rows

New file:
test/c2s-inbox.test.js

  • data-path coverage for the fields the mapping relies on

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/activitypub.js

    r513ba82 r0cea12b  
    8484});
    8585
     86// ── Inbox read (owner only, AP C2S) ───────────────────────────────
     87// GET on the inbox is part of ActivityPub C2S: the account owner (a bearer
     88// scoped to this site) reads recent inbound posts (the timeline: accounts
     89// they follow) as Create(Note) items, so an app (Shaer) can build a unified
     90// feed. Anyone else gets 403; the inbox stays write-only for the public.
     91router.get('/ap/users/:slug/inbox', (req, res) => {
     92  const auth = OAuth.verifyBearer(req.headers.authorization);
     93  if (!auth || auth.site.slug !== req.params.slug) return res.status(403).end();
     94  const base = baseUrl(req);
     95  const items = AP.getTimeline(auth.site.slug, 60).map((t) => ({
     96    id: `${t.id}#create`,
     97    type: 'Create',
     98    actor: t.author_uri,
     99    published: t.published || t.created_at || undefined,
     100    object: {
     101      id: t.id,
     102      type: 'Note',
     103      attributedTo: t.author_uri,
     104      content: t.content,
     105      url: t.url || undefined,
     106      published: t.published || t.created_at || undefined,
     107      sensitive: !!t.nsfw,
     108      summary: t.cw || undefined,
     109    },
     110  }));
     111  AP.sendAP(res, {
     112    '@context': AP.AP_CONTEXT,
     113    id: `${base}/ap/users/${auth.site.slug}/inbox`,
     114    type: 'OrderedCollection',
     115    totalItems: items.length,
     116    orderedItems: items,
     117  });
     118});
     119
    86120// ── Followers (count-only public, full for the owner) ─────────────
    87121// A C2S bearer scoped to this site (the account owner) gets the real actor
Note: See TracChangeset for help on using the changeset viewer.