Skip to content

chore: sync develop with main (symbol-table build fixes from #151, #152)#153

Closed
dvcdsys wants to merge 15 commits into
developfrom
main
Closed

chore: sync develop with main (symbol-table build fixes from #151, #152)#153
dvcdsys wants to merge 15 commits into
developfrom
main

Conversation

@dvcdsys

@dvcdsys dvcdsys commented Jul 19, 2026

Copy link
Copy Markdown
Owner

Carries the two symbol-table build changes from main into develop so both
branches are identical again:

With this merged, git diff develop main is empty. Merging this also
triggers prerelease-cli.yml (it modifies that workflow), so the floating
cli/develop build will be the first artifact produced with the symbol
table kept — a live validation before tagging a stable release.

🤖 Generated with Claude Code

dvcdsys and others added 15 commits July 2, 2026 17:25
release: develop → main (dependency & security hardening)
release: develop → main (watch manage TUI, workspace CLI verbs, llama b9982)
…t of the box

The CPU image (server/Dockerfile) booted and served symbol/keyword search but
every semantic query failed. Two causes: the final stage never bundled
llama-server (the "Embeddings land in Phase 3" TODO was never done), and its
base distroless/static-debian12 has no glibc to run the dynamically-linked
binary anyway. A fresh cix-models named volume also mounted root-owned, so the
first-boot GGUF download died with "mkdir /data/models: permission denied".
Only the CUDA image — and thus prod — ever worked.

Mirror the proven CUDA pattern:
- new pinned llama-source stage FROM ghcr.io/ggml-org/llama.cpp:server (the CPU
  multi-arch index, amd64+arm64) -> COPY /app/llama-server + /app/*.so*
- base distroless/static-debian12 -> distroless/cc-debian13:nonroot, verified
  to ship every system lib llama-server links (libgomp/libssl/libcrypto/
  libstdc++/libgcc_s) + ca-certificates, keeping the nonroot uid 65532
- set CIX_LLAMA_BIN_DIR=/app, CIX_N_GPU_LAYERS=0, LD_LIBRARY_PATH=/app,
  CIX_GGUF_CACHE_DIR=/data/models
- pre-create /data/models in the builder stage so the separate cix-models
  named volume inherits 65532 ownership

Also pre-own /data/models in Dockerfile.cuda for the docker-compose.cuda.yml
separate-volume case (inert for the single-volume prod portainer stack).

Verified end-to-end: the multi-arch build (amd64+arm64) is green; the arm64
image boots, downloads the 146 MB GGUF into a fresh cix-models volume, loads it
in llama-server, and two semantic searches return the right files across Go and
Python.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rom release notes

The Python backend was archived 2026-04-24; every server release since has still
carried a "See doc/MIGRATION_FROM_PYTHON.md if upgrading from the Python backend"
line in its GitHub release body via this template. Remove it — the Docker-images
table plus the auto-generated changelog are the whole body now.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The marketing site is the one surface a release never touches, so it silently
keeps showing the old version — site/src/shared/versions.js still said 0.12.2
the moment server/v0.12.3 shipped. ci-site.yml hard-fails on a stale
versions.js, but it only triggers on site/** changes, so a server release
never runs it.

Add a site-version job that compares versions.js against the version being
released and emits a warning plus a step summary when they differ.
Non-blocking on purpose: versions.js may only name an already-tagged version,
so the bump legitimately lands after this tag exists — the warning is the
reminder to go do it, not a failure. Guards on the file's existence, since
site/ has not merged to main yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Release: marketing site to main
… the CLI

The CLI was never scanned by govulncheck — security.yml only ever gated the
server — and its released binaries take their stdlib from the toolchain pinned
in cli/go.mod. That directive still said `go 1.25.0`, so the published
cix v0.10.0 binaries were built on go1.25.0 and carry 16 reachable standard
library advisories, including GO-2026-5856 (Encrypted Client Hello privacy
leak in crypto/tls), GO-2026-5037/4947/4946 (crypto/x509), GO-2026-4918
(net/http) and GO-2026-4971 (net). Reachability is real, not theoretical:
client.Health -> http.Client.Do -> tls.Conn.HandshakeContext, and
SendFilesStreaming -> io.ReadAll -> textproto.Reader.ReadMIMEHeader.

Bump the directive to 1.25.12, which is the highest fix version among the 16,
and add a govulncheck (cli) job mirroring the server one so an unscanned CLI
cannot ship again.

Verified locally: builds clean, `go test ./...` passes, and govulncheck goes
from "affected by 16 vulnerabilities" to "No vulnerabilities found".

Note: the shipped SERVER images are not affected by GO-2026-5856 — they are
built on golang:1.26-alpine (go1.26.5), and 1.26.5 is the fix version for the
1.26 line.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
cli/go.mod declared `module github.com/anthropics/code-index/cli`, which is not
where this repository lives. Both CLAUDE.md and cli/README.md already documented
the correct path (github.com/dvcdsys/code-index/cli) — only the code disagreed,
so this is a leftover, not a deliberate choice. A module path that does not
match the repo URL also means `go install github.com/dvcdsys/code-index/cli@latest`
could never have worked.

Rewrites the module declaration and all 43 internal import paths, plus the two
places the old path was hard-coded outside Go source:
  - cli/Makefile
  - the `-X '<module>/cmd.Version=...'` ldflags in release-cli.yml and
    prerelease-cli.yml — these MUST move with the module path or version
    injection silently stops working and the binary reports its default version.

Verified: build, vet and the full test suite pass, and a binary built with the
release ldflags reports its injected version correctly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…6.5)

The go directive drove CI's govulncheck (`go-version-file: server/go.mod`) but
NOT the released artifact: server/Dockerfile builds on `golang:1.26-alpine`.
CI was therefore scanning go1.25.12's standard library while the published
images shipped go1.26.5 — a green govulncheck did not prove the image was
clean, and a red one did not prove it was vulnerable. That gap is exactly what
made GO-2026-5856 confusing to triage: CI failed on 1.25.11 while the shipped
image, on 1.26.5, was already patched (the advisory is fixed in BOTH 1.25.12
and 1.26.5).

Point the directive at the line the Dockerfile builds with, so the scan and the
artifact agree. No change to the shipped binary — it was already compiled by
golang:1.26-alpine.

Verified at go1.26.5: build, vet, the full server test suite, and govulncheck
("affected by 0 vulnerabilities").

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Follows the two releases just cut. Policy is site-follows-release: versions.js
may only name a version that is already tagged, so the bump lands after the
tags exist — which is what the (non-blocking) site-version job in
release-server.yml warned about on the v0.12.4 run: "released=0.12.4
site=0.12.3".

ci-site.yml's version gate now matches the newest tags again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The CLI resolved golang.org/x/crypto to v0.52.0 while the server requires
v0.54.0. Pure hygiene — it does NOT change the module's vulnerability status:
govulncheck reports 0 before and after.

In particular this does not address GO-2026-5932 (x/crypto/openpgp is
unmaintained and unsafe by design) and nothing can, because that advisory has
no fixed version — the upstream remedy is "do not use the package". It is also
a non-issue here: openpgp is not part of this binary at all. `go list -deps`
does not include it, the released binary contains zero references to it, and
source-mode govulncheck reports 0. It only surfaces when scanning the released
binary in -mode=binary: release builds are stripped (-s -w), so govulncheck
cannot do symbol analysis and falls back to module-level reporting — visible in
its output as package wildcards (`openpgp/armor/*`) rather than real called
symbols. x/crypto is pulled in solely for sha3, via go-playground/validator.

Also carries the x/sys and x/text bumps that came with the upgrade.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ep -w)

Stripped binaries (-s) force govulncheck -mode=binary into module-level
fallback: it cannot see which packages are actually linked, so it flags
every advisory on every required module — including GO-2026-5932
(x/crypto/openpgp), a package this binary does not contain at all.

With the symbol table present govulncheck does real symbol-level
analysis. Verified locally on the current cli/ tree:

  -s -w : 13.5 MB, binary scan reports "affected by 1 vulnerability"
  -w    : 15.0 MB, binary scan reports 0 (openpgp correctly unreachable)
  none  : 20.0 MB, binary scan reports 0

-w (DWARF stripping) stays, so the size cost is ~+11%, not +48%.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…p -w)

Companion to #151, which does the same for the CLI. Both server images still
build with `-ldflags "-s -w"`, so the shipped cix-server binary has no symbol
table and any binary-mode vulnerability scan of the published image degrades to
module-level reporting — flagging advisories for packages that are not linked
at all. Measured on this binary, the same false positive #151 removes from the
CLI is present here:

  -s -w :  24.0 MB,    143 symbols  -> "affected by 1 vulnerability from 1 module"
  -w    :  25.7 MB, 26 377 symbols  -> "No vulnerabilities found"

Cost is +6.8% on the binary (~1.7 MB) inside images of ~172 MB (CPU) and
~1.5 GB (CUDA), so it is noise at the image level. `-w` still drops DWARF.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
build(cli): keep the Go symbol table in release binaries (drop -s, keep -w)
build(server): keep the Go symbol table in image builds (drop -s, keep -w)
Comment thread cli/go.mod
@@ -1,6 +1,6 @@
module github.com/anthropics/code-index/cli
module github.com/dvcdsys/code-index/cli
@dvcdsys

dvcdsys commented Jul 19, 2026

Copy link
Copy Markdown
Owner Author

Direct main→develop merge conflicts because the branches share content via cherry-picks, not merges. Replacing with a cherry-pick PR, per repo convention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants