Skip to content

fix(ci+sec): idempotent relationship upsert, I2 line drift, inline CWE-22 sanitisers#53

Open
cdeust wants to merge 5 commits into
mainfrom
fix/ci-failures-and-codeql-sanitisers
Open

fix(ci+sec): idempotent relationship upsert, I2 line drift, inline CWE-22 sanitisers#53
cdeust wants to merge 5 commits into
mainfrom
fix/ci-failures-and-codeql-sanitisers

Conversation

@cdeust

@cdeust cdeust commented Jun 8, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes both CI Test-job failures and the open CodeQL/Dependabot security alerts on the default branch.

CI failures (both verified against pgvector/pgvector:pg17)

  • insert_relationship (pg_store_relationships.py) — made the upsert idempotent with ON CONFLICT (source, target, type) DO UPDATE. It was raising UniqueViolation on uq_relationships_directed during incremental re-ingest.
  • I2 canonical-writer allow-list (test_I2_canonical_writer.py) — line pins drifted: 477→543, 537→603.

Security

  • 4 CodeQL path-injection (CWE-22) alerts — refactored to a sanitise-and-return _contained_resolved() helper in http_file_diff.py and http_standalone_trace.py, with an inline is_relative_to containment barrier.
  • 1 CodeQL weak-hash alert — stale (the usedforsecurity=False fix landed after the alert was raised; auto-clears). No change.
  • 3 Dependabot mediums — transitive-only (starlette/aiohttp not imported); a fresh resolve already patches them. No change.

Test plan

  • codebase-alteration 5/5, invariants+store 57/57, server helpers 20/20 — all green
  • ruff clean

🤖 Generated with Claude Code

cdeust and others added 5 commits June 9, 2026 00:30
…E-22 sanitisers

Two CI Test-job failures + 4 CodeQL path-injection alerts.

CI:
- insert_relationship: plain INSERT collided with uq_relationships_directed
  on incremental codebase re-analysis (defines/imports/extends edges replay).
  Now ON CONFLICT (source,target,type) DO UPDATE — keep strongest weight/
  confidence, refresh last_reinforced — mirroring staging_resolve_sink.
- test_I2_canonical_writer: allow-list line numbers drifted as code was added
  above the two canonical heat_base writers (477→543 bump_heat_raw,
  537→603 update_memories_heat_batch). Updated the pins.

Security (CWE-22):
- http_file_diff / http_standalone_trace: refactor _under_allowed_root into
  sanitise-and-return _contained_resolved(p) -> Path|None. Callers now use the
  validated resolved path for is_dir()/git rev-parse, so the is_relative_to
  barrier sits inline on the tainted→sink dataflow CodeQL tracks. Behaviour
  unchanged (boolean wrapper retained); 20 server-helper tests green.

Verified against pgvector/pgvector:pg17: codebase-alteration 5/5, invariants
+ store 57/57, server helpers 20/20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eadless authoring

The CI Test job hung ~1h on every run since 2026-05-25 (commit 148d5a1) —
pre-existing, not introduced by this branch. Two root causes in the
consolidate → wiki-maintenance path, both surfaced via faulthandler.

1. Self-deadlock (the CI hang). `_run_purge_axis` ran inside the async
   consolidate handler yet bridged to wiki_purge via
   `asyncio.run_coroutine_threadsafe(coro, running_loop).result(timeout=120)`.
   It scheduled the coroutine on the *same* loop whose thread the
   synchronous caller had already blocked, so the coroutine could never
   run and each axis stalled to the 120s timeout. Fix: make the chain
   async end-to-end (`_run_purge_axis`, `run_wiki_maintenance` →
   `async def`; consolidate awaits via new `_atimed`). The purge now runs
   on its owning loop with the correctly-bound psycopg async pool. The
   dead identical-branch loop detection in `_invoke_wiki_purge` is removed.

2. Subprocess storm (machine-crash family). Headless authoring spawned up
   to ~38 `claude -p` subprocesses (30 anchor + 8 file-doc) at 180s each,
   synchronously on the event loop — wedging dev machines and the local
   test suite (claude is on PATH there; on CI it FileNotFounds fast, which
   is why CI hung only on cause 1). Gated behind `CORTEX_HEADLESS_AUTHORING`
   (default OFF) until per-cycle load balancing lands.

tests_py/handlers/test_consolidate.py: 9/9 pass in 6m (was hanging ~1h).
ruff clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…vendored dirs in wiki-drift walk

CI Test (Python 3.11) hung because 41 handlers each constructed their own
PgMemoryStore, leaking 60+ PG connections (batch timeout 1800s = 30-min stall).
A second hang came from wiki-drift walking a stray 154M vendored deps/ tree.

- infrastructure/memory_store.py: add process-wide get_shared_store()/
  reset_shared_store() cache keyed by backend/url/dim; extract _construct_store().
- handlers/*.py (41): route _get_store() through get_shared_store(...); drop
  4 dead MemoryStore imports.
- tests_py/conftest.py: _reset_all_singletons calls reset_shared_store() and
  nulls handler caches via package iteration.
- core/wiki_drift.py, core/wiki_coverage.py: prune _SKIP_DIRECTORIES
  (deps, site-packages) in _file_exists_under walk.

Verified: 37 handlers -> 1 store; PG conns peak 16 (was 60+); back to 1 at
teardown. pytest tests_py/handlers/ = 378 passed, no hang.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The mechanical pool-leak edit (memory_store.py get_shared_store) and the
_SKIP_DIRECTORIES prune (wiki_drift._file_exists_under) left a call and a
comprehension that now fit on one line; ruff format --check flagged both,
failing CI Lint. Pure whitespace, no behaviour change. Lint was green at
bed6393 — these two are the only regression.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant