v2 M5: AT Proto/Bluesky client, wired but inert until credentials exist
internal/atproto is a minimal client: Login (app password, never the
real account password) via com.atproto.server.createSession, Post via
com.atproto.repo.createRecord (app.bsky.feed.post), truncated to
Bluesky's 300-rune post limit.
A repo pair can now declare an optional bluesky block (handle +
app_password_file, same token-file convention as Forgejo). When set,
GitSyncer and PatchSyncer post a short note whenever they mirror a new
commit or open a patch/PR, alongside the existing activity_log entry.
Absent config is a true no-op everywhere (BlueskyPoster.Post is nil-safe)
— no account configured, no behavior change, verified live: deployed
with zero bluesky config present, service healthy, /social still
correctly shows "not configured" for every series.
Genuinely untestable further without a real account, as flagged in the
v2 plan from the start — the code is complete and defensive (a failed
Bluesky call never blocks or fails the sync loop), but live posting is
unverified until a dedicated Bluesky handle + app password exists to
test against.