8eabe191d2
Five field reports in the 24 hours after v0.10.0 all pointed at the same thing: gates that were right in principle refused real, ordinary setups, and then failed to say why. Per the consolidated strictness decision, each gate keeps the protection that matters and drops the part that was refusing legitimate users — and every refusal now names what it refused and how to proceed. **Daemon image gate: npx and every ephemeral install path (#1539, #1383).** The admission check treated "the peer's image hashes differently" and "the peer's image cannot be examined at all" as one failure. The second is what `npx codebase-memory-mcp` always produces (ephemeral cache path, unfingerprintable), so every npx-invoked client was rejected — and, because the client never reported it, agents saw a transport that closed mid-handshake with zero bytes on stdout. Reported by @wassolles with the admission path already read and the fix space mapped. An unverifiable image is now admitted: the rendezvous HELLO immediately above it has already proven semantic version, build fingerprint, and protocol/store/ feature ABI, and the image check was trading that real proof for an unavailable one. It logs daemon.client_image_unverifiable_admitted so the weaker check is never invisible. A fingerprint MISMATCH — the tamper case the gate exists for — still rejects hard. Separate test seams keep the two modes testable apart. **Client bootstrap failures are no longer silent (#1539).** An MCP client that cannot reach the daemon now emits a JSON-RPC error on stdout naming the reason, plus the same text on stderr. Previously the reason sat in bootstrap_result.message and the process exited having written nothing at all. **POSIX activation: group-writable ancestors (#1535, discussion #1526).** activation_directory_secure required no group or other write bit on the install directory AND every ancestor. WSL2 ships ~ and ~/.local at 0775, as do several distro skeletons and any site using a shared primary group, so install.sh failed for a large fraction of Linux users — reporting a policy refusal as "activation transaction I/O failed", which sent reporters after disk errors and filesystem types. Root-caused by @AmirF194 in a clean ubuntu container; @shochdoerfer and @iandol confirmed independently. World-writable ancestors are still refused (any local user could swap a path component mid-transaction). Group-writable ancestors are now warned about and admitted. The LEAF directory stays strictly owner-private — that is where the binary is published, and group write there would let another account replace the executable between validation and exec. Refusals now name the directory, its mode, and which rule refused. **The obsolete ui/standard chooser (#1538, from discussion #1526).** v0.10.0 consolidated to one archive per platform with the UI always embedded, but `update` still offered a variant choice: "ui" could only 404, and "standard" quietly WAS the UI build. Reported by @iandol upgrading 0.9.0 -> 0.10.0. The chooser, its --standard/--ui flags, and the ui- URL plumbing are removed, along with the CBM_VARIANT=ui remnant in the npm installer. Already-released 0.9.x binaries cannot be fixed retroactively, so the release workflow now publishes byte-identical ui-*-named alias assets — their updaters work again with no user action. The aliases are uploaded AFTER the VirusTotal gate: they are the same bytes as archives it already cleared, and uploading them earlier would duplicate every object in the scan set and the provenance manifest. **macOS install noise and attribution (#1537).** install.sh silenced the "No such xattr: com.apple.quarantine" line, which is what happens when a curl-downloaded archive carries no quarantine attribute — harmless, and it became the title of a bug report about an unrelated failure. The session-stop refusal now points at `daemon status` to list the client processes actually holding the daemon, instead of asserting sessions exist and leaving the reader to guess. Reported by @listepo. **Riders.** hatchling is pinned in pkg/pypi (an unpinned backend resolved fresh inside `python -m build` is what emitted Metadata-Version 2.5 and broke the v0.10.1 publish); SECURITY.md's supported-versions table moves to 0.10.x. Tests: separate seams for unverifiable vs mismatched peer images with a test per outcome; activation refusal must name directory + mode + rule; a group-writable ancestor must stage successfully. The update tests drop the flag that no longer exists. Verified against each reporter's environment shape. **Open security alerts (all three, OSSF Scorecard).** - HIGH, binary artifact: an 8.8 MB compiled Go ELF wrapper had been committed at pkg/go/codebase-memory-mcp by accident. Removed, and both it and its .exe sibling are gitignored so `go build` in that directory cannot repeat it. - HIGH, GHSA-2v37-7h3g-55p8: nanoid < 3.3.17 loops forever when a custom generator is called with size 0. It reaches us transitively (postcss -> vite), so it is pinned through the existing graph-ui overrides block rather than promoted to a direct dependency; the lockfile resolves 3.3.18. - MEDIUM, unpinned pip command: the publish step installed build/twine by version only, leaving the whole transitive graph resolved at run time. pkg/pypi/requirements-publish.txt now hash-pins the complete toolchain (316 hashes), generated on a linux/amd64 python:3.12 image so the wheels match what ubuntu-latest resolves, and the step runs pip with --require-hashes. Verified by installing from it in that same image. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
89 lines
1.8 KiB
Plaintext
89 lines
1.8 KiB
Plaintext
# Binaries
|
|
code-graph-mcp
|
|
/codebase-memory-mcp
|
|
bin/
|
|
*.exe
|
|
*.dll
|
|
*.so
|
|
*.dylib
|
|
|
|
# Test artifacts
|
|
*.test
|
|
*.out
|
|
coverage.txt
|
|
|
|
# Test fixture temp dirs (created by C test suite in CWD instead of /tmp/)
|
|
cbm_*/
|
|
cli-*/
|
|
|
|
# IDE
|
|
.idea/
|
|
.vscode/
|
|
*.swp
|
|
*.swo
|
|
|
|
# OS
|
|
.DS_Store
|
|
Thumbs.db
|
|
|
|
# Database files (local cache)
|
|
*.db
|
|
*.db-wal
|
|
*.db-shm
|
|
|
|
# MCP config (user-local, generated by install command)
|
|
.mcp.json
|
|
|
|
# MCP Registry auth tokens
|
|
.mcpregistry_*
|
|
|
|
# Local project memory (Claude Code auto-memory)
|
|
memory/
|
|
reference/
|
|
|
|
# Local-only scratch / session notes (never pushed)
|
|
private/
|
|
|
|
# Build artifacts
|
|
build/
|
|
node_modules/
|
|
graph-ui/dist/
|
|
# Generated by scripts/embed-frontend.sh into the source tree (the linker needs
|
|
# it beside the other UI sources). Removed by scripts/clean.sh; never committed.
|
|
src/ui/embedded_assets.c
|
|
|
|
# Generated reports
|
|
BENCHMARK_REPORT.md
|
|
TEST_PLAN.md
|
|
CHANGELOG.md
|
|
|
|
# Soak test output
|
|
soak-results/
|
|
|
|
# LSP originality-check reference cache (scripts/check-lsp-originality.sh)
|
|
.lsp-refs/
|
|
|
|
# Local npm cache
|
|
graph-ui/.npm-cache-local/
|
|
|
|
# Python bytecode from tests/windows/ harness
|
|
__pycache__/
|
|
*.pyc
|
|
|
|
# Local soak-leg outputs (uploaded as CI artifacts, never committed)
|
|
soak-results/
|
|
soak-results-query-leak/
|
|
# ...and ANY ad-hoc run directory at the repo root. The two exact names above did
|
|
# not match hand-named runs, so 13 soak directories and 4 memlab files (78 files
|
|
# of logs and CSVs) were committed to main by accident in 7808eee. Root-anchored
|
|
# so nothing under scripts/ or tests/ is affected — scripts/soak-legs.sh and
|
|
# scripts/soak-test.sh stay tracked.
|
|
/soak*/
|
|
/memlab-*
|
|
|
|
# Compiled Go wrapper binary. `go build` in pkg/go drops the executable beside
|
|
# its sources; one was committed by accident (8.8 MB ELF, flagged by OSSF
|
|
# Scorecard as a binary artifact in source). Source only, never the build.
|
|
/pkg/go/codebase-memory-mcp
|
|
/pkg/go/codebase-memory-mcp.exe
|