Back

Changelog

v2.100

Releases

July 2026(15)May 2026(2)April 2026(1)February 2026(29)
View on GitHub

What's New in DeRahm

Every merged pull request is a release. This page tracks all changes shipped to DeRahm, from new features and improvements to bug fixes and infrastructure work.

July 2026

v0.5.7
Today

fix: upgrade workflow SDK off sunset 4.x beta — restores all sync enqueues

Production incident All sync enqueues on derahm.com are failing with: ```json {"error":"Failed to enqueue connection sync","errorCode":"connection_sync_enqueue_failed","traceId":"..."} ``` Root cause (from Vercel runtime logs, `POST /api/connections/[id]/sync`, trace `dad1be518d7d9173c05f0b2f7fbace65` era): ``` WorkflowAPIError: This Workflow 4.x beta release is no longer supported for starting new runs. Please upgrade to the latest supported Workflow release. status: 426, url: https://vercel-workflow.com/api/v2/runs/.../events ``` Vercel sunset the Workflow DevKit 4.x **beta** line. We were pinned to `workflow@^4.1.0-beta.57`, so `start()` is rejected with HTTP 426 for every run. This also silently breaks the `refresh-ical-feeds` cron (`[calendar-resource-links] Failed to enqueue config-change sync` on every cycle) and the hourly scheduled syncs. DynamoDB, Neon, and Clerk are all healthy in the request traces — this is purely the SDK version. Change

•`workflow` `^4.1.0-beta.57` → `^4.6.0` (current stable GA)
•`@workflow/errors` `4.1.0-beta.15` → `4.1.4` (the version workflow@4.6.0 ships with)
•`.gitignore`: `/.swc` entry appended by build tooling

Verification

•Every symbol we import exists in 4.6.0: `start`/`getRun` (`workflow/api`), `getStepMetadata`/`getWritable` (`workflow`), `withWorkflow` (`workflow/next`)
•`tsc --noEmit` error set is **identical** to the pre-upgrade baseline (one pre-existing error at `lib/workflow/client.ts:31` changed error code TS2345→TS2769 because `start` gained overloads; same underlying complaint, no new errors)
•Integration suite: **188/188 pass**

+ 8 more lines...

azide0x37azide0x37
#119
v0.5.6
1 weeks ago

Gate sync creation at plan limit with upgrade dialog

Problem Free users at their sync connection limit could walk through the entire sync wizard, only to fail at the final step with a generic **"Failed to create sync — Please try again"** toast. Retrying can never succeed, and the structured 402 response the API already returns (`errorCode: plan_limit_reached`, `upgradeUrl: /pricing`) was thrown away by the client. Changes **Entry gate (primary fix)**

•The client now consumes the `billing` summary that `/api/state/bootstrap` already returns and computes `atSyncConnectionLimit` from the same user-visible connection list the server-side check counts.
•Every wizard entry point (header "New Sync", both mobile buttons, empty-state templates) is gated: at-limit free users get a contextual upgrade dialog instead of the wizard. Editing an existing sync is untouched; Pro users (unlimited) never hit the gate; missing billing data fails open to the server backstop.

**Upgrade dialog (`PlanLimitDialog`)**

•Framed as an upsell, not an error: usage context ("You're using 1 of 1 sync connections on the free plan"), Pro feature highlights matching the pricing page, reassurance that existing syncs keep running, "Upgrade to Pro" CTA to `/pricing`, and a "Maybe later" dismiss.
•Fires `plan_limit_paywall_shown` / `plan_limit_paywall_upgrade_clicked` analytics events tagged with trigger source (`entry_gate` vs `create_rejected`) so conversion on this flow is measurable.

**402 backstop**

•New `ApiRequestError` preserves `status`/`errorCode`/`traceId` from API error bodies; `createConnection` throws it instead of a flattened `Error`.

+ 9 more lines...

azide0x37azide0x37
#117
v0.5.5
1 weeks ago

chore: go-live polish — real favicon, mobile drawer, live search, copy and hygiene

Summary Go-live polish batch across icons, mobile navigation, search, copy, and v0-scaffolding cleanup. Does not touch `components/share-link-list.tsx` or `components/google-connect.tsx` (owned by parallel branches). 1. Favicon / app icons are now the real logo The audit found `app/icon.tsx` / `app/apple-icon.tsx` (ImageResponse generators) were overriding the `metadata.icons` block — and the static `/public` assets that block points at were still the **v0 logo** (`icon.svg` and both 32x32 PNGs showed the v0 wordmark).

•`public/icon-light-32x32.png` and `public/icon-dark-32x32.png` regenerated from `public/derahm-logo.png` via `sips` — **the favicon is now the rainbow DeRahm nabla (inverted triangle with constellation) on a transparent background**, same artwork in both color schemes since the mark reads well on light and dark
•`public/icon.svg` replaced with a hand-built scalable SVG of the nabla mark (rainbow gradient stroke, vertex stars, constellation line), transparent background
•`public/apple-icon.png` (180x180 nabla on dark) already matched the real logo — kept as-is
•`app/icon.tsx` and `app/apple-icon.tsx` deleted, so the light/dark media-query `metadata.icons` block in `app/layout.tsx` now takes effect
•`app/opengraph-image.tsx` untouched (already uses the real logo)

2. Mobile menu drawer (`components/sidebar.tsx`)

•Drawer now slides in from the **right**, under the hamburger button (closed: `translate-x-full`, anchored `right-0`)

+ 29 more lines...

azide0x37azide0x37
#115
v0.5.4
1 weeks ago

fix: invites/shares section clarity, accepted-share actions, consistent delete confirms

What Section rename

•Sidebar nav item and section header renamed from "Pending Invites" to **"Invites & Shares"**, with a description covering both pending requests and accepted shares. The section id `proposals` is unchanged (referenced in nav, analytics, and section routing).
•The page now labels its two groups: "Pending Requests" and "Accepted Shares", and the empty state reflects both.

Reusable ConfirmDialog

•New `components/ui/confirm-dialog.tsx`: small controlled confirmation modal following the house modal style (`fixed inset-0 bg-black/50` overlay, `rounded-2xl border bg-card` panel, destructive styling option). Plain React + Tailwind, no new dependencies.

Consistent delete confirmations

•**Share link Delete** (`share-link-list.tsx`): now confirms, noting the link stops working immediately for anyone who has it.
•**Share Revoke**: the `window.confirm` in `derahm-app.tsx` is gone; the confirm lives in `share-link-list.tsx` next to the action.

+ 14 more lines...

azide0x37azide0x37
#116
v0.5.3
1 weeks ago

fix: make Google disconnect real, confirmed, and account linking work for email users

Problems 1. **Disconnect didn't actually disconnect.** `handleGoogleDisconnect` only flipped app-side state (`/api/google-state`). The Clerk-managed Google external account stayed linked, so the reconcile effect in `derahm-app.tsx` — which trusts Clerk as the source of truth via `checkGoogleConnection()` — immediately set the state back to connected. The disconnect visibly undid itself. 2. **No confirmation** before disconnecting, despite it breaking every sync that uses Google calendars. 3. **The sidebar's "Connected" chip fired disconnect on click.** It looks like a status indicator; clicking it was destructive. 4. **Email-signup users couldn't connect Google.** `GoogleCalendarSetup` called `openSignIn()`, which is a no-op for an already-signed-in user, and the `isConnecting` spinner never reset. Fixes

•**Real disconnect (server side).** New `disconnectGoogleAccount()` server action in `lib/google-actions.ts`: resolves the user via `auth()`, finds the `oauth_google` external account, and unlinks it with `client.users.deleteUserExternalAccount({ userId, externalAccountId })` (verified against the installed `@clerk/backend` 3.2.10 types). After the unlink, `checkGoogleConnection()` returns `connected: false`, so the reconcile effect keeps the state disconnected instead of resurrecting it.
•**Confirmation modal.** New `GoogleDisconnectModal` (house style: fixed overlay, rounded-2xl card, destructive + Cancel actions) warns that syncs using Google calendars stop working until reconnected. Every disconnect path goes through it; it shows a pending state while the unlink runs and surfaces failures via a destructive toast.
•**Sidebar chip is non-destructive.** `GoogleConnect`'s `onDisconnect` prop is replaced with `onManage`; the sidebar routes it to the Settings section. Disconnect now lives only in Settings behind the confirm modal. Analytics event renamed from "Google Disconnect" to "Google Connection Manage" accordingly.
•**Account linking for email users.** `GoogleCalendarSetup` now uses `user.createExternalAccount({ strategy: "oauth_google", redirectUrl })` and navigates to `verification.externalVerificationRedirectURL`. Errors (including Clerk API error messages) render inline and reset the spinner. Already-connected users still jump straight to calendar selection.
•**Atomic state clear.** Added `clearGoogleConnection()` to `use-connections`: calling `setGoogleConnected(false)` and `setSelectedCalendarIds([])` back to back races on a stale closure — the second PUT would send `connected: true` again.

Verification

•`npx tsc --noEmit`: no errors in any touched file; total project errors went from 31 on main to 30 (the removed error was the old broken `openSignIn` call itself). Remaining errors are pre-existing and unrelated.

+ 3 more lines...

azide0x37azide0x37
#114
v0.5.2
1 weeks ago

fix: stop landing-page flash on refresh and post-login

Problem **Before:** on every page refresh (and right after login), signed-in users saw the marketing landing page flash for a moment, then the workspace replaced it with a "Connecting to DeRahm" spinner. Fresh email sign-ins/sign-ups were also redirected to `/` (the marketing page) instead of the app, and the installed PWA opened on the landing page. Root causes: 1. `DeRahmApp` rendered `<LandingPage />` whenever Clerk `!isLoaded` — i.e. during hydration on every refresh, even for signed-in users — before swapping to `AuthenticatedApp` and its own bootstrap splash. 2. The page wrapped everything in `<Suspense fallback={null}>`, so the first paint was blank. 3. The sign-in and sign-up pages set `fallbackRedirectUrl="/"` on the Clerk components, overriding the ClerkProvider's `signInFallbackRedirectUrl="/connection"` from `app/layout.tsx`. 4. `app/manifest.ts` set `start_url: "/"`. Fix **After:** a refresh shows one continuous neutral splash (spinner + "Loading your workspace... / Connecting to DeRahm") from first paint through Clerk hydration through backend bootstrap — no marketing-page flash. Email sign-in/sign-up and the installed PWA land directly on `/connection`.

•New `components/workspace-splash.tsx` extracts the existing bootstrap-pending splash markup, reused in three places:
•`AuthenticatedApp`'s `bootstrapStatus === "pending"` branch (was inline JSX)
•`DeRahmApp` while Clerk `!isLoaded` (was `LandingPage`)
•The page-level `Suspense` fallback (was `null`)
•`fallbackRedirectUrl` → `"/connection"` on both sign-in and sign-up pages
•Manifest `start_url` → `"/connection"` (scope stays `/`)

Unchanged invariants

+ 6 more lines...

azide0x37azide0x37
#112
v0.5.1
1 weeks ago

fix: make public routes reachable and harden setup endpoint

Middleware public routes (middleware.ts) Clerk's `auth.protect()` was blocking routes that must be reachable without a session:

•**`/u/(.*)`** — the public profile page (`app/u/[handle]/page.tsx`). This is a growth feature (every viewer is a potential signup) and was returning an auth redirect for logged-out visitors.
•**`/api/cron/refresh-ical-feeds(.*)`** — scheduled every 15 min in `vercel.json`. Vercel cron requests carry `Authorization: Bearer CRON_SECRET`, not a Clerk session, so the middleware rejected them before the route's own CRON_SECRET check ran. Mirrors the already-public `/api/cron/sync-calendars`.
•**`/icon`, `/apple-icon`, `/opengraph-image`** — Next.js file-convention metadata routes generated from `app/icon.tsx`, `app/apple-icon.tsx`, `app/opengraph-image.tsx`. They have no file extension, so the middleware matcher's static-file skip doesn't apply; favicons failed for logged-out visitors and OG scrapers were blocked.

Also removed the stale `"/trust"` entry — `app/trust` does not exist. Setup endpoint hardening (app/api/setup/recreate-table/route.ts) This route deletes and recreates the entire DynamoDB table:

•**Production guard**: `POST` now returns a 404 JSON response immediately when `process.env.VERCEL_ENV === "production"`, before any auth or AWS logic runs. The existing `x-setup-secret` check is unchanged for non-production environments.
•**Log hygiene**: removed the `console.log` that recorded auth metadata (secret presence, secret lengths, whether the header matched).

Tests

+ 4 more lines...

azide0x37azide0x37
#113
v0.5.0
1 weeks ago

fix: unblock the iCal refresh cron and backfill daily sync schedules

Problem Two independent gaps left an existing user's calendars unsynced: 1. **The iCal refresh cron has never run in production.** `/api/cron/refresh-ical-feeds` shipped 2026-02-19 without being added to the middleware public-route list (`/api/cron/sync-calendars` got its exemption 2026-02-05). The Vercel cron request carries only the `CRON_SECRET` bearer, so Clerk's `auth.protect()` answered it with a 404 every 15 minutes since launch — verified live: the route returned 404 while sync-calendars returned 401. Remote Import Calendars only refreshed on manual user action. 2. **Enabled connections could drop out of the hourly sync cron forever.** `SCHEDULE#DAILY` items are only written on connection mutations. Any connection whose item was lost (unschedule-on-failure, share expiry, a missed write) was never enqueued again, and unlike iCal poll schedules there was no bootstrap backfill to restore it. Fix

•Public route patterns move to a Clerk-free module ([lib/server/public-routes.ts](../blob/fix/cron-middleware-daily-schedule-backfill/lib/server/public-routes.ts)) and cover `/api/cron(.*)` as a whole; every cron route already enforces the `CRON_SECRET` bearer itself.
•Bootstrap reconciliation re-derives daily schedule items from connection state on every load via `ensureDailySchedulesForConnections` (idempotent set for enabled / remove for disabled), so wedged connections heal the next time the user opens the app — pairing with the lazy orphan-run unwedge from #107.

Tests

•`cron-route-public-access.integration.test.ts`: every route under `app/api/cron/` must be covered by the public matcher **and** contain its own cron-secret check; authenticated API routes must stay non-public. Guards against the next cron route regressing the same way.
•`daily-schedule-backfill.integration.test.ts`: schedule restore for enabled connections, removal for disabled, counts, no-op.
•Full suite: 187/187 pass (node test runner). `next build` passes; no new `tsc` errors in touched files.

Post-deploy verification 1. `curl -s -o /dev/null -w '%{http_code}' https://derahm.com/api/cron/refresh-ical-feeds` → expect **401** (was 404). 2. Import Calendar `lastFetched` should advance within 15 minutes. 3. Open the app once (bootstrap backfills schedules), then check connections' `lastSynced` advances on the next hourly cron. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

azide0x37azide0x37
#111
v0.4.9
2 weeks ago

feat: add Clerk Billing free/pro tiers with server-side plan limits

Summary Adds monetization via Clerk Billing (backed by the already-connected Stripe account). The app never talks to Stripe directly. **Tiers**

•**Free**: 1 sync connection, 1 active share link, unlimited iCal feed imports
•**Pro** (Clerk plan slug `pro`, override via `CLERK_PRO_PLAN_SLUG`): unlimited connections and share links

**Server-side enforcement**

•New `lib/server/billing.ts`: plan limits, plan resolution, and the 402 limit response
•Plan resolution order (cheapest first): Clerk session claims via `auth().has({ plan })` → `pla` claim on verified bearer tokens (iOS) → Clerk Billing API fallback. Unresolvable states default to free; `past_due` keeps entitlements through dunning; org-scoped plans do not grant personal entitlements
•`POST /api/connections`: new connections blocked over the limit (upserts of existing connections exempt; counts user-visible connections so managed-pair legs don't consume quota)
•`POST /api/share-links`: pending/accepted invites hold slots; declined/expired/revoked free them; rejections emit `share_invite_create_rejected` telemetry

+ 10 more lines...

azide0x37azide0x37
#110
v0.4.8
2 weeks ago

Fix: complete Windows timezone alias table from CLDR windowsZones

What Expands `WINDOWS_TIMEZONE_ALIASES` in `lib/server/ical.ts` from ~10 hand-added entries to the full CLDR windowsZones (territory 001) mapping, so Outlook/Exchange iCal feeds with TZIDs like `Tokyo Standard Time`, `India Standard Time`, or `AUS Eastern Standard Time` resolve correctly instead of dropping those events. Review corrections applied to the original draft

•**`Central Asia Standard Time` → `Asia/Bishkek`**, not `Asia/Almaty`: Kazakhstan unified on UTC+5 on 2024-03-01, so Almaty no longer matches this UTC+6 Windows zone (post-2024 CLDR agrees).
•**Unresolvable TZIDs keep the drop behavior.** The draft added a fall-through that reinterpreted the wall clock as UTC; that converts a visible failure (missing event) into a silent one (event synced hours off with a green run). Reverted — feeds using truly custom TZIDs (e.g. Exchange `Customized Time Zone`, defined only in an in-feed VTIMEZONE block the parser doesn't read) drop those values as before.
•The three **ad-hoc aliases that are not CLDR keys** (`gmt`, `w. europe time`, `central europe time`) are separated into a labelled block so a future regeneration from CLDR doesn't silently lose them.

Testing

•All 31 iCal/timezone integration tests pass; full suite 173/173.
•Pre-existing `tsc` strict-null warning at the parser loop (`currentEvent` possibly null) is unrelated and tracked separately.

Stacked on #106 (CI fix); its commits disappear from this diff once #106 merges. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

azide0x37azide0x37
#108
v0.4.7
2 weeks ago

Fix: unwedge connections orphaned by a crash before workflow start

Problem `startConnectionSync` persists a non-deferred run with status `queued` and no `workflowRunId`, sets `connection.syncStatus="queued"`, and only then starts the workflow. If the serverless function crashes or times out in that window, the orphan run projects as in-flight forever (`projectSyncRunStatus` returns `queued` verbatim when there is no workflow to look up), so every subsequent enqueue — manual, repair, hourly cron — resolves strategy `already_queued` against it. The connection wedges permanently. This is the non-deferred twin of the deferred-run wedge fixed in #103. Fix

•**`isOrphanedQueuedRun`** (sync-cutover-logic): a non-deferred `queued` run with no workflow attached, older than `STALE_SYNC_LOCK_MIN_AGE_MS` (90s, moved here and exported so service + tests share one floor), is abandoned — the start window has long since passed.
•**`isInFlightSyncRun`** takes optional `ageMs`/`orphanedQueuedMinAgeMs` and excludes stale orphans; age-less callers keep the conservative reading. The orphan predicate's params are required, so a caller can't silently defuse the check by omitting one.
•**`findActiveRunForConnection`** passes each candidate's age, and when the scan finds nothing in flight, terminalizes collected orphans via `recordSyncFailure({ terminalReason: "workflow_start_orphaned", skipDeferredStart: true })` — run record, connection projection, and lawful-sync mirror all terminalize together, and `skipDeferredStart` prevents recursion. Terminalization is deferred to after the scan so a failure is never stamped over a genuinely active run's connection state.

Known trade-off A workflow start that is merely slow (>90s between `putSyncRun` and the workflow attach) is indistinguishable from a crash and could be terminalized by a concurrent enqueue; `updateSyncRun` has no compare-and-swap, so the original could later flip the run back to running. Same acceptance as the existing `staleSyncLockBefore` recovery — the 90s floor comfortably exceeds a step's execution budget. A leased/conditional write on the queued record would close this class entirely (follow-up). Testing

•New `tests/integration/sync-orphaned-queued-run.integration.test.ts` in the style of the deferred-lifecycle test: stale orphan excluded and next enqueue resolves `queue_immediate` (mirroring production's `runId`/status strategy wiring); fresh in-window orphan still blocks duplicates; age never demotes runs with a workflow or deferred placeholders; age-less callers unchanged.
•Full integration suite: 173/173 pass.

Stacked on #106 (CI fix); the first two commits disappear from this diff once #106 merges. 🤖 Generated with [Claude Code](https://claude.com/claude-code)

azide0x37azide0x37
#107
v0.4.6
2 weeks ago

Fix test CI: run node test runner instead of missing vitest

Summary

•The `test` workflow ran `pnpm exec vitest run --coverage.enabled true`, but vitest has never been a dependency — the check failed on every PR in ~30s with `ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL` and was routinely merged over red.
•The workflow now runs the real suite: `pnpm run test:integration` (node test runner + tsx). The vitest coverage-report action is removed, along with the `pull-requests: write` permission it needed.
•CI Node is bumped 20 → 22: pnpm executes scripts via `sh` on Linux, which passes the `tests/integration/**/*.test.ts` glob through literally, and only Node ≥21's test runner expands globs itself. (Also matches `@types/node: ^22`.)
•Fixes the one pre-existing failure on main, **fetchICalFeed parses Windows timezone IDs**: the fixture's hardcoded event date (2026-02-19) drifted out of `fetchICalFeed`'s 30-day past window (`clampEventsToWindow`), so it started failing around 2026-03-21. The test now freezes the clock with `node:test` mock timers, keeping the Microsoft Exchange fixture byte-for-byte.

Test plan

•[x] Full suite green locally on a clean checkout of this commit: 169/169 pass
•[x] Verified via `sh -c` (literal glob, node-side expansion) to mimic the CI execution path

+ 2 more lines...

azide0x37azide0x37
#106
v0.4.5
2 weeks ago

Switch lawful-sync store to Neon HTTP driver, drop request-path DDL

Summary Lands the hanging `api-error-analysis` branch (April 2026, never PR'd) so all active work is in main.

•Replaces `@vercel/postgres` pooled client with the `@neondatabase/serverless` HTTP driver in `lib/server/lawful-sync/store.ts` (one fetch per query, no WebSocket pool)
•Removes the `ensureSchema()` DDL calls from every request path; schema is now provisioned out-of-band via new `scripts/001_lawful_sync_schema.sql`
•Drops the `DATABASE_URL` fallback — lawful sync now requires `POSTGRES_URL` explicitly (fails fast with a clear error if missing)
•Removes `scripts/setup-lawful-sync-postgres.ts` and the `db:setup:lawful-sync` script

Ops note Deployments must have `POSTGRES_URL` set (the `DATABASE_URL` fallback is gone) and the schema applied via `scripts/001_lawful_sync_schema.sql` before this serves traffic. Validation

•Merges clean against current main; main has not touched these files since the branch point
•`tsc --noEmit`: no errors in any file this change touches (remaining errors are pre-existing debt, build uses `ignoreBuildErrors`)

+ 2 more lines...

azide0x37azide0x37
#105
v0.4.4
2 weeks ago

Add iOS PWA icon set, Apple touch icon, and safe-area handling

Summary Finishes the installable-PWA work for iOS. Splits out the working-tree changes that were unrelated to the calendar-sync fixes in #103. Changes

•**`app/manifest.ts`** — replace the dynamic `/icon` (32px) and double-used `/apple-icon` (180px) entries with a proper installable icon set: **192px + 512px**, each in both `any` and `maskable` purposes, backed by dedicated static PNGs. This is the icon set Android/Chrome and iOS expect for a clean install + masked launcher icon.
•**`app/layout.tsx`** — declare a 180×180 Apple touch icon (`/apple-icon.png`) so the iOS "Add to Home Screen" shortcut uses real artwork.
•**`components/landing-page.tsx`**
•Pad the fixed nav and hero with `env(safe-area-inset-top)` so content clears the notch / Dynamic Island when launched standalone (installed) on iOS.
•**Fix:** import `useSignUp` from `@clerk/nextjs` instead of `@clerk/nextjs/legacy`. The app mounts the current `ClerkProvider` (from `@clerk/nextjs`), so the legacy hook read a provider context that isn't present — `signUpLoaded` stayed `false` and the landing-page Google sign-up button was effectively a no-op. This was also the last remaining `@clerk/nextjs/legacy` import in the codebase.
•**`public/*.png`** — new icon assets: `apple-icon.png` (180), `pwa-icon-192/512.png` (any), `pwa-maskable-192/512.png` (maskable).

Notes for reviewer

+ 4 more lines...

azide0x37azide0x37
#104
v0.4.3
2 weeks ago

Fix deferred calendar-sync wedge + harden cron sync pathways

Summary Deep-dive into the external-calendar auto-sync and scheduled-sync state machine surfaced one high-severity logical error plus four robustness gaps. This PR fixes all of them. 🔴 Primary: deferred-run wedge (silent, permanent) When a `config_change` lands while a sync is running, a follow-up run is deferred (persisted as `queued` with no workflow attached). But `findActiveRunForConnection` counted that deferred run as *in flight*, so:

•`startDeferredRunIfReady` short-circuited on the very run it was supposed to start, and
•every subsequent enqueue (manual, hourly cron, `config_change`) deduped into the stalled placeholder and returned `alreadyQueued`.

Net effect: after a single deferral, the connection **silently stops syncing** (automated *and* manual), while the UI still shows the last successful state. Most likely to hit paired connections (the reverse-pair recovery path explicitly enqueues `config_change`) and iCal-poll-vs-running-sync overlaps. The deferred-start path had **no test coverage**. **Fix**

•New pure predicates `isDeferredPendingRun` / `isInFlightSyncRun` in `sync-cutover-logic` — a deferred queued run with no workflow is not in flight.
•`findActiveRunForConnection` and `findDeferredQueuedRun` use them, so deferred runs no longer block their own start.
•On enqueue, when nothing is in flight and a deferred run is waiting, it's **promoted/started** (reusing the already-loaded connection, one extra lookup only when a deferred run exists). Because every enqueue path — including the hourly cron — funnels through here, this also **reaps deferred runs orphaned** by a process that died before recording a terminal state (self-heals within ≤1h).
•New regression test `sync-deferred-run-lifecycle.integration.test.ts` covering defer → terminal → start.

+ 8 more lines...

azide0x37azide0x37
#103

May 2026

v0.4.2v0
2 months ago

Enable PWA support and optimize mobile safe-area layout

•Added Progressive Web App (PWA) support including configuration for manifest.ts.
•Updated application icons with Next.js branding and removed legacy image assets.
•Fixed safe-area inset issues in the header and sidebar to ensure proper layout on notched mobile devices.

[v0 Session](https://v0.app/chat/YeTXnZVhiqM)

azide0x37azide0x37
#102
v0.4.1v0
2 months ago

Enable Google OAuth, referral tracking, and public profile management

•Implemented Google OAuth authentication including callback handling and landing page integration.
•Added an empty state interface featuring a visual flow diagram to guide new users.
•Created public profile sections and user settings for profile management.
•Integrated referral tracking functionality to monitor user growth.
•Added a branded footer across the application.
•Imported initial project structure from GitHub.

[v0 Session](https://v0.app/chat/T32aMN1U2Wh)

azide0x37azide0x37
#101

April 2026

v0.4.0v0
3 months ago

Upgrade Clerk authentication to v7 for client trust support

•Upgraded `@clerk/nextjs` to version 7.0 to leverage the latest authentication features.
•Enabled client trust support to enhance security and session reliability.
•Initialized the project structure with imported source files from GitHub.

[v0 Session](https://v0.app/chat/DsS3k6R9wZX)

azide0x37azide0x37
#100

February 2026

v0.3.9
5 months ago

Redesign calendar avatars and enable public connection routes

•Redesigned the `CalendarAvatar` component using ghost avatars and a text-dominant hierarchy to improve visual clarity.
•Enabled public access to connection routes, allowing unauthenticated users to view connection-related pages.

[v0 Session](https://v0.app/chat/pksbQa6ojNS)

azide0x37azide0x37
#99
v0.3.8
5 months ago

Enable public access to connection routes

•Removed authentication requirements for `/connection` routes to allow public access.
•Updated project configuration in `settings.json`.

[v0 Session](https://v0.app/chat/pksbQa6ojNS)

azide0x37azide0x37
#98
v0.3.7
5 months ago

fix: correct typo in showShareLink references

This PR addresses a typo in `showShareLink` references to ensure correct functionality. **Problem/Issue/Goal:**

•References to `showShareLinkDialog` were incorrect due to a typo.

**Fix/Solution:**

•Corrected the typo in `showShareLink` references in three locations.

Chat link: https://v0.app/chat/BiLxlvTWIyG

azide0x37azide0x37
#97
v0.3.6
5 months ago

Update project files

This PR includes 30 commits with various updates and improvements. Chat link: https://v0.app/chat/wh25es6JzVn

azide0x37azide0x37
#96
v0.3.5
5 months ago

feat: enhance changelog, data handling, and calendar sync

This PR introduces a changelog, enhances data handling and calendar synchronization, and improves the overall user interface. **Problem/Issue/Goal:**

•**Changelog & Versioning:** Needed a clear way to communicate updates and features, ensure public access to documentation, and optimize changelog generation.
•**Data & Backend Reliability:** Encountered issues with DynamoDB credentials, schema consistency, silent data loading failures, and cron secret validation.
•**Calendar Synchronization:** Faced challenges with Google Calendar filtering, iCal duplicate keys, recurring event handling, and general sync robustness.
•**User Experience:** Required layout improvements for better navigation and content visibility on larger screens.

**Fix/Solution:**

•**Changelog & Versioning:** Implemented a version badge and a publicly accessible changelog page, refactored to build-time generation for improved performance.
•**Data & Backend Reliability:** Resolved DynamoDB credential and schema issues, centralized data loading with robust error handling, added debug logging for cron secrets, and updated the data layer for a consistent schema.

+ 3 more lines...

azide0x37azide0x37
#95
v0.3.4
5 months ago

feat: enhance changelog, improve data handling, and fix calendar sync

This PR introduces significant improvements to calendar synchronization, enhances data handling robustness, and refactors the changelog system for better reliability and user experience. **Problem/Issue/Goal:**

•Existing DynamoDB configurations led to credential, key schema, and table schema mismatches, affecting data operations.
•The application lacked a version badge and a dedicated changelog page, and existing changelog content was not publicly accessible or prone to runtime errors.
•Data loading mechanisms were susceptible to silent failures, lacking proper error states and diagnostic logging.
•Calendar synchronization (Google Calendar, iCal) suffered from several issues, including incorrect filtering, duplicate key errors, flawed recurring event handling, Blob token retrieval problems, and a lack of robust error handling for API interactions.

**Fix/Solution:**

•**Database & Data Reliability:**
•Resolved DynamoDB credential, key schema, and table schema mismatches.

+ 12 more lines...

azide0x37azide0x37
#94
v0.3.3
5 months ago

feat: Implement changelog, improve data handling, and enhance calendar sync

This PR introduces a changelog, significantly improves data handling and stability, and enhances calendar synchronization capabilities. **Problem/Issue/Goal:**

•Lack of a public changelog and version tracking.
•Frequent DynamoDB credential and schema issues on Vercel, leading to instability.
•Silent failures in data loading and lack of clear error states for users.
•Inefficient runtime changelog generation causing potential API errors.
•Inaccurate Google Calendar filtering and synchronization issues, including duplicate key errors and problems with recurring events in iCal.
•Need for better diagnostics for cron secret validation.

**Fix/Solution:**

+ 8 more lines...

azide0x37azide0x37
#93
v0.3.2
5 months ago

feat: implement changelog, enhance data, and fix database & iCal

This PR introduces a changelog page, significantly improves data handling, and resolves critical issues related to database schema, credentials, and calendar synchronization. **Problem/Issue/Goal:**

•Lack of a version badge and a centralized changelog for users.
•Inconsistent and error-prone data loading, leading to silent failures.
•Persistent DynamoDB credential and schema mismatches affecting application stability.
•Inefficient changelog generation causing runtime API errors.
•Inaccurate Google Calendar filtering and recurring event synchronization issues.

**Fix/Solution:**

•Implemented a version badge and a dedicated changelog page, ensuring public accessibility.

+ 6 more lines...

azide0x37azide0x37
#92
v0.3.1
5 months ago

Update project files

This PR includes 19 commits with various updates and improvements. Chat link: https://v0.app/chat/wh25es6JzVn

azide0x37azide0x37
#91
v0.3.0
5 months ago

feat: enhance changelog, improve data handling, and fix database issues

This PR introduces a changelog page, significantly improves data handling and error reporting, and addresses various critical database and credential issues. **Problem/Issue/Goal:**

•Users needed a way to view version history and changes.
•DynamoDB credential and key schema issues were causing deployment and data access problems.
•Data loading mechanisms were prone to silent failures, leading to a poor user experience.
•Certain public-facing content (changelog) was unintentionally restricted.
•Debugging for cron secret validation was insufficient.
•Google calendar integration required specific filtering.

**Fix/Solution:**

+ 8 more lines...

azide0x37azide0x37
#90
v0.2.9
5 months ago

feat: Implement changelog, improve data handling, and fix database

This PR introduces a changelog and version badge feature, significantly improves data loading and error handling, and addresses critical DynamoDB configuration and schema issues. **Problem/Issue/Goal:**

•Lack of a clear way to track product versions and changes for users.
•Silent failures in data loading hooks led to an inconsistent user experience.
•Persistent DynamoDB credential and key schema mismatches on Vercel caused data access failures.
•Changelog pages were not publicly accessible, hindering information dissemination.
•Difficulty in diagnosing cron secret validation failures.

**Fix/Solution:**

•Implemented a version badge and a dedicated changelog page, populated by merged PRs.

+ 6 more lines...

azide0x37azide0x37
#89
v0.2.8
5 months ago

feat: Implement changelog, enhance data handling, and fix issues

This PR introduces a changelog page, improves data loading and error handling, and resolves several critical issues related to DynamoDB and public access. **Problem/Issue/Goal:**

•DynamoDB credential and schema mismatches were causing application errors.
•The application lacked a public changelog and version tracking.
•Data loading had silent failures, leading to poor user experience.
•Certain public pages and APIs were unintentionally restricted.
•Difficulty diagnosing cron secret validation failures.

**Fix/Solution:**

•Resolved DynamoDB credential issues on Vercel and fixed key schema mismatches.

+ 5 more lines...

azide0x37azide0x37
#88
v0.2.7
5 months ago

feat: Implement changelog, enhance data handling, and fix issues

This PR introduces a changelog page, enhances data loading mechanisms, and resolves several backend and access-related issues. **Problem/Issue/Goal:**

•DynamoDB credential and key schema mismatches caused data access and persistence problems.
•Data loading mechanisms were silently failing, leading to an inconsistent user experience and poor error handling.
•The changelog and its API routes were not publicly accessible, hindering information dissemination.
•There was a lack of a dedicated version badge and a comprehensive changelog page for users.
•Issues on the landing page for authenticated users needed to be resolved.

**Fix/Solution:**

•Resolved DynamoDB credential and key schema inconsistencies, including table recreation with the correct composite key.

+ 5 more lines...

azide0x37azide0x37
#87
v0.2.6
5 months ago

feat: Add changelog, improve data handling, and fix issues

This PR introduces a new changelog page and version badge, centralizes data loading with robust error handling, and resolves several critical issues to improve application stability and user experience. **Problem/Issue/Goal:**

•DynamoDB credential and key schema mismatches led to application instability.
•Data hooks experienced silent failures, and backend issues were not properly communicated.
•Changelog and related API endpoints were restricted, requiring authentication.
•Lack of a clear way to display application version and recent changes to users.

**Fix/Solution:**

•Addressed DynamoDB credential and key schema issues for improved database reliability.
•Centralized data loading and implemented proper error handling to surface backend failures and provide clear error states.

+ 3 more lines...

azide0x37azide0x37
#86
v0.2.5
5 months ago

feat: implement version badge and changelog page

This PR introduces a version badge and changelog page, enhancing transparency and user information, while also addressing critical backend and frontend stability issues. **Problem/Issue/Goal:**

•Lack of clear versioning and change history for users.
•Critical DynamoDB credential and key schema mismatches affecting application stability.
•Inconsistent landing page experience for authenticated users.

**Fix/Solution:**

•Implemented a version badge and a dedicated changelog page, powered by an API route for merged PRs.
•Resolved DynamoDB credential issues on Vercel and corrected key schema mismatches.
•Refined landing page logic by separating hooks for authenticated users.

+ 1 more lines...

azide0x37azide0x37
#85
v0.2.4
5 months ago

feat: add version badge and changelog page

This PR introduces new features for version tracking and a changelog, while also resolving a critical credential issue for DynamoDB on Vercel. **Problem/Issue/Goal:**

•DynamoDB operations were failing on Vercel due to credential misconfiguration.
•Users lacked a clear way to identify the current application version.
•There was no centralized location to view release notes or recent changes.

**Fix/Solution:**

•Addressed and resolved DynamoDB credential issues specifically impacting Vercel deployments.
•Implemented a version badge component to display the application's current version.
•Developed a dedicated changelog page, populated by fetching merged PRs, to provide release notes.

+ 1 more lines...

azide0x37azide0x37
#84
v0.2.3
5 months ago

fix: resolve DynamoDB credential issues on Vercel

This PR resolves critical DynamoDB credential issues, ensuring proper database functionality on Vercel deployments. **Problem/Issue/Goal:**

•DynamoDB operations were failing due to incorrect or missing credentials when deployed on Vercel.

**Fix/Solution:**

•Implemented a fix to correctly configure and resolve DynamoDB credentials for Vercel environments.
•Ensures stable and reliable database interactions for the application.

Chat link: https://v0.app/chat/wh25es6JzVn

azide0x37azide0x37
#83
v0.2.2
5 months ago

feat: implement OpenTelemetry tracing

This PR integrates OpenTelemetry tracing into the Derahm application to enhance observability and corrects an environment variable used for DynamoDB table access. **Problem/Issue/Goal:**

•The application lacked distributed tracing capabilities, making it difficult to monitor request flows and performance.
•Initial attempts to implement tracing had incorrect package imports and configurations.
•An incorrect environment variable name was being used for the DynamoDB table, potentially leading to access issues.

**Fix/Solution:**

•Implemented OpenTelemetry tracing utilities and instrumented critical operations throughout the Derahm app.
•Corrected OpenTelemetry package imports, configurations, and usage within the tracing module.
•Updated all references from `DERAHM_DDB_TABLE` to `DYNAMODB_TABLE_NAME` for accurate DynamoDB table identification.

+ 1 more lines...

azide0x37azide0x37
#82
v0.2.1
5 months ago

fix: Update DynamoDB table env var name

This PR corrects the environment variable used for the DynamoDB table name, ensuring proper application configuration. **Problem/Issue/Goal:**

•An incorrect environment variable (`DERAHM_DDB_TABLE`) was being referenced for the DynamoDB table name.
•This could lead to misconfiguration or failure to connect to the correct DynamoDB table.

**Fix/Solution:**

•Updated all references from `DERAHM_DDB_TABLE` to `DYNAMODB_TABLE_NAME`.
•Ensures the application correctly identifies and uses the DynamoDB table name.

Chat link: https://v0.app/chat/4aOaFfkpK7h

azide0x37azide0x37
#81
v0.2.0
5 months ago

feat: add custom tracking events and update cron schedule

This PR introduces custom tracking events and updates the cron schedule to enhance monitoring and task automation. **Problem/Issue/Goal:**

•Needed to implement custom tracking for specific events.
•Required an update to the existing cron schedule.
•Needed to add tracking to action links.

**Fix/Solution:**

•Added custom tracking events.
•Updated the `vercel.json` cron schedule.
•Implemented tracking for action links.

+ 1 more lines...

azide0x37azide0x37
#80
v0.1.9
5 months ago

feat: Integrate Clerk auth, optimize navigation, and update branding

This PR introduces Clerk for authentication, significantly enhances navigation performance, and updates the application's branding and legal documentation. **Problem/Issue/Goal:**

•Implement a robust and scalable authentication system.
•Resolve existing authentication flow issues like infinite loading states and redirect handling.
•Improve overall navigation performance and layout stability.
•Add essential legal compliance pages (Privacy, Terms of Service).
•Update application branding and design elements.

**Fix/Solution:**

•Integrated Clerk with Google Calendar OAuth, including necessary components and server actions.

+ 7 more lines...

azide0x37azide0x37
#77
v0.1.8
5 months ago

fix: Remove route protection and update privacy policy

This PR enhances public access to key information pages and ensures compliance by updating documentation regarding Google Calendar API scopes. **Problem/Issue/Goal:**

•Critical information pages (`/privacy`, `/trust`) were inaccessible to the public due to route protection.
•Debugging components were present and needed removal for a cleaner production environment.
•The privacy policy and documentation did not accurately reflect the Google Calendar API scopes in use.

**Fix/Solution:**

•Removed route protection for `/privacy` and `/trust`, making them publicly accessible.
•Eliminated debug pane and associated logging elements.
•Updated the privacy policy and relevant documentation to correctly detail Google Calendar API scopes.

+ 1 more lines...

azide0x37azide0x37
#79
v0.1.7
5 months ago

fix: Remove route protection and debug elements

This PR addresses access restrictions and removes debugging components to streamline the application. **Problem/Issue/Goal:**

•The `/privacy` and `/trust` routes were protected, preventing public access.
•Debugging elements (pane and logs) were present in the application.

**Fix/Solution:**

•Removed route protection for `/privacy` and `/trust` to make them publicly accessible.
•Eliminated the debug pane and associated logs from the application.

Chat link: https://v0.app/chat/Yh1b7xPzKIl

azide0x37azide0x37
#78
v0.1.6
5 months ago

feat: Integrate Clerk auth, optimize navigation & add legal pages

This PR integrates Clerk for robust authentication, significantly optimizes navigation performance, and adds essential legal compliance pages. **Problem/Issue/Goal:**

•Existing authentication needed a robust solution, including Google Calendar OAuth.
•Clerk authentication flow had issues with loading states and redirect handling.
•Navigation performance was suboptimal, leading to full page redraws and layout instability.
•Missing critical Privacy and Terms of Service pages for legal compliance.

**Fix/Solution:**

•Integrated Clerk with Google Calendar OAuth, including `ClerkProvider` and middleware.
•Improved Clerk auth flow by removing blocking loading states, using built-in components, and setting proper redirect URLs.

+ 5 more lines...

azide0x37azide0x37
#76
v0.1.5
5 months ago

feat: Integrate Clerk auth and enhance navigation

This PR introduces Clerk for user authentication and significantly enhances the application's navigation performance and stability. **Problem/Issue/Goal:**

•Lack of a robust and secure authentication system.
•Inefficient state-based navigation leading to full page redraws and poor performance.
•Existing authentication flow had issues like infinite loading states and improper redirect handling.
•Layout instability and Cumulative Layout Shift (CLS) during navigation.
•Need for Google Calendar OAuth integration.

**Fix/Solution:**

•Integrated Clerk for comprehensive user authentication, including ClerkProvider, middleware, and server actions.

+ 5 more lines...

azide0x37azide0x37
#75
v0.1.4
5 months ago

feat: Integrate Clerk auth and optimize navigation

This PR introduces Clerk for user authentication, including Google Calendar OAuth, and significantly enhances application performance by optimizing navigation and routing. **Problem/Issue/Goal:**

•**Navigation Performance:** State-based navigation led to full page redraws and poor performance, especially for the sidebar.
•**Authentication:** Lacked a robust and secure user authentication system with OAuth capabilities (e.g., Google Calendar).
•**Clerk Integration Issues:** Initial Clerk setup faced problems like blocking loading states, incorrect redirect handling, and infinite loading loops.

**Fix/Solution:**

•**Optimized Navigation:** Converted sidebar to URL-based routing and implemented scoped view transitions to prevent full page redraws, resulting in smoother navigation.
•**Clerk Authentication:** Integrated Clerk for user authentication, including `ClerkProvider`, middleware, and server actions for Google Calendar OAuth.
•**Improved Auth Flow:** Refined Clerk's authentication flow by removing blocking loading states, utilizing Clerk's built-in components, and configuring dedicated sign-in/sign-up pages with correct redirect URLs.

+ 2 more lines...

azide0x37azide0x37
#74
v0.1.3
5 months ago

feat: Integrate Clerk OAuth and optimize navigation

This PR integrates Clerk for robust user authentication with Google Calendar OAuth and significantly improves navigation performance by optimizing routing and view transitions. **Problem/Issue/Goal:**

•Existing state-based navigation led to full page redraws, impacting performance.
•Lack of a robust and secure user authentication system.
•Clerk authentication flow needed improvements for better user experience and redirect handling.

**Fix/Solution:**

•Optimized navigation by converting the sidebar to URL-based routing and scoping view transitions.
•Integrated Clerk for user authentication, including Google Calendar OAuth, ClerkProvider, middleware, and server actions.
•Improved Clerk auth flow by removing blocking loading states, using built-in components, and creating dedicated sign-in/sign-up pages with proper redirect URLs.

+ 1 more lines...

azide0x37azide0x37
#73
v0.1.2
5 months ago

feat: Integrate Clerk OAuth and optimize navigation

This PR introduces Google Calendar OAuth integration and significantly enhances application performance through navigation and routing optimizations. **Problem/Issue/Goal:**

•Existing state-based navigation led to inefficient full page redraws.
•Sidebar navigation and overall routing performance needed improvement.
•A secure and robust authentication solution with Google Calendar OAuth was required.

**Fix/Solution:**

•Implemented Clerk for user authentication, including ClerkProvider and middleware.
•Integrated Google Calendar server actions to support OAuth.
•Optimized state-based navigation to prevent full page redraws.

+ 2 more lines...

azide0x37azide0x37
#72
v0.1.1
5 months ago

fix: Optimize navigation and routing performance

This PR optimizes the application's navigation system by transitioning to URL-based routing, significantly improving performance and user experience. **Problem/Issue/Goal:**

•Existing state-based navigation caused full page redraws, leading to performance issues.
•Inefficient navigation negatively impacted user experience.

**Fix/Solution:**

•Converted sidebar to URL-based routing for improved navigation.
•Optimized existing state-based navigation to prevent full page redraws.
•Implemented scoped view transitions to enhance performance.

Chat link: https://v0.app/chat/T5Ts5i9L2PK

azide0x37azide0x37
#71

This changelog is automatically generated from merged pull requests in the DeRahm repository.