Clear oauthState before exchangeCode so duplicate callback requests
fail the state check instead of hitting GitHub with a consumed code.
Marked as HACK — root cause of duplicate HTTP requests is unknown.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Uses Date.now() so each process start gets a unique version.
This ensures Rivet Cloud migrates actors to the new runner on
deploy instead of routing requests to stale runners.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
OAuth authorization codes are single-use. The appWorkspaceAction wrapper
retries failed calls up to 20 times, but if the code exchange succeeds
and a later step fails, every retry sends the already-consumed code,
producing "bad_verification_code" from GitHub.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use CREATE TABLE IF NOT EXISTS and CREATE UNIQUE INDEX IF NOT
EXISTS so the squashed baseline can run against actors that
already have tables from the pre-squash migration sequence.
This fixes the "table already exists" error when org workspace
actors wake up with stale migration journals.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Every request was calling getOrCreate on the Rivet engine API
to resolve the workspace actor, even though it's always the same
actor. Cache the handle and invalidate on error so retries
re-resolve. This eliminates redundant cross-region round-trips
to api.rivet.dev on every request.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Railway has no persistent volumes so stale actors are wiped on
each deploy. The v2 key rotation is no longer needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Hide terminal pane body when no terminal tabs exist
- Redesign history minimap from orange bar to single icon with popover dropdown
- Simplify popover items to single-line user messages with ellipsis
- Adjust min-used badge hover padding
- Add right padding to message list for history icon clearance
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>