Conversation
…icit auth gating doc/openapi.yaml describes all 18 endpoints; oapi-codegen v2 generates typed request/response models and a chi-server ServerInterface, committed in internal/httpapi/openapi/. Handlers were rewritten as methods on a new Server struct that implements the generated interface — wire format is byte-identical to the previous closure-based handlers. NDJSON streaming on POST /index/files keeps both content-types under one spec entry with Accept-header negotiation; the embedded spec is served at /openapi.json (no file duplication — pulled from openapi.GetSpecJSON). Swagger UI 5.18.2 is embedded via embed.FS and served at /docs (public, same-origin). Makefile gains openapi-gen, openapi-check, swagger-ui-fetch targets. CI can run openapi-check to catch drift between spec and generated code. Auth gating made explicit: the implicit empty-API-key bypass is removed. config.Validate now refuses to start with CIX_API_KEY="" unless CIX_AUTH_DISABLED=true is set. The middleware panics on empty-key construction as a defense-in-depth check; the router wires it only when auth is not explicitly disabled. Production Docker images are unaffected (they always set CIX_API_KEY); local dev gets a loud WARN and a clear opt-out flag instead of silent open auth. Local-dev defaults for SQLitePath / ChromaPersistDir resolve to ~/.cix/data/... so make run works without editing .env. Container images explicitly override these to /data/... — no production behaviour change. The CPU Dockerfile gains the same ENV CIX_SQLITE_PATH / CIX_CHROMA_PERSIST_DIR that Dockerfile.cuda already had, so both images share one data layout. .gitignore exception added for server/internal/httpapi/docs/ so the embedded Swagger UI bundle ships with the source tree (top-level docs/ remains gitignored per CLAUDE.md). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The CLI's defer-cleanup on early exit (Ctrl-C, network drop) calls
POST /index/cancel to free the per-project run lock. Gating cancel
behind the admin role would strand viewer-owned runs until the 1-hour
TTL elapses — worse UX than the theoretical DoS we'd be preventing.
PATCH /projects/{path} and DELETE /projects/{path} stay admin-only;
those are genuinely destructive. If we ever need owner-scoped cancel,
key off projects.indexing_run.started_by_user_id in a follow-up.
- Drop mustBeAdmin gate from IndexCancel; add comment explaining why.
- Update OpenAPI summary/description; drop 403 from cancel responses.
- Regenerate openapi.gen.go.
- Test: TestIndexCancel_AnyAuthenticatedUser pins the new policy
(viewer cancels their own project → 200, not 403).
- Trim cancel from TestProjectMutations_AdminOnly cases.
- Doc: SECURITY_DEPLOYMENT.md "what the server does NOT do" section
now lists PATCH/DELETE (not PATCH/DELETE/index-cancel) as admin-only.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CI: Server / test was failing on `go vet` because //go:embed all:dist in dashboard/embed.go found no matching files — the .gitkeep marker that .gitignore promises to preserve was never actually committable: a stray bare `dist/` rule in the Python section matched any `dist/` directory at any depth, and Git can't re-include a file under a broadly-excluded parent. Narrow the bare rule to /dist/ (root only) and commit the marker so a fresh clone passes the test suite without first building the React bundle. CodeQL go/uncontrolled-allocation-size flagged server.go:419 — `make([]openapi.FileResultItem, 0, limit)` where limit derives from a user-supplied JSON field. Cap with a new clampLimit helper at maxResultLimit = 1000 — well above any legit dashboard / CLI page size, well below any value that would balloon the slice or stall the SQL LIMIT clause. Apply to the four other endpoints that derive `limit` from `body.Limit` for defense in depth (search, files, references, definitions, symbols). derefIntOrDefault keeps the old contract (still used for non-capacity metadata fields like body.TotalFilesDiscovered). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…nale Two-part change in response to PR review: 1) Lengthen the random portion of issued keys from 24 → 32 bytes, so the on-the-wire token is now `cix_<43-char-base64url>` (47 chars total) instead of `cix_<32-char>` (36 chars). Matches GitHub-class PAT verbosity and pushes the entropy floor from 192 → 256 bits. Existing keys keep working — the lookup column is the hash, not the length. 2) Expand the comment on hashKey() to spell out why SHA-256 is the correct primitive for hashing a server-issued, high-entropy token and explicitly refute the CodeQL `go/insufficient-password-hash` alert. Adding a slow KDF (bcrypt/argon2/PBKDF2) would tax every authenticated request 25–250 ms without raising the security floor a single bit, because brute-forcing the hash at 256-bit pre-image entropy is computationally indistinguishable from brute-forcing the underlying random bytes. Same pattern GitHub / Stripe / AWS use for their machine-issued tokens. Test asserting body length updated 32 → 43 to match the new size. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Both Dockerfile and Dockerfile.cuda have `COPY --from=openapi openapi.yaml /spec/openapi.yaml` in the dashboard build stage (added when the dashboard started consuming the OpenAPI spec for type generation). The release workflow's docker/build-push-action calls were missing the corresponding `build-contexts: openapi=doc` parameter, so the next `server/v*` tag push (or workflow_dispatch) would fail at the dashboard stage with "stage openapi not found". `make docker-build-cuda-dev` works because it passes `--build-context openapi=$(ROOT)/../doc` directly. This brings CI to parity. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Full web dashboard at `/dashboard`, first-class auth, admin-side runtime control of the embedding sidecar, and a security hardening pass. Spans 9 commits (PR-A through PR-E + two security iterations + cancel-gate refinement).
Highlights
Breaking changes
🚨 Read before upgrading:
CLI compatibility
`cli/v0.5.0` is fully compatible with `server/v0.5.0`. No CLI tag bump needed.
Release order
Test plan
🤖 Generated with Claude Code