Commit graph naco-api/internal/activitypub
Author SHA1 Message Date
c96447e3e0
fix(activitypub): harden client, add outbox fallback and throttled GTS warming
Extract ActivityPub outbox walk into internal/activitypub/outbox.go with
webfinger/actor resolution, Create/Note filtering and IRI dereferencing.
Fix searchStatus returning wrong post, nil-account panic in SearchActors,
@local handle resolution, empty Author via noteToInternalPost, protocol-
relative URL handling, pagination loops, limit clamping (200) and cacheErr
masking. Add per-host token-bucket throttle (1/s, cross-host concurrency)
in throttle.go and background GTS warming via search?resolve for outbox-
fetched posts without following remotes. Align AGENTS.md.

Co-Authored-By: internal-model
2026-09-10 09:59:44 +00:00
4df3967cab
fix: harden ActivityPub client pagination and response bounds
- paginate GetLatestNPosts up to the requested limit (40/page, the
  Mastodon API cap) instead of relying on silent server clamping
- cap GetPostsInTimeframe at maxTimeframePages to stop runaway paging
- bound response bodies with a 1 MB LimitReader
- short-circuit on a canceled ctx between pages and guard limit <= 0
2026-09-09 23:17:43 +00:00
2fd4a4ec90
refactor: finish activitypub post migration from Text to Content
Drop the redundant Post.Text/internalPost.Text fields and complete the
rename in server converters and test fixtures so the tree builds again.

- types.go: remove Text from Post and internalPost; toPost only writes
  Author when the account acct is present
- posts_convert.go: apPostsPtrToItems / apPostsToAnalyticsItems read Content
- server tests: drop duplicate Text literal fields (values identical to Content)
2026-09-09 23:17:35 +00:00
3b443eff36
refactor: harden HTTP clients with timeouts, per-relay ctx, rate-limit handling 2026-09-08 01:11:13 +00:00
ee2829b818
refactor: pointer-ify profile/post slices across backends, converters, and tests 2026-09-08 01:08:28 +00:00
c8d1829172 test(clients): expand coverage for rate-limit, pagination and error paths
- nostr: variants for resolvePubkey/EventID, invalid ID/author checks, relay failure
- bluesky: add FeedGetPosts/getProfile/searchActors mocks, pagination and time-filtering with cursor
- twitter: add RateLimit retry (Reset/Retry-After), exhausted retries, lookup errors, context cancel
- activitypub: fix GetPostsInTimeframe to test 2-page pagination and start/end boundary
2026-09-03 17:00:28 +00:00
63f8756cc7 db: add user_style_posts table for post ID caching
- migration 004: create user_style_posts with user_id, platform, post_id, post_text, created_at
- queries: UpsertStylePosts, DeleteStylePosts (excludes Twitter), GetStylePosts, GetStylePostsByIDs, GetStylePostByID, PruneStylePosts
- activitypub: add ID field to Post struct
- server: fetchProfilePosts checks cache first, upserts on miss; buildStyleProfile deletes non-Twitter posts before rebuild; background pruner runs daily
2026-09-01 23:41:45 +02:00
4ac15ff6c2 test: cover getActor/searchActors clients and migrations
Runnable (HTTP-mocked) unit tests:
- activitypub: GetActor (accounts/lookup) plus id-lookup fallback, and SearchActors
  (accounts/search).
- twitter: GetActor (/users/by/username) and SearchActors (/users/search).
- nostr: SearchActors best-effort path (non-resolvable query returns empty, no network).
- store: extractUpSQL parsing helper.

Store integration test (TestStoreRoundTrip) is gated behind TEST_DATABASE_URL and skipped
when no Postgres+pgvector is available; it runs Migrate and exercises the Upsert/Get/
FindSimilarUsers round-trip against a real database.

Co-Authored-By: Claude (AI assistant) <noreply@anthropic.com>
2026-08-29 02:16:39 +02:00
1d97ca1164 feat: add getActor and searchActors tools across platforms
Introduce a shared actor.Profile type (internal/actor) so every platform client can return a
common shape without importing the server package (which would be an import cycle).

- Bluesky: GetActor (app.bsky.actor.getProfile) and SearchActors (app.bsky.actor.searchActors) via XRPC.
- ActivityPub: GetActor (accounts/lookup, falling back to accounts/{id}) and SearchActors
  (accounts/search).
- Nostr: GetActor subscribes to kind:0 metadata; SearchActors is best-effort (resolves a
  pubkey/npub query to a single profile; Nostr has no global actor search).
- Twitter: GetActor (/users/by/username) and SearchActors (/users/search).

server: register getActor and searchActors as payable tools; searchActors fans the query out
to all four platforms and merges results, skipping any platform that errors.

Schema fixes: document that getPost.collection is Bluesky-only, and that getFeed.uri is a feed
URI for Bluesky but an author handle for other platforms.

Co-Authored-By: Claude (AI assistant) <noreply@anthropic.com>
2026-08-29 02:14:29 +02:00
533ecede00 test: cover new cross-platform client methods
Add runnable (HTTP-mocked) unit tests for the client methods added when extending the
post tools to all platforms:

- twitter: GetPost (single-tweet object response + author expansion + public_metrics) and
  GetPostsInTimeframe (start_time/end_time query params + metrics)
- activitypub: GetPostsInTimeframe (paginated Mastodon statuses within a window)
- nostr: resolvePubkey/resolveEventID resolution helpers via real npub/note encoding

Also fix a latent bug in internal/nostr: resolvePubkey/resolveEventID wrapped the wrong
error variable (the nip19 error instead of the hex-decode error) when the 64-hex fallback
failed, producing misleading messages.

Co-Authored-By: Claude (AI assistant) <noreply@anthropic.com>
2026-08-29 01:44:39 +02:00
e31a4313f4 test: add unit tests for pure helpers and HTTP clients
Add runnable unit tests (no external services required):

- internal/utils: FormatVector/ParseEmbedding (all type branches + round-trip),
  AverageVector, TopWords (min-length + stopword filtering + ranking)
- internal/config: getEnvBool, splitComma, Load defaults/override
- internal/server: determinePlatform (did/npub/@-handle/64-hex/dotted) and
  platformFromString
- internal/twitter: mocked Twitter API v2 (empty-token error, fetch+parse,
  max_results clamping, non-200 error)
- internal/activitypub: mocked Mastodon API (constructor validation,
  GetLatestNPosts, GetPost, non-200 error)

Not covered (require live services / heavy mocking): store sqlc queries +
pgvector migrations (need Postgres), nostr client (needs a relay), ollama
client (wraps the ollama/go API over HTTP), and server orchestration
(requestStyleProfile, enrichCrossPlatform, fetchProfilePosts, getSimilarProfiles
need a DB + platform clients).

Co-Authored-By: Claude (AI assistant) <noreply@anthropic.com>
2026-08-29 01:33:42 +02:00
e5168e33f3 add: multi-platform getStyleProfile with slow, discovery-based prewarmer
- Nostr client (fiatjaf.com/nostr) fetching kind:1 notes from relays
- Twitter client using raw Twitter API v2 (no external X library), optional (no token = lazy error)
- getStyleProfile dispatches by platform; a profile is updated only when a request is
  made and the cached profile is older than a week (served from cache otherwise)
- shared requestStyleProfile path used by both the tool and the prewarmer
- StartPrewarm discovers interesting authors (from a feed URI or seed list) and
  pre-fetches at most one profile per minute; fresh profiles are never re-embedded
2026-08-29 01:07:47 +02:00
fed1a8d294 feat: add activitypub 2026-07-18 22:42:44 +00:00
5ca7f55ddf fix: log client ip 2025-12-21 01:53:10 +00:00