Audit + remediation pass on non-Laravel Brain callers per #121. docs/brain-callers-audit.md (NEW): audit baseline. Lists every PHP + Go + script call site, current protections (org auth, retry, circuit breaker), and gaps. Cross-references recent fixes (#312, #998, #1052, #1055, #1006, #985). New pkg/agentic/brain_client.go helper: routes Go callers through the shared OpenBrain client path with org injection (CORE_BRAIN_ORG fallback) and a shared circuit breaker. Patched call sites: - pkg/agentic/prep.go (line ~1200) - pkg/agentic/session.go (line ~826) - pkg/agentic/brain_seed_memory.go (line ~153) - pkg/brain/direct.go (line ~106) These previously made raw Brain HTTP posts. Now they go through the hardened client path inheriting #998 (key-perm), #1052 (bearer SSRF guard), #1055 (jitter), and the circuit breaker. Remaining non-Laravel gaps (documented in audit doc, not patched here because they're outside this lane's path-allowlist): - core/mcp/pkg/mcp/agentic/prep.go - Hermes Python plugins - Claude shell hooks - plugins/core-go api-endpoints SKILL example Follow-up tickets needed for those (file separately). Co-authored-by: Codex <noreply@openai.com> Closes tasks.lthn.sh/view.php?id=121
6.8 KiB
6.8 KiB
Brain Callers Audit
Date: 2026-04-25
Ticket: Mantis #121
Scope
Audit command:
rg -n '/v1/brain' /Users/snider/Code/core/agent /Users/snider/Code/core/mcp
Tests, PHP/Laravel handlers, and documentation-only references were excluded when classifying runtime callers.
Verdict
This ticket is not stale-fixed.
core/agentstill had direct Go callers that bypassed the shared OpenBrain helper path. Those are patched in this ticket.core/mcpalready has a hardened shared client and direct subsystem, but one MCP prep caller still bypasses that client.- Hermes Python plugins and Claude shell hooks still call
/v1/brain/*directly without a circuit-breaker or retry policy. plugins/core-go/skills/api-endpoints/SKILL.mdis documentation only, not a runtime caller, but its example still shows the raw endpoint shape rather than the hardened client path.
Hardened Baseline
The current non-Laravel baseline is the shared Go client in client.go:
- client.go injects default org and agent on typed
Remember,Recall, andListrequests. - client.go routes requests through retry and circuit-breaker policy.
- client.go opens and cools down the circuit.
- client.go retries
408,429, and5xx, withRetry-Aftersupport at client.go.
Runtime Callers
| Path | Status | Org scope | Breaker / retry | Notes |
|---|---|---|---|---|
| pkg/brain/direct.go | patched | now defaults org from CORE_BRAIN_ORG when omitted |
already used shared client Call() |
Active core-agent brain subsystem |
| pkg/agentic/prep.go via pkg/agentic/brain_client.go | patched | helper injects configured org when caller omitted it | helper now uses shared client + shared circuit breaker | Replaced raw HTTPPost recall |
| pkg/agentic/session.go via pkg/agentic/brain_client.go | patched | helper injects configured org when caller omitted it | helper now uses shared client + shared circuit breaker | Replaced raw HTTPPost remember |
| pkg/agentic/brain_seed_memory.go via pkg/agentic/brain_client.go | patched | helper injects configured org when caller omitted it | helper now uses shared client + shared circuit breaker | Replaced raw HTTPPost remember while preserving workspace_id |
| pkg/mcp/brain/direct.go | aligned | typed client path carries org defaulting | shared client | Already on hardened path |
| cmd/brain-seed/main.go and cmd/brain-seed/main.go | aligned | org passed into shared client and request input | shared client | Already on hardened path |
| pkg/mcp/agentic/prep.go | follow-up | no explicit org in request body | raw http.NewRequest + s.client.Do, no shared breaker / retry |
Read-only in this sandbox; should be switched to pkg/mcp/brain/client |
| hermes/plugins/openbrain_memory.py and hermes/plugins/openbrain_memory.py | follow-up | org is optional / caller-provided | direct requests / httpx / urllib, no breaker / retry |
Outside allowed edit scope for this ticket |
| hermes/plugins/openbrain_context.py and hermes/plugins/openbrain_context.py | follow-up | org is optional / caller-provided | direct requests / httpx / urllib, no breaker / retry |
Outside allowed edit scope for this ticket |
| claude/core/scripts/session-start.sh, claude/core/scripts/session-save.sh, claude/core/scripts/pre-compact.sh | follow-up | no org field sent | raw curl, no breaker / retry |
Outside the shell-script allowlist for this ticket |
Documentation-Only Reference
- plugins/core-go/skills/api-endpoints/SKILL.md is not a runtime caller. It is still worth tightening so plugin authors are pointed at the shared client pattern or at least warned that raw
curlexamples omit org and breaker/retry policy.
Changes Applied
- Added pkg/agentic/brain_client.go to centralise non-tool OpenBrain calls in
core-agentonto the shared client with a subsystem-scoped circuit breaker and org injection. - Updated pkg/agentic/prep.go, pkg/agentic/session.go, and pkg/agentic/brain_seed_memory.go to use that helper instead of raw
HTTPPost. - Updated pkg/brain/direct.go so remember / recall / list send the configured org by default when callers omit it.
Recommended Follow-Up
- Patch pkg/mcp/agentic/prep.go to use
pkg/mcp/brain/client. - Patch Hermes OpenBrain plugins to reuse a shared client wrapper with org defaults plus retry / breaker logic.
- Patch Claude shell hooks or retire them in favour of a small Go helper that uses the shared client.
- Tighten plugins/core-go/skills/api-endpoints/SKILL.md so the example does not become a copy-paste bypass.
Notes
- No top-level
scripts/*.shfile in this repository currently calls/v1/brain/*. /Users/snider/Code/core/mcpwas readable but not writable in this session, so the MCP prep caller could be audited but not patched here.