Delete unused files (run-logs.tsx, welcome/), remove unused mock data
and functions from data modules, un-export internal types, replace array
index keys with stable identifiers, fix label/htmlFor association, add
role+onKeyDown to click-intercepting div, and convert anchor to button
in settings sidebar nav.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Refactor SessionTurn into discriminated union (UserTurn, AssistantTurn, ToolTurn)
using oneOf + discriminator so invalid states are unrepresentable
- Add format: date-time to all timestamp fields for proper codegen types
- Rename CreateSessionRequest.prompt to .content for consistency with SendMessageRequest
- Change sendSessionMessage from 200 to 202 (async processing via SSE)
- Extract inline response to SendMessageResponse schema
- Add updated_at to SessionListItem for sort-by-activity support
- Extract SessionId parameter to components/parameters (DRY)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add id, is_error, duration_ms to ToolUse; rename args to input
- Add created_at/updated_at timestamps to session schemas; replace time/date display strings
- Add descriptions and examples to all Sessions API fields and endpoints
- Flatten List Sessions response from grouped SessionGroup[] to SessionListItem[]
- Move date grouping (Today/Yesterday/etc.) to React client via groupSessionsByDate()
- Symlink docs/api-reference/arc-api.yaml to canonical openapi/arc-api.yaml
- Update React ToolRow components with duration display and error styling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a FeatureFlags config section with a session_sandboxes boolean
(default false) to both the Rust server config and web app config.
Gate the project/branch picker UI behind this flag. Set it to false
in the Docker demo config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adapt session detail and sidebar to the new schema: use created_at/
updated_at instead of repo/time, display relative timestamps via a new
timeAgo() helper, and remove repo badges from the UI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the server-level `--demo` flag with per-request demo dispatch.
The Rust API builds both a demo and real router; incoming requests with
the `X-Arc-Demo: 1` header hit the demo router (auth disabled, static
data), all others hit the real router with normal auth.
The React web app gets a beaker icon toggle in the top nav bar (next to
the theme toggle) that sets an `arc-demo` cookie. Loaders read the
cookie to decide whether to send the `X-Arc-Demo: 1` header to the API.
The `ARC_DEMO=1` env var still works as a default when no cookie is set.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Switch mintlify install from bun to npm with katex version patch
- Add arm64 platform and pull_policy: never to docker-compose.demo.yaml
- Unwrap data envelope in verifications loader response
- Add name-gen script
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
error.message was displayed to users in all environments, while
stack traces were correctly gated behind import.meta.env.DEV.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three routes (run-overview, run-configuration, run-graph) were typing
the stages API response as RunStage[] but the endpoint returns a
paginated wrapper { data, meta }. Destructure .data to get the array.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename the endpoint, schema (RunFiles -> RunCompare), operation ID,
handlers, and frontend route across the full stack.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wrap 4 list endpoints that returned bare arrays in the standard
paginated `{ data, meta: { has_more } }` shape so adding real
pagination later is additive rather than a breaking change.
Endpoints: GET /runs/{id}/questions, /runs/{id}/stages,
/runs/{id}/verifications, and /verifications.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multi-stage Dockerfile builds Rust API binary and bundles the web app
and docs into a single image. docker-compose.demo.yaml orchestrates
the three services (api, web, docs) with a shared entrypoint router.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Apply the same page[limit]/page[offset] pagination pattern from
GET /runs to: workflows, workflow runs, retros, sessions, projects,
branches, saved queries, query history, and stage turns.
Each endpoint now returns { data, meta: { has_more } } instead of
a bare array. Includes OpenAPI spec updates, demo handler changes,
regenerated TS client, updated frontend consumers, and a new
pagination conformance test.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduce page[limit]/page[offset] query params and { data, meta: { hasMore } }
response wrapper for the /runs endpoint, establishing the pagination pattern
for all future list endpoints.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Install ring CryptoProvider at CLI startup to prevent rustls panic
- Skip TLS in demo mode so the server uses plain HTTP
- Add ARC_DEMO=1 env var to web app config to bypass GitHub OAuth
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- redirect-home: only check GitHub app config when provider is "github"
- app-shell: hide sign-out button when provider is "tailscale"
- auth-logout: skip session destroy and redirect to /start for Tailscale
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Read Tailscale-User-Login/Name/Profile-Pic headers when web.auth.provider
is "tailscale", checking login against required allowed_usernames list.
Rename githubLogin → login across session/callback/shell for provider
neutrality. Update app-shell loader and auth-login page to handle the
new provider.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automates first-time setup: generates server.toml, Ed25519 JWT keypair,
mTLS CA+server certificates, session secret, and .env file with proper
permissions. Includes pre-flight system dependency checks shared with
doctor, LLM provider API key collection, and optional doctor verification.
Also renames config file from arc.toml to server.toml across the codebase,
and loads ~/.arc/.env before CWD .env for centralized secret management.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the API server is unreachable, the raw "fetch failed" error gives
no indication of what URL was being requested. Wrapping the error
includes the target URL in the message while chaining the original
cause.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The app-shell and redirect-home loaders unconditionally required GitHub
OAuth, which broke demo mode. Now they check the auth provider config
and use a hardcoded demo user when auth is disabled.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The sub claim was set to https://api.github.com/user/{id} (numeric ID),
but the API-side username extractor splits on '/' expecting a login name.
Use https://github.com/{login} so the extracted segment matches the
allowed_usernames config.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The JWT now includes a `sub` claim containing the authenticated user's
GitHub profile URL (e.g. https://github.com/brynary), enabling the
backend to identify which user is making each request.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move auth config under [web.auth] in arc.toml to group web-specific
settings together. Add WebConfig with url field (default localhost:5173).
Add `arc doctor` command with checks for config, API, web, LLM providers,
Brave Search, sandbox, and GitHub App. Extract Provider::api_key_env_vars
and has_api_key to deduplicate validation logic.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Some deployment environments (e.g. container orchestrators) make it
easier to pass secrets as single-line base64 strings rather than
multi-line PEM. Both env vars now auto-detect the format: if the value
starts with "-----" it's treated as raw PEM, otherwise base64-decoded.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add reloadAppConfig() so setup-callback refreshes the in-memory config
after writing TOML, fixing a bug where the login redirect would fail.
Export ARC_CONFIG_PATH to eliminate duplicated path construction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Non-secret config (app_id, client_id) now lives in [git] section of
~/.arc/arc.toml. Secrets remain in .env. Setup callback writes
non-secrets to TOML and secrets to .env.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Better reflects domain semantics: the config describes a workflow run,
and the free-text field is the run's goal, not a generic "task".
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ARC_INSECURE_DISABLE_AUTHENTICATION and ARC_API_BASE_URL env vars
with [auth] and [api] sections in ~/.arc/arc.toml. Only secrets
(ARC_JWT_PUBLIC_KEY, ARC_JWT_PRIVATE_KEY) remain as env vars.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace cookie-based sessions with SQLite-backed storage using
better-sqlite3 and React Router's createSessionStorage. Sessions are
now stored in ~/.arc/arc-web.db with a session ID cookie, enabling
larger payloads and server-side revocation.
- Add db.server.ts (lazy singleton, WAL mode, web_sessions table)
- Add session-storage.server.ts (CRUD ops, probabilistic cleanup)
- Fetch primary verified email from /user/emails during OAuth
- Add emails:read to GitHub App manifest default_permissions
- Expand session data: userUrl, githubId, githubNodeId, email
- Default ARC_API_BASE_URL to localhost:3000
- Whitelist better-sqlite3 in trustedDependencies
- Externalize better-sqlite3 from Vite SSR bundling
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Write the private key as base64 to avoid multiline quoting issues.
Add getGitHubAppPrivateKey() that accepts both raw PEM and base64.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shared layout for setup, login, and callback pages with consistent
styling. Add GitHub mark icon to action buttons. Document dev server
commands in CLAUDE.md.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set env vars on process.env at runtime after writing .env, then redirect
to /auth/login. Removes the success UI telling users to restart.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds one-click GitHub App setup via the manifest flow, OAuth login
via Arctic, and cookie-based sessions so the app shell shows the
real authenticated user instead of a hardcoded placeholder.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a new API endpoint for generating sandbox preview URLs (stubbed to
return google.com in demo mode). The Run detail page now shows a Preview
button that POSTs to this endpoint and opens the returned URL in a new tab.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
apiJson was throwing a plain Error on non-ok responses, which React
Router always treated as a 500. Now throws a Response with the actual
status code so API 404s surface as proper 404 error pages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the unstyled error boundary with themed pages: teal gradient
number for 404, coral for 500, centered on the atmospheric background
with action buttons and a collapsible stack trace in dev mode.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Expand the OpenAPI spec from 11 to 39 endpoints covering Runs, Workflows,
Verifications, Retros, Sessions, Insights, Settings, and Projects with ~45
schemas. Add `--demo` flag to `arc serve` that serves static demo data for
all endpoints (auth disabled, read-only). Non-demo mode returns 501 for new
endpoints while existing run handlers continue working.
Regenerate the TypeScript API client and add `apiJson` helper. Wire all 19
React route files with server-side loaders that fetch from the API and map
snake_case responses to camelCase UI types. Mock data kept as fallback.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- routes/pipelines.tsx → routes/runs.tsx, component Pipelines → Runs
- Update route config to point to runs.tsx
- Retro.pipeline_name → workflow_name in data and all display components
- Table header "Pipeline" → "Workflow" in retros list
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a sandboxId field to RunItem and a Terminal dropdown on the run
detail page with "Web Terminal" (links to Daytona proxy) and
"Connect with SSH" options. Uses existing Headless UI Menu pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a global CSS base rule for interactive elements (buttons, links,
selects, summary, ARIA roles) and add cursor-pointer to clickable
table rows. Remove now-redundant per-element cursor-pointer classes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds /verifications/:slug route with detail page showing control
description, stat cards, evaluation history, recent runs, checks/examples,
and sibling navigation. Makes verification catalog rows fully clickable.
Fixes dark mode hydration mismatch with suppressHydrationWarning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace openapi-typescript types-only output with a full TypeScript Axios
client generated by openapi-generator-cli. The generated code is committed
so IDE support works without running codegen. arc-web consumes the client
via bun workspaces.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Create openapi/arc-api.yaml as source of truth for all API endpoints
- Add arc-types crate with build.rs using typify to generate Rust structs
from the spec's component schemas
- Refactor server.rs to use generated types instead of hand-written ones
- Add route coverage conformance test validating router matches spec
- Add openapi-typescript to arc-web for TypeScript type generation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The existing gradient logo (#c4dede-#495669) was designed for dark
backgrounds. Adds logotype-light.svg with the same paths but a
deeper gradient (#2a6b6b-#1c2a3a) for better contrast on white,
and swaps the src based on the current theme.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The .light CSS variable overrides were defined before the :root dark
defaults, so equal-specificity source-order caused the dark values to
always win. Move .light overrides after each :root block so they
correctly take effect.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>