Back to blog

Dev Diary #6

Refactored cast publishing from Neynar signers to direct Hub submission and wired full Farcaster integration into LifeOS

April 13, 2026

Dev Diary #6

I'm deep in a two-day refactor of cast publishing, and there's a structural problem I'm sitting with. The cast module started as a thin wrapper around Neynar signers, but I've now ripped that out entirely and switched to direct Hub submission with an encrypted private key stored in the database. The issue: I'm storing encryption keys in env config (FARCASTER_ENCRYPTION_KEY), but the actual decryption happens at publish time in cast/src/publish, and if that service dies mid-flight, I have no retry visibility. I added a cast/src/retry module to handle failed publishes by querying the DB for casts with status = 'failed', but the Drizzle query arg order was wrong on first pass—I had the where clause conditions backwards, which meant retry was silently skipping everything.

The bigger picture is that I've wired up a full Farcaster integration layer into life.os, my personal dashboard. Over these two days I added the farcaster module with history sync, style learning, and friend engagement scoring. Then I built cast as a generic publishing service that both farcaster (for auto-generated highlight casts) and dev-blog (for posting entries) can call. I also added a signer registration script that prompts for the DB URL and encryption key, because the original approach of pre-registering signers via Neynar's API was fragile.

In parallel, I'm shipping dashboards. My Grafana dashboard now has 27 dashboards—16 dedicated to Life-OS services. I added cast, farcaster, and dev-blog dashboards to track latency, error rates, and cast volume. That required wiring up metric names across all three services to match what Prometheus scrapes.

The rough edge: the farcaster channel resolution. When publishing a cast to a channel, I need to fetch the channel's parent_url from Neynar's API first, but that adds latency and a dependency. Right now I'm just calling Neynar inline during publish, but if that API times out, the entire cast fails. I need to pre-fetch and cache channel metadata, but I haven't done that yet.

Next is stabilizing the two-phase clan XP tracking I added to rs3. The first sweep fetches clan roster, the second sweep fetches individual member XP gains, rate-limited to 1 per second. But I'm not sure if the second sweep should run on the same tick or defer to the next cycle.

Home
About
Resume
Projects
Blog
Press
Search