Commit graph

3 commits

Author SHA1 Message Date
Snider
1872424cfd feat(agent/brain): lift OpenBrain discovery features (search/discoverTags/listScopes) (#180)
Bounded subset of RFC-OPENBRAIN lifted from lab/lthn.ai shim into the
OSS BrainService at php/Services/BrainService.php:

- search(query, filter, pagination): Elasticsearch path first, falls
  back to MariaDB if ES is unavailable. Operates on active/latest
  memories only.
- discoverTags(filter): tag-cloud / popular-tags discovery scoped to
  authenticated org(s).
- listScopes(filter): org/project distribution counts for the
  authenticated session.

All three:
- Enforce bounded inputs (per #1001 patterns)
- Honour org auth (per #312 patterns)
- Only operate on active/latest memories (active=1, deleted_at IS NULL)

Self-hosters now get the same discovery surface that lab/lthn.ai
exposes — no need to fork the OSS service to access these features.

Pest covers: bounds-violation rejection, fallback behaviour, scoped
discovery returning correct org/project breakdowns.

Lab-only features still out of scope for this lane (would pull in
extra schema/models/events): agentContext, recall feedback,
maintenance lifecycle (reindex/consolidate/clean/prune). Those need
follow-up tickets if/when bounded-lift becomes possible.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=180
2026-04-25 20:39:14 +01:00
Snider
b7bc526d50 test(agent/brain): regression coverage for filter field bounds (closes #1000)
#1000 was stale-fixed: BrainService::recall() validates filter input
via the shared validator at line 489, which already bounds org,
project, type, agent_id. forget() bounds id at line 499.

These tests pin the safety claim explicitly:
- project=129 chars rejected
- agent_id=65 chars rejected
- project="core" accepted (sanity)
- project=128 chars accepted (boundary)

Note: BrainList.php (separate MCP list path) still lacks explicit
max lengths for project + agent_id — file outside this lane's allow-
list. File a follow-up if that surface needs the same bounds.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=1000
2026-04-25 19:23:41 +01:00
Snider
385b89b3eb fix(agent/brain): cap remember()/recall()/forget() input field sizes
Bound input field sizes against memory/DB/Qdrant bloat (DoS-by-self):
- content: 65536 bytes via mb_strlen
- tags: max 100 entries; each tag max 128 chars
- agent_id, type: 64 chars each
- project, org: 128 chars each
- supersedes_id: ULID-shape only

validateRememberInput() throws InvalidArgumentException at every entry
point (remember, recall, forget) before any DB or upstream call. Field-
specific error messages so callers know which field violated.

Pest covers good-path, content-too-long, tags-array-too-large, tag-
length, exact-boundary cases.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=1001
2026-04-25 18:58:41 +01:00