Skip to content

Harden BlueskyPublisher: link facets, conventions, NSID lexicon, tests - #94

Merged
paulocastellano merged 6 commits into
mainfrom
fix/bluesky-publisher-hardening
Jun 13, 2026
Merged

Harden BlueskyPublisher: link facets, conventions, NSID lexicon, tests#94
paulocastellano merged 6 commits into
mainfrom
fix/bluesky-publisher-hardening

Conversation

@paulocastellano

Copy link
Copy Markdown
Contributor

Follow-up to #93. Hardens BlueskyPublisher (and the sibling Bluesky services) — one real bug, convention cleanup, a shared NSID lexicon, and stronger tests.

Bug fix

  • Link facets swallowed trailing punctuation. The URL regex captured trailing sentence punctuation and an unmatched closing paren (see https://x.com).) into the link facet, so Bluesky rendered a malformed/over-long link. Now trimmed like the official atproto tokenizer.

Conventions / cleanup

  • Import Exception instead of inline \Exception.
  • Read the upload blob via data_get instead of direct array access.
  • Source the web-app host from a new config('trypost.platforms.bluesky.web_app') key instead of hardcoding bsky.app.
  • Remove the getUtf8ByteOffset no-op — PREG_OFFSET_CAPTURE with /u already returns byte offsets, so call sites use them directly.

BlueskyLexicon

  • Centralize the AT Protocol lexicon identifiers (NSIDs: createRecord, createSession, feed.post, facet types, etc.) into App\Services\Social\BlueskyLexicon. They were repeated as magic strings across BlueskyPublisher, BlueskyAnalytics, ConnectionVerifier and BlueskyController, where a typo fails silently at runtime as "Invalid request" (the same class of bug Fix: resolve Bluesky @mention handles to DIDs (mentions caused "Invalid post data") #93 fixed). A typo is now an undefined-constant error. Tests keep the literal NSIDs as the independent contract.

Tests

  • Add coverage for the URL trailing-punctuation trim and for byte-offset correctness after multibyte characters (emoji/accents).
  • Strengthen the image tests to actually assert an app.bsky.embed.images embed is attached and that six images upload exactly four (they previously only checked createRecord was sent).

Full suite green (1970 passed, 2 skipped).

Out of scope

  • Image alt text — the Media model has no alt field; needs a migration + UI (separate feature).

The URL regex captured trailing sentence punctuation and an unmatched closing
paren ("see https://x.com).") into the link facet, so Bluesky rendered the
punctuation as part of a malformed link. Trim it like the official atproto
tokenizer. Add tests for the trim and for byte-offset correctness after
multibyte characters (emoji/accents).
Import Exception instead of referencing it inline, read the blob via data_get,
source the web-app host from config (new bluesky.web_app key) instead of
hardcoding bsky.app, and drop the getUtf8ByteOffset no-op — the PREG /u offset
is already in bytes, so the call sites use it directly.
The image tests only checked that createRecord was sent — the faked empty
download meant no blob was ever attached, so they never verified the embed.
Drive a real (mocked) optimize + upload and assert the createRecord record
carries an app.bsky.embed.images embed, and that six images upload exactly four.
The Bluesky lexicon identifiers (createRecord, createSession, feed.post, facet
types, etc.) were repeated as magic strings across BlueskyPublisher,
BlueskyAnalytics, ConnectionVerifier and BlueskyController, where a typo fails
silently at runtime as "Invalid request". Define them once as named constants
so a typo is an undefined-constant error instead. Tests keep the literal NSIDs
as the independent contract.
Add a unit test asserting each BlueskyLexicon constant equals its AT Protocol
NSID — a wrong value (not just a typo'd name) would otherwise fail silently at
runtime. Add a test that a URL with a matching '(' keeps its trailing ')'
(Wikipedia-style), covering the previously-untested keep branch of the trim.
Add a test that a network error during handle resolution degrades the mention
to plain text instead of failing the post (exercises the resolveHandleToDid
try/catch), and a test asserting the post URL is built from the configured
web_app host (a revert to a hardcoded host would now fail).
@paulocastellano
paulocastellano merged commit 986e266 into main Jun 13, 2026
2 checks passed
@paulocastellano
paulocastellano deleted the fix/bluesky-publisher-hardening branch June 13, 2026 23:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant