agent/docs/brain-callers-audit.md
Snider 9628e5d088 feat(agent/brain): non-Laravel callers route through shared OpenBrain client (#121)
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
2026-04-25 20:33:33 +01:00

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/agent still had direct Go callers that bypassed the shared OpenBrain helper path. Those are patched in this ticket.
  • core/mcp already 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.md is 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, and List requests.
  • client.go routes requests through retry and circuit-breaker policy.
  • client.go opens and cools down the circuit.
  • client.go retries 408, 429, and 5xx, with Retry-After support 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 curl examples omit org and breaker/retry policy.

Changes Applied

  1. Patch pkg/mcp/agentic/prep.go to use pkg/mcp/brain/client.
  2. Patch Hermes OpenBrain plugins to reuse a shared client wrapper with org defaults plus retry / breaker logic.
  3. Patch Claude shell hooks or retire them in favour of a small Go helper that uses the shared client.
  4. Tighten plugins/core-go/skills/api-endpoints/SKILL.md so the example does not become a copy-paste bypass.

Notes

  • No top-level scripts/*.sh file in this repository currently calls /v1/brain/*.
  • /Users/snider/Code/core/mcp was readable but not writable in this session, so the MCP prep caller could be audited but not patched here.