Skip to main content
Paul Welty, PhD AI, WORK, AND STAYING HUMAN

Work log: Diktura — April 1, 2026

What shipped today

Today was an infrastructure and reliability pass on the feedback inbox — the kind of work that doesn’t change what users see but makes the system defensible going forward. Four commits landed, closing three GitHub issues, and the work broke into three coherent themes: auth hardening, error surfacing, and performance.

The first theme was auth. The middleware had no route guard — authenticated routes were being reached without a valid session, relying entirely on downstream checks to catch it. The fix (issue #50) added a proper guard directly in middleware.ts that checks the Supabase session after refresh and redirects unauthenticated users to /auth/login?next=... before they ever reach a protected route. A login page was also wired up for this flow — the application now has a complete unauthenticated → authenticated → redirect cycle. Sixteen middleware tests now cover the session refresh and redirect behavior.

The second theme was silent failures. A scout scan earlier in the project had flagged several places where errors were swallowed rather than surfaced (issue #51). The FieldSelect component now shows an inline error if updateFeedbackItem fails. Sign-out wraps supabase.auth.signOut() and renders failure inline rather than dropping it. The comments fetch checks the Supabase error response and renders an error state instead of showing an empty list with no explanation. The comment form now confirms submission with “Comment posted.” rather than resetting silently. These are individually small, but together they close the gap between code that works in the happy path and code that communicates honestly when something goes wrong.

The third theme was performance and pagination (issue #53). Comments were being fetched without a limit — an unbounded query on a detail page that could silently degrade as feedback accumulates. That’s now capped at 50 per load. The auth helper createServerSupabase() was being awaited before getCurrentUser() even though there’s no dependency between them — those now run in parallel via Promise.all. A Supabase migration added an index on workspace_memberships(profile_id, is_active) since that compound lookup happens on every authenticated request. Finally, out-of-bounds ?page= values now redirect to the last valid page rather than rendering a blank table.

Completed

  • #50 — Add root middleware.ts for session refresh and route protection
  • #51 — Fix silent failures in FieldSelect, sign-out, and comments fetch
  • #53 — Add pagination to comments and batch sequential auth queries

Carry-over

  • #52 — Test coverage for auth flows and server actions (ready-for-prep; strategy decision needed before implementation)
  • #54 — Port widget public submission flow, changelog, and broadcasts (ready-for-prep; the next major feature slice per PRODUCT.md)
  • #55 — Legacy Rails CI: scan_ruby and lint jobs failing (Rails-side, not new stack)
  • #56 — Engine build error on Railway (production deploy failing; needs investigation)

Risks

Two open issues warrant immediate attention next session. Issue #56 is a Railway build failure on the diktura-engine service — the engine is not deploying to production. This is a silent risk: the web layer works fine but command processing is broken until this is resolved. Issue #55 is a CI failure on the legacy Rails side (scan_ruby and lint jobs) — less urgent since the Rails app is in maintenance mode, but it means CI is red and could mask new failures.

Test coverage remains the structural risk (#52). Auth flows, server actions, and onboarding have no automated tests, and CI does not enforce test passes. The middleware tests added today are a start, but the core paths are still uncovered. See RISKS.md entry for the full register entry.

Flags and watch-outs

  • The Railway engine build failure (#56) means the commands queue is accumulating without being processed in production. If there are real users, any command-based flows are silently broken. Check this first next session.
  • The workspace_memberships index migration (20260401120000) is committed and will apply on the next supabase db push. Confirm it’s applied before treating auth performance as resolved.
  • Vitest is now configured in web/ but the test suite is thin — 16 middleware tests and 2 env helper tests. The scaffolding is there; coverage work (#52) can now proceed without setup friction.

Next session

  1. Investigate and fix the Railway engine build error (#56) — start by reading the Railway logs, then check the Dockerfile and any recent dependency or config changes in engine/.
  2. Prep issue #54 (widget public submission flow) — read the legacy Rails widget controller and views to understand the embed and submission model, then scope the new stack implementation. This is the next product slice.
  3. Decide test strategy for #52 — unit tests with mocked Supabase vs integration tests with a test project. Document the decision in DECISIONS.md, then start with auth + feedback CRUD as the first coverage targets.
  4. Address Rails CI (#55) — lower priority but CI should be green; scan the failing lint/scan_ruby annotations to see if these are fixable in a single pass.

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.

Delegation without comprehension is just prayer

The organizations that survive won't be the ones that automated the most. They'll be the ones that figured out what to stop delegating.

The case for corporate amnesia

Most organizations worship institutional memory. But what if the thing they're preserving is mostly decay?

Your design philosophy is already written

Builders who work across multiple projects leave fingerprints everywhere. The same mind solves the same problem differently in every domain — and usually doesn't notice. You need someone to read it back to you.