honcho/tests/utils
Vineeth Voruganti d9de9b88f8 fix(filter): fail closed on unrecognized filter shapes
The filter body is arbitrary client JSON with no schema, so validation
was emergent: any shape the DSL didn't recognize surfaced as an
unhandled 500 from somewhere in SQLAlchemy or psycopg. Fixing individual
shapes doesn't converge — a fuzz over the DSL found five more families
beyond the three already fixed here:

  {"AND": [None]}                TypeError, non-dict in a logical list
  {"AND": [[]]}                  AttributeError on .items()
  {"session_id": {"gte": true}}  SQLAlchemy ArgumentError
  {"embedding": []}              NotImplementedError, no python_type
  {"session_id": {"ne": {...}}}  execute-time "cannot adapt type 'dict'"

Two generic guards instead:

1. Any operand bound to a non-JSONB column must be a scalar, checked
   element-wise for `in`. A dict or list bound to a scalar column
   compiles cleanly and only fails in the driver at execute time, so it
   has to be rejected during construction. JSONB columns are exempt —
   a dict there is a containment match.

2. apply_filter fails closed: FilterError propagates, anything else is
   logged with logger.exception (filter shape included) and re-raised as
   FilterError. Unknown filter failures become 422s while staying fully
   visible as errors rather than being swallowed.

Adds two invariant tests over a generated matrix of filter shapes: every
shape either compiles or raises FilterError, and no non-scalar is ever
bound to a scalar column. Both fail without the guards above. They cover
shapes nobody enumerated, so the next unimagined body fails in CI rather
than in production.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 15:19:14 -04:00
..
__init__.py refactor: replace mirascope with handrolled client (#202) 2025-09-24 11:53:30 -04:00
test_agent_tools.py feat: session allowlist on dialectic and representation via filters (#882) 2026-07-28 10:55:02 -04:00
test_clients.py feat(telemetry): CloudEvents + Langfuse tracing as projections over a captured LLM stream (#845) 2026-07-02 16:49:53 -04:00
test_config_helpers.py feat: deriver custom instructions (#609) 2026-05-11 18:05:42 -04:00
test_files.py fix(files): handle empty json uploads safely (#434) 2026-03-18 18:36:34 -04:00
test_filter.py fix(filter): fail closed on unrecognized filter shapes 2026-07-28 15:19:14 -04:00
test_length_finish_reason.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00
test_schema_conversion.py feat(dialectic): optional structured outputs with limited schema for Dialectic calls (#896) 2026-07-20 18:46:49 -04:00
test_summarizer.py Refactor clients.py to add modern features and more flexible configuration (#459) 2026-04-20 02:46:37 -04:00