Work log: Authexis — March 3, 2026
What shipped today
Big day across three fronts: the Apple app’s three-column navigation finally works properly, the Zapier-to-social-queue pipeline is live, and the social post data model was cleaned up to keep fields separate.
Apple app three-column navigation. The iPad/Mac NavigationSplitView had a persistent bug where clicking items in the sidebar’s list views wouldn’t populate the detail column. After multiple failed approaches (Button+state, NavigationLink with and without NavigationStack), the fix landed using SwiftUI’s List(selection:) pattern. Every list view (Articles, Feeds, Ideas, Briefings, Content) now accepts an optional selection: Binding<String?>? parameter — when present (iPad/Mac), rows use .tag() for selection-driven navigation; when nil (iPhone), they use NavigationLink. Tag/badge styling was also unified from Capsule to RoundedRectangle across 15+ files. This closes the entire v1-apple milestone and most of v2-apple’s navigation issues.
Zapier social queue integration. Started as an ambitious auto-generation pipeline (Zapier detects blog post → Authexis writes teasers → auto-approves → schedules). After exploring the full content pipeline approach and building parts of it, Paul correctly called out the complexity. The pivot: Authexis is “just a scheduler” — Zapier handles content creation, then pushes finished posts via POST /api/v2/social-posts. The endpoint accepts content, platform, source_url, and hashtags as separate fields, auto-queues with the next position, and auto-schedules into the next available posting slot. A race condition where rapid submissions got the same slot was also fixed with a post-insert collision check.
Social post field separation (#748). Initially the API concatenated source_url and hashtags into the content field, but this made character budgeting fragile for the caller (especially on Bluesky’s 300-char limit). Reversed that: fields are stored separately, and the engine publisher assembles the final text per platform at publish time — skipping hashtags for Bluesky where they’re not conventional. The queue UI now displays source_url and hashtags below the content and counts the assembled length for character limits.
Form UX for contents/new. When creating social posts from existing content (/contents/new?from=<id>&type=social_post), the form now properly pre-fills the title (no “Re:” prefix), shows a summary banner, uses “Guidance” as the label, hides irrelevant SEO keywords, and pre-populates the source URL.
RLS security fix. Supabase linter flagged 5 tables (workspace_actions, system_messages, tip_views, podcast_episodes, changelogs) exposed to PostgREST without Row Level Security. Enabled RLS on all five with appropriate policies: workspace-scoped access for data tables, authenticated-read for global tables (changelogs, system messages). Service role is unaffected.
Completed
- #730 — App icon and accent color for universal Apple app
- #735 — macOS: set default window size
- #736 — Fix nested NavigationSplitView (detail pane broken)
- #737 — Remove Scans from sidebar
- #738 — Rename sidebar Bookmarks to Articles
- #745 — Zapier social post endpoint and pipeline
- #746 — Auto-generate and queue social teasers (abandoned approach, closed)
- #747 — contents/new form UX for social posts
- #748 — Social-posts API: store source_url and hashtags separately
Release progress
- v1-apple: 54/54 closed — ready to close
- v1: 296/296 closed — ready to close
- v1-marketing: 8/8 closed — ready to close
- v2: 12/12 closed — ready to close
- v1.5: 3/4 closed — 1 remaining (#701 marketing email system)
- v2-apple: 4/9 closed — 5 remaining (Preferences, Integrations, Calendar, Alternative layouts, Dashboard redesign)
Carry-over
hashtagscolumn migration was pushed viasupabase db pushbut verify the column exists if posts failsettings-client.tsxhas a stale trailing newline diff — harmless, clean up whenever- Engine changes (social_publish.py) need Railway deployment to take effect
Risks
- The slot collision fix (insert-then-check) is eventually consistent, not transactional. Under extreme concurrency it could still collide, but for Zapier’s sequential webhook calls it’s solid.
- The supabase migration history may be slightly out of sync — the original migration was applied/reverted manually before being rewritten to just the ALTER TABLE.
Flags and watch-outs
- Four milestones are fully closed and should be formally closed: v1-apple, v1, v1-marketing, v2
- The social_post content type config in the database is in its original state (no hashtags/source_url in pipeline stages). The content pipeline is unchanged — only the social_posts queue table and publisher were updated.
- Zapier integration uses the
ax_k_e036234...API key named “Zapier” - Engine deploy needed for the publisher to assemble source_url/hashtags at publish time
Next session
- Deploy engine to Railway so the publisher assembles source_url/hashtags per platform
- Close completed milestones: v1-apple, v1, v1-marketing, v2
- Test full Zapier → social queue → publish flow end-to-end
- v2-apple: pick up #739 (Preferences page) as the next Apple app issue
- v1.5: evaluate #701 (marketing email system) — prep or close
Why customer tools are organized wrong
This article reveals a fundamental flaw in how customer support tools are designed—organizing by interaction type instead of by customer—and explains why this fragmentation wastes time and obscures the full picture you need to help users effectively.
Infrastructure shapes thought
The tools you build determine what kinds of thinking become possible. On infrastructure, friction, and building deliberately for thought rather than just throughput.
Server-side dashboard architecture: Why moving data fetching off the browser changes everything
How choosing server-side rendering solved security, CORS, and credential management problems I didn't know I had.
The work of being available now
A book on AI, judgment, and staying human at work.
The practice of work in progress
Practical essays on how work actually gets done.
Your process was built for a different speed
When work changes velocity, governance systems don't just fall behind. They become theater. And theater is worse than nothing—it gives you the feeling of control without any of the substance.
The difference between shipping and finishing
Shipping is mechanical. Finishing is a judgment call. And most organizations have quietly made it impossible to tell the difference.
Nothing is finished until you say it is
Continuous delivery removed the endings from work. That felt like progress. But without formal completion, you lose the ability to say what you actually accomplished — and more importantly, what you're done thinking about.