Graph Kernel DEP Audit V2
**OpenClaw CompCore — Deep Engineering Posture Assessment** **Version:** 2.0.0 · **Date:** 2026-02-14 **Auditor:** Automated Code Analysis + Live Service Inspection **Codebase:** `core/semantic/cc-graph-kernel/` — ~11,241 lines Rust
Full Public Reader
Graph Kernel DEP Audit V2
OpenClaw CompCore — Deep Engineering Posture Assessment
Version: 2.0.0 · Date: 2026-02-14
Auditor: Automated Code Analysis + Live Service Inspection
Codebase: `core/semantic/cc-graph-kernel/` — ~11,241 lines Rust
---
Executive Summary
The Graph Kernel is a remarkably well-architected provenance engine. It achieves something rare: a Rust service with genuine cryptographic security guarantees enforced at the type level, deterministic behavior verified through golden tests, and a clean separation between its core library (zero I/O) and its service layer (Axum + PostgreSQL). The codebase punches above its weight.
That said, this audit identifies 47 specific findings across 12 dimensions. The most critical: the 291ms latency is entirely addressable (90
Overall Health Score: 7.4 / 10 — Production-viable with clear improvement vectors.
---
Dimension Scores
| # | Dimension | Score | Verdict |
|---|---|---|---|
| 1 | Code Quality | 8/10 | Clean Rust, strong idioms, no unsafe |
| 2 | Architecture | 9/10 | Exceptional separation of concerns |
| 3 | Performance | 5/10 | 291ms latency, all network-caused |
| 4 | Data Model | 7/10 | Solid triple store, normalization gaps |
| 5 | Security | 9/10 | HMAC + type-level enforcement is excellent |
| 6 | Testing | 8/10 | Golden tests, property tests, benchmarks |
| 7 | Documentation | 9/10 | Research paper, architecture doc, inline comments |
| 8 | Dependencies | 7/10 | Clean, some staleness risk |
| 9 | Operational | 7/10 | Health checks present, metrics are log-based only |
| 10 | Scale | 6/10 | Works at current load, limits unclear |
| 11 | Known Bugs | 6/10 | Entity normalization, pagination |
| 12 | Missing Features | 5/10 | No server-side traversal, no streaming, no visualization |
---
1. Code Quality — 8/10
Strengths
- Zero `unsafe` blocks. The entire codebase uses safe Rust exclusively. No raw pointer manipulation, no transmutes, no FFI unsafety.
- `#![warn(missing_docs)]` and `#![warn(clippy::all)]` are set at the crate root (`lib.rs`). Every public item has doc comments. This is discipline most production Rust codebases lack.
- Type-driven design. `TurnId`, `SliceFingerprint`, `GraphSnapshotHash`, `AdmissibilityToken` — each concept gets its own newtype wrapper with domain-specific methods. No stringly-typed APIs.
- Error handling is idiomatic. `thiserror` for domain errors, `Result` propagation throughout. The `SlicerError` enum covers all failure modes with descriptive variants.
- Canonical ordering everywhere. `BTreeMap` over `HashMap`, sorted `Vec<TurnSnapshot>` and `Vec<Edge>`, `Ord` implementations on domain types. This isn't accidental — it's systematic determinism enforcement.
Findings
| ID | Severity | Finding |
|---|---|---|
| CQ-1 | LOW | `TurnSnapshot::new()` takes 11 positional parameters. This is a builder pattern candidate. The `#[allow(clippy::too_many_arguments)]` annotation is a code smell being suppressed rather than addressed. |
| CQ-2 | LOW | `Role::from_str()` and `Phase::from_str()` are custom methods, not `impl FromStr for Role`. Implementing the standard trait would enable `.parse::<Role>()` syntax and improve ergonomics. |
| CQ-3 | LOW | `AdmissibilityToken::verify_hmac()` uses a manual fold for constant-time comparison instead of `subtle::ConstantTimeEq` or `hmac::Mac::verify_slice()`. The current implementation (`fold(true, \|acc, (a, b)\| acc && (a == b))`) may be optimized away by LLVM into a short-circuit comparison. |
| CQ-4 | INFO | `regex_lite::Regex::new()` is called on every request in `normalize_path()` (middleware.rs:52). Should be a `LazyLock<Regex>` or `OnceLock<Regex>`. |
| CQ-5 | INFO | Several `#[allow(deprecated)]` annotations for the `issue_legacy` token path. Consider removing legacy token support entirely since HMAC v2 is the production path. |
Clippy Compliance
The crate compiles cleanly with `#![warn(clippy::all)]`. No clippy suppressions beyond `too_many_arguments`. Static analysis posture is strong.
---
2. Architecture — 9/10
Strengths
- Feature-gated layering is exemplary. The crate compiles three ways:
- `default` — Pure library, zero I/O, no async runtime. Suitable for embedding.
- `postgres` — Adds sqlx + tokio for database access.
- `service` — Full HTTP service with Axum, CORS, tracing.
This means the core slicing logic can be used as a library in other Rust crates without pulling in a web framework. This is the correct way to build a Rust service.
- `GraphStore` trait abstraction. The `async_trait`-based `GraphStore` trait enables clean backend swapping. `InMemoryGraphStore` for tests, `PostgresGraphStore` for production. Adding SQLite would require only implementing this trait.
- Dual-purpose design is cleanly separated. Context slicing (the `slicer` module) and knowledge graph CRUD (the `routes` module) share the same `PostgresGraphStore` but have no coupling between them. They could be split into separate services trivially.
- Atlas subsystem. The atlas module (snapshot → batch slicer → overlap → influence → bundler) is a complete graph analytics pipeline with its own schema version. This is architectural foresight — it enables pre-computed graph structure without coupling to the real-time API.
- Policy registry with hash-stable fingerprints. Policies are immutable once registered, referenced by content hash, and the registry itself has a composite fingerprint. This enables reproducible policy resolution across deployments.
Findings
| ID | Severity | Finding |
|---|---|---|
| AR-1 | MEDIUM | Knowledge graph CRUD handlers in `routes.rs` use raw SQL via `sqlx::query()` with dynamic string formatting for the WHERE clause (`format!("WHERE {}", conditions.join(" AND "))`). While parameterized bind values prevent SQL injection for the values, the condition construction uses string concatenation for column names. This is safe only because the column names come from the code, not user input — but it violates the pattern established by `SliceBoundaryGuard`. |
| AR-2 | MEDIUM | The batch knowledge insert handler (`add_knowledge_batch_handler`) processes triples sequentially within a transaction. There's no streaming or chunked processing — a 10,000 triple batch will hold a single transaction open for the entire duration. |
| AR-3 | LOW | `ServiceState` is generic over `S: GraphStore`, but `routes.rs` hardcodes `type AppState = ServiceState<PostgresGraphStore>`. The generic parameter enables testing but the routes aren't generic — you'd need to refactor routes to test them with `InMemoryGraphStore`. |
| AR-4 | INFO | No rate limiting middleware. The service is exposed on [ip] by default. In a local deployment this is fine; on Cloud Run the load balancer handles rate limiting. But there's no application-level defense against query amplification. |
---
3. Performance — 5/10
The 291ms Problem
This is the single most impactful finding. The benchmark data is unambiguous:
| Component | Contribution |
|---|---|
| Network RTT to Supabase PostgreSQL | ~180–200 ms |
| PostgreSQL query execution | ~5–20 ms |
| TCP connection overhead | ~10–15 ms |
| Rust serialization + JSON | ~1–2 ms |
| Multi-hop per additional hop | +200 ms |
| Projected with local SQLite | 10–30 ms |
The Rust code itself is fast. Serialization is ~1ms. HMAC computation is sub-millisecond. The xxHash64 fingerprinting is sub-microsecond. The problem is entirely architectural: every query crosses the Atlantic (or at minimum a VPC boundary) to reach Supabase.
Connection Pooling
Current configuration:
max_connections: 10
min_connections: 2
connect_timeout: 10s
idle_timeout: 300s
max_lifetime: 1800s
test_before_acquire: trueThe `test_before_acquire: true` setting adds a `SELECT 1` round-trip before every connection acquisition. For a remote database with 200ms RTT, this adds 200ms to the first query on every connection checkout. This should be `false` for local deployments and conditionally set based on `DB_TEST_BEFORE_ACQUIRE` env var.
Findings
| ID | Severity | Finding |
|---|---|---|
| PF-1 | HIGH | No query caching. Identical knowledge graph queries hit PostgreSQL every time. A simple LRU cache (like the one already used for token verification) would eliminate repeated queries. |
| PF-2 | HIGH | Multi-hop requires N HTTP round-trips. A 3-hop traversal = 3 × 291ms = ~874ms. Server-side traversal would reduce this to 1 × 291ms (or 1 × 30ms with local DB). |
| PF-3 | MEDIUM | No prepared statement caching. The knowledge graph query handler builds SQL strings dynamically. sqlx's compile-time checked queries (`sqlx::query!()`) aren't used for the knowledge graph endpoints, only for the graph store. |
| PF-4 | MEDIUM | `test_before_acquire: true` adds unnecessary RTT for warm connections. Should be configurable. |
| PF-5 | LOW | `min_connections: 2` keeps only 2 idle connections warm. Under burst traffic (e.g., an agent querying the graph rapidly), the first few requests will pay connection establishment cost. Consider `min_connections: 5` for production. |
| PF-6 | INFO | No response compression. JSON payloads for large slices (256 turns × ~200 bytes each) could benefit from gzip/brotli via `tower-http::compression`. |
---
4. Data Model — 7/10
Triple Schema
CREATE TABLE knowledge_graph (
id BIGSERIAL PRIMARY KEY,
subject TEXT NOT NULL,
predicate TEXT NOT NULL,
object TEXT NOT NULL,
confidence DOUBLE PRECISION DEFAULT 0.5,
source TEXT DEFAULT 'unknown',
created_at TIMESTAMPTZ DEFAULT NOW(),
UNIQUE(subject, predicate, object)
);Indexes present: `idx_knowledge_subject`, `idx_knowledge_predicate`, `idx_knowledge_confidence`.
Live Data Profile (as of audit)
| Metric | Value |
|---|---|
| Total triples | 3,502 |
| Unique subjects | 221 |
| Unique predicates | 88 |
| Top predicate | `has_file` (810 triples, 23 |
Findings
| ID | Severity | Finding |
|---|---|---|
| DM-1 | HIGH | No entity normalization at the Rust layer. The Python middleware (`entity-normalizer.py`) handles canonicalization of entity names, but the Rust service stores whatever it receives. If a client bypasses the middleware, "Dream Weaver" and "dream-weaver-engine" are distinct entities. Normalization should be enforced at the service level via a `canonicalize_entity()` function called in the route handlers before database writes. |
| DM-2 | MEDIUM | No `object` index. The `object` column has no index, but queries filter on it. A composite index on `(subject, predicate)` and a separate index on `object` would improve relationship queries. |
| DM-3 | MEDIUM | Predicate taxonomy is uncontrolled. 88 unique predicates with no schema validation. `needs_to`, `should`, `wants_to` are semantically overlapping. `has_file` and `has_path` could be unified. There's no predicate registry or ontology. |
| DM-4 | MEDIUM | No `updated_at` column. Triples can be updated via `ON CONFLICT ... DO UPDATE SET confidence`, but there's no `updated_at` timestamp to track when the confidence was changed. This breaks temporal audit trails. |
| DM-5 | LOW | No soft delete. Triples can only be created or updated. There's no `deleted_at` column or deletion endpoint. Knowledge decay (marking outdated triples as low-confidence or expired) has no mechanism. |
| DM-6 | LOW | Confidence is a scalar, not a distribution. A confidence of 0.7 from a human assertion and 0.7 from an automated extractor should not be treated identically. Consider a `(confidence, source_reliability)` pair or a Bayesian update model. |
| DM-7 | INFO | No named graph / context support. All triples exist in a single flat namespace. There's no way to scope triples to a project, conversation, or time window (e.g., "triples valid for this session only"). This is a W3C RDF Named Graphs gap. |
---
5. Security — 9/10
Strengths
The Graph Kernel's security model is its crown jewel. The HMAC-signed admissibility framework is the strongest security implementation I've seen in a sub-15KLOC codebase:
- HMAC-SHA256 token signing with a 128-bit truncated output. The canonical string includes 6 fields + a version marker, preventing field reordering attacks.
- Type-level enforcement via `AdmissibleEvidenceBundle`. This type can only be constructed through `from_verified()`, which requires the HMAC secret and performs verification. Downstream APIs that accept `AdmissibleEvidenceBundle` get compile-time guarantee that the evidence was kernel-authorized.
- 8 security invariants (INV-GK-001 through INV-GK-008) are documented, each with corresponding incident types, severity levels, and response procedures.
- `SliceBoundaryGuard` prevents SQL injection by construction. Database queries for slice retrieval use parameterized arrays (`WHERE id = ANY($1)`) with the guard as the only way to produce the parameter.
- Token verification cache with constant-time comparison and LRU eviction. Performance target: <5ms p99 for cached verification.
Findings
| ID | Severity | Finding |
|---|---|---|
| SC-1 | MEDIUM | Development HMAC secret fallback. When `KERNEL_HMAC_SECRET` is not set, the service falls back to `b"development_only_secret_not_for_production"`. This is logged as a warning but the service starts successfully. In production deployments, this should be a hard error. Consider a `KERNEL_REQUIRE_HMAC=true` env var or a `--production` flag that fails-fast without a secret. |
| SC-2 | MEDIUM | Constant-time comparison may not be constant-time. `AdmissibilityToken::verify_hmac()` uses `token_bytes.iter().zip(expected[..16].iter()).fold(true, \|acc, (a, b)\| acc && (a == b))`. LLVM may optimize this into a short-circuit. Use `subtle::ConstantTimeEq` or `hmac::Mac::verify_slice()` for guaranteed constant-time behavior. |
| SC-3 | LOW | No HMAC secret rotation mechanism. If the secret is compromised, all previously issued tokens remain valid. There's no key versioning or dual-key verification (verify with current key, then fall back to previous key). |
| SC-4 | LOW | CORS allows any origin. `CorsLayer::new().allow_origin(Any).allow_methods(Any).allow_headers(Any)` is fine for a local service but should be locked down for Cloud Run deployments. |
| SC-5 | INFO | Knowledge graph endpoints have no authentication. The `/api/knowledge` POST endpoint can be called by anyone with network access. The `/api/slice` endpoint is governed by HMAC tokens, but the knowledge graph CRUD has no access control. This is acceptable for a local service but a risk for remote deployments. |
---
6. Testing — 8/10
Test Inventory
| Category | File | Tests | Quality |
|---|---|---|---|
| Golden tests | `tests/golden.rs` | 10 | Excellent — 100-run determinism, byte-level fingerprint verification |
| Atlas integration | `tests/atlas_integration.rs` | ~12 | Good — end-to-end pipeline validation |
| Unit tests | Inline `#[cfg(test)]` modules | ~40+ | Good — every module has tests |
| Property tests | `proptest` in dev-dependencies | Listed but undercounted | Cargo.toml declares proptest but usage is limited |
| Benchmarks | `benches/verification.rs` | 5 groups | Excellent — cold/cached/miss/contention/HMAC |
Strengths
- The 100-run determinism tests (`test_same_anchor_same_slice_id_100_runs`, `test_slice_fingerprint_byte_level`) are the gold standard for deterministic system testing. Most codebases don't test this rigorously.
- Benchmark suite covers cold verification, cached verification, cache misses, cache contention (multi-threaded), and HMAC computation overhead. This enables regression detection.
- `InMemoryGraphStore` enables fast, deterministic testing without database dependencies. Test helper functions (`make_turn`, `build_linear_graph`, `build_branching_graph`) are well-factored.
Findings
| ID | Severity | Finding |
|---|---|---|
| TS-1 | MEDIUM | No integration tests against PostgreSQL. All tests use `InMemoryGraphStore`. The PostgreSQL store has zero test coverage for query correctness, connection error handling, or pool behavior. A Docker-based integration test (or `testcontainers-rs`) would catch schema drift. |
| TS-2 | MEDIUM | Property tests are declared but sparse. `proptest` is in `dev-dependencies` but there are no `proptest!` blocks in the codebase. Property tests would be valuable for: (a) any valid graph + any valid policy → slice contains anchor, (b) slice IDs are deterministic for any input, (c) HMAC verification round-trips for any secret/payload. |
| TS-3 | LOW | No HTTP-level tests. The Axum routes are tested indirectly through the golden tests but there are no tests that construct an Axum test client and exercise the HTTP API (status codes, error responses, CORS headers). |
| TS-4 | LOW | No fuzz testing. Given the JSON parsing and UUID parsing surface area, `cargo fuzz` would be valuable for finding edge cases in `TurnId::from_str()`, `KnowledgeTriple` deserialization, etc. |
---
7. Documentation — 9/10
Inventory
| Document | Lines | Purpose |
|---|---|---|
| `GRAPH-KERNEL-ARCHITECTURE.md` | ~1,100 | Complete technical architecture reference |
| `GRAPH-KERNEL-EVALUATION-REPORT.md` | ~690 | Benchmark results + industry comparison |
| `GRAPH-KERNEL-RESEARCH-PAPER.md` | ~630 | Academic paper format, publication-ready |
| Inline Rust docs | ~500+ doc comments | Every public item documented |
| `IMPROVEMENT-PLAN.md` | ~160 | Prioritized improvement roadmap |
Strengths
- The research paper is genuine scholarship. Formal definitions, proper citations, comparative analysis against 9 industry systems. This positions the project for publication, not just internal documentation.
- The architecture doc is a complete reference. API endpoints, data model, deployment guide, configuration reference, operational runbook — all in one document. New contributors can onboard from this alone.
- Inline documentation density is exceptional. Module-level docs explain purpose. Function docs explain contracts. Security invariants are documented inline where enforced.
Findings
| ID | Severity | Finding |
|---|---|---|
| DC-1 | LOW | No CHANGELOG.md. The project is at v0.1.0 with no change log. As the codebase evolves, a conventional changelog would help track breaking changes, especially since downstream systems depend on schema version `1.0.0`. |
| DC-2 | LOW | No API OpenAPI/Swagger spec. The architecture doc describes endpoints textually, but there's no machine-readable API specification. `utoipa` could generate OpenAPI from the route handler types. |
| DC-3 | INFO | Benchmark docs reference Python scripts (`run_benchmark.py`, `gk-proxy.py`, `topology-ingester.py`) that live in `benchmarks/` and `scripts/` but aren't documented in the architecture doc. |
---
8. Dependencies — 7/10
Cargo.toml Audit
| Crate | Version | Purpose | Risk |
|---|---|---|---|
| `serde` | 1.0 | Serialization | ✅ Stable, well-maintained |
| `serde_json` | 1.0 | JSON | ✅ Stable |
| `axum` | 0.7 | Web framework | ✅ Active development |
| `sqlx` | 0.7 | Database driver | ⚠️ 0.8 is available, significant changes |
| `tokio` | 1.0 | Async runtime | ✅ Stable |
| `tower` | 0.4 | Middleware | ⚠️ 0.5 is in development |
| `tower-http` | 0.5 | HTTP middleware | ✅ Matches tower 0.4 |
| `xxhash-rust` | 0.8 | Hashing | ✅ Stable, no-std compatible |
| `hmac` | 0.12 | HMAC | ✅ RustCrypto, actively maintained |
| `sha2` | 0.10 | SHA-256 | ✅ RustCrypto |
| `hex` | 0.4 | Hex encoding | ✅ Stable |
| `lru` | 0.12 | LRU cache | ✅ Simple, correct |
| `parking_lot` | 0.12 | Synchronization | ✅ Widely used |
| `uuid` | 1.0 | UUID generation | ✅ Stable |
| `chrono` | 0.4 | Time | ⚠️ Historical CVE (RUSTSEC-2020-0159, since fixed) |
| `thiserror` | 1.0 | Error derive | ⚠️ 2.0 is available |
| `async-trait` | 0.1 | Async traits | ⚠️ Rust 1.75+ has native async trait support |
| `tracing` | 0.1 | Structured logging | ✅ Standard |
| `regex-lite` | 0.1 | Regex (lightweight) | ✅ Good choice over full regex |
| `proptest` | 1.0 | Property testing | ✅ Dev-only |
| `criterion` | 0.5 | Benchmarks | ✅ Dev-only |
Findings
| ID | Severity | Finding |
|---|---|---|
| DP-1 | LOW | `async-trait` is unnecessary on Rust 1.75+. Native `async fn` in traits is stable. Removing `async-trait` eliminates a proc-macro dependency and improves compile times. The `GraphStore` trait is the primary consumer. |
| DP-2 | LOW | `thiserror` 2.0 is available with no breaking API changes. Worth bumping for maintenance currency. |
| DP-3 | LOW | `sqlx` 0.7 → 0.8 has breaking changes (compile-time query checking improvements, connection pool API changes). Worth evaluating but not urgent. |
| DP-4 | INFO | No `cargo audit` in CI. The dependency tree should be checked against RustSec advisories. `chrono` 0.4 has had historical advisories (fixed in recent versions). |
---
9. Operational — 7/10
What's Present
- Structured JSON logging compatible with Cloud Logging / Cloud Trace
- Request tracing with correlation IDs (X-Cloud-Trace-Context)
- Health check hierarchy: `/health` (detailed), `/health/live` (liveness), `/health/ready` (readiness), `/health/startup` (startup probe) — Cloud Run compatible
- Graceful shutdown handling SIGTERM and Ctrl+C
- Connection pool monitoring via `pool_stats()` in health response
Findings
| ID | Severity | Finding |
|---|---|---|
| OP-1 | MEDIUM | Metrics are log-based only. The middleware records metrics as structured log lines (`metric_type = "request"`), not as Prometheus counters/histograms. In a Cloud Run environment, log-based metrics work but are delayed (minutes, not seconds). For real-time monitoring, expose `/metrics` with `metrics-exporter-prometheus`. |
| OP-2 | MEDIUM | No circuit breaker for database failures. If PostgreSQL becomes unreachable, every request will wait up to the 10s connect timeout before failing. A circuit breaker (open after N consecutive failures, half-open after T seconds) would fail-fast and reduce resource consumption during outages. |
| OP-3 | LOW | No request timeout. Axum routes don't have a timeout middleware. A runaway query could hold a connection indefinitely. `tower::timeout::TimeoutLayer` should be added with a 30s cap. |
| OP-4 | LOW | Error recovery logs but doesn't recover. Failed triple insertions in batch mode are logged with `tracing::warn!` but the error is silently swallowed. The batch response includes the count but not the specific failures. Consider returning per-triple error details. |
| OP-5 | INFO | No deployment automation. The architecture doc describes manual `cargo run` and Docker deployment but there's no Dockerfile, docker-compose.yml, or Cloud Run deployment config in the repository. |
---
10. Scale — 6/10
Current Operating Point
| Metric | Value |
|---|---|
| Triples | 3,502 |
| Subjects | 221 |
| Predicates | 88 |
| Connection pool | 2 min / 10 max |
| Concurrent capacity | ~10 queries (pool-limited) |
| Memory footprint | ~20MB binary + pool overhead |
Findings
| ID | Severity | Finding |
|---|---|---|
| SC-1 | MEDIUM | Pool size of 10 is the bottleneck. With 291ms average query time, 10 connections can serve ~34 queries/second. Under burst load (e.g., an atlas batch run), this saturates quickly. The pool size should be configurable via env var (already is: `DB_MAX_CONNECTIONS`) but the default should be reconsidered for production. |
| SC-2 | MEDIUM | Knowledge graph queries fetch entire result sets. `query_knowledge_handler` returns up to 500 triples in a single response. For large result sets, this creates memory pressure and JSON serialization latency. Cursor-based pagination would be more scalable. |
| SC-3 | LOW | No connection pool warming on startup. The `min_connections: 2` setting establishes connections lazily. First burst of requests will pay connection establishment overhead. Consider calling `pool.acquire().await` on startup to pre-warm. |
| SC-4 | INFO | No read replica support. The single DATABASE_URL connects to one PostgreSQL instance. For read-heavy workloads (knowledge graph queries), a read replica URL could distribute load. |
---
11. Known Bugs — 6/10
Active Issues
| ID | Severity | Bug | Status |
|---|---|---|---|
| BG-1 | HIGH | Entity normalization fragmentation. "Dream Weaver" ≠ "dream-weaver-engine" creates duplicate entities. 169 raw subjects collapse to 132 canonical entities (37 duplicates). This suppresses relationship query relevance from theoretical 1.00 to measured 0.94. | Partially mitigated by Python middleware; not fixed in Rust service. |
| BG-2 | MEDIUM | Pagination returns wrong total count. `query_knowledge_handler` returns `total: triples.len()` (count of returned results), not the actual total count of matching triples. This makes pagination impossible — clients can't know if there are more results. | Open. |
| BG-3 | MEDIUM | `confidence` filter uses float interpolation. The `min_confidence` parameter is formatted directly into the SQL string (`format!("confidence >= {}", min_conf)`). While this is safe (f64 formatting can't produce SQL injection), it's inconsistent with the parameterized approach used for other fields. It should use a bind parameter. | Open. |
| BG-4 | LOW | `source` field defaults to "unknown". When a triple is inserted without a source, it gets `source = 'unknown'`. When updated via `ON CONFLICT ... DO UPDATE`, the source is overwritten with the new value. This means the original source is lost on confidence updates. | Open. |
| BG-5 | LOW | Batch triple insertion is not idempotent. The `added/updated` counts in `KnowledgeBatchResponse` count per-row results, but if the same triple appears twice in a single batch, the second occurrence will be counted as an "update" even though it was just inserted. | Open. |
---
12. Missing Features — 5/10
| ID | Priority | Feature | Impact |
|---|---|---|---|
| MF-1 | CRITICAL | Server-side multi-hop traversal. Currently, multi-hop queries require N HTTP round-trips (one per hop). A `POST /api/knowledge/traverse` endpoint accepting `start_entity`, `predicates[]`, `max_hops`, `direction` would reduce a 3-hop query from ~874ms to ~291ms (single round-trip). | Would eliminate the Graph Kernel's largest latency multiplier. |
| MF-2 | HIGH | SPARQL or Cypher subset. The current query API supports only exact field matching. A graph query language (even a minimal subset) would enable pattern matching, path queries, and aggregation without custom endpoint proliferation. | Would make the knowledge graph genuinely useful for ad-hoc exploration. |
| MF-3 | HIGH | Batch operations for slicing. `POST /api/slice/batch` exists but processes sequentially. True parallel batch slicing (using `tokio::join!` or `FuturesUnordered`) would significantly improve atlas batch run performance. | Atlas runs would scale linearly with connection pool size. |
| MF-4 | MEDIUM | Streaming results. Large knowledge graph queries return the entire result set as a JSON array. Server-sent events (SSE) or NDJSON streaming would reduce time-to-first-byte and memory usage. | Would enable real-time graph exploration UIs. |
| MF-5 | MEDIUM | Graph visualization endpoint. A `GET /api/knowledge/graph?subject=X&hops=2` that returns D3-compatible JSON or Mermaid syntax would enable visual exploration of the knowledge graph. | Would dramatically improve developer experience and debugging. |
| MF-6 | LOW | WebSocket subscriptions. Real-time notifications when triples are added/updated would enable reactive UIs and downstream pipeline triggers. | Would enable event-driven architecture patterns. |
| MF-7 | LOW | DELETE endpoint for knowledge triples. There's no way to remove incorrect triples except by direct database manipulation. A `DELETE /api/knowledge` endpoint is needed. | Knowledge maintenance is currently impossible through the API. |
| MF-8 | LOW | Temporal versioning. Triples have `created_at` but no validity windows (`valid_from`, `valid_until`). This means outdated knowledge (e.g., "X uses Y" when X has migrated to Z) persists indefinitely at full confidence. | Would enable knowledge lifecycle management. |
---
Overall Health Assessment
╔══════════════════════════════════════════════════════════════╗
║ ║
║ OVERALL HEALTH SCORE: 7.4 / 10 ║
║ ║
║ Verdict: PRODUCTION-VIABLE with clear improvement paths ║
║ ║
║ Critical path: Latency (local DB) → Entity normalization ║
║ → Server-side traversal → Prometheus metrics ║
║ ║
╚══════════════════════════════════════════════════════════════╝Score Breakdown
| Weight | Dimension | Score | Weighted |
|---|---|---|---|
| 10 | |||
| 15 | |||
| 15 | |||
| 10 | |||
| 10 | |||
| 8 | |||
| 5 | |||
| 5 | |||
| 7 | |||
| 7 | |||
| 4 | |||
| 4 | |||
| **100 |
What Makes This Codebase Special
1. The provenance engine concept is novel. No other system in the graph database / RAG space combines deterministic context slicing with HMAC-signed admissibility tokens. The research paper correctly identifies this as a new infrastructure category.
2. Type-level security enforcement. The `AdmissibleEvidenceBundle` pattern — where the type itself is proof of verification — is genuinely elegant. It turns security violations into compile errors.
3. The documentation-to-code ratio is remarkable. A research paper, architecture doc, evaluation report, improvement plan, and dense inline docs for an 11K-line codebase. This project is more documented than most 100K-line projects.
What Needs Attention
1. Get off the remote database for reads. The SQLite proxy (already implemented in Python) is the right pattern. The Rust service should support SQLite natively via a feature flag.
2. Entity normalization belongs in Rust. The Python middleware is a workaround. A `canonicalize_entity()` function at the route handler level would close the normalization gap permanently.
3. Server-side traversal is the highest-impact feature. A single new endpoint would transform the Graph Kernel's multi-hop story from "N round-trips" to "one query."
---
Audit generated from static analysis of the cc-graph-kernel crate, live service inspection at localhost:8001, benchmark data from graph-kernel-evaluation.md, and documentation review.
Promotion Decision
Attach run IDs, datasets, metrics, and reproduction commands.
Source Anchor
Comp-Core/docs/GRAPH-KERNEL-DEP-AUDIT.md
Detected Structure
Method · Evaluation · Figures · Code Anchors · Architecture