Commit graph

11 commits

Author SHA1 Message Date
Bryan Helmkamp
3a2e91a123 Fix react-doctor warnings: remove dead code, fix keys and accessibility (92→99)
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>
2026-03-06 09:40:20 -05:00
Bryan Helmkamp
b601df47e5 Per-request demo mode with UI toggle
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>
2026-03-06 07:30:23 -05:00
Bryan Helmkamp
71f7af267a Add URL context to API fetch errors for easier debugging
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>
2026-03-03 21:41:35 -05:00
Bryan Helmkamp
859da7d035 Add user identity (sub claim) to JWT for arc-web → arc-api auth
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>
2026-03-03 15:38:03 -05:00
Bryan Helmkamp
d5b98af6d1 Support base64-encoded PEM for ARC_JWT_PUBLIC_KEY and ARC_JWT_PRIVATE_KEY
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>
2026-03-03 14:39:49 -05:00
Bryan Helmkamp
1cebe29fad Move auth and API config from env vars to TOML (~/.arc/arc.toml)
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>
2026-03-02 22:49:04 -05:00
Bryan Helmkamp
1fd9a8ebfe SQLite-backed sessions with GitHub email and app manifest fix
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>
2026-03-02 21:05:59 -05:00
Bryan Helmkamp
79d97ebb5c Fix stale labels, grammar, and comments from sandbox rename
- Fix display label `image:` → `name:` for SnapshotPulling/SnapshotPulled
  in format_event_detail
- Fix grammar: "an Sandbox" → "a Sandbox" in README and parallel.rs
- Fix typo: "sandboxs" → "sandboxes" in parallel.rs
- Update remaining "execution environment" comments to "sandbox"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 11:43:34 -05:00
Bryan Helmkamp
e938d3395a Throw Response from apiJson so API 404s render as 404 pages
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>
2026-03-02 11:05:34 -05:00
Bryan Helmkamp
49364b0843 Add demo API server and wire React app to fetch from API
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>
2026-03-02 09:39:53 -05:00
Bryan Helmkamp
6d869aa8da Add asymmetric JWT service-to-service auth between arc-web and arc-attractor
Ed25519 asymmetric JWT: arc-web signs with private key, arc-attractor verifies
with public key. Adds AuthenticatedService axum extractor to all routes, jose
dependency for TypeScript signing, and key generation script.

Startup behavior: ARC_JWT_PUBLIC_KEY set → enforce JWT auth; not set +
ARC_INSECURE_DISABLE_AUTHENTICATION=true → allow unauthenticated; neither →
refuse to start with clear error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 18:05:49 -05:00