Stage 2d-1 — serializable matcher AST + fail-closed classifier (DAN-605) - #2
Conversation
…605, ADR-009) Filters become data: JSON-pure AST (eq/neq, ordered, in/nin, exists, and/or/not) with builder M, strict coercion-free evaluator (own-props only, SQL-NULL absence discipline), canonical sorted-key serialization, and the two-tier classifyFilter gate — encodable ONLY for input that fully validates; closures/unknown ops/malformed trees route opaque (a re-run is always correct; a missed update never is). Untrusted-input hardening: accessor properties rejected unread, proto field names refused, depth cap 32, list cap 10K, frozen fresh copies. Normative semantics table in docs/design/matcher-semantics.md = the contract the DAN-579 worker SQL tier compiles against. Unblocks live queries (roadmap 2.2). Audit blocker #7 closed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DAN-605 Stage 2d-1 — serializable matcher AST + fail-closed classifier (audit blocker #7)
First slice of DAN-579 (scope item 1 — "the real first deliverable"). Split out 2026-07-20 per Danny's lane pick: the AST is a pure additive module with unit-test verification; the worker query tier (ADR-003 amendment, real-browser verification) and pinned result sets stay in DAN-579. GoalQuery filters become serializable data: a matcher AST with a strict in-memory evaluator and a classifier that fails CLOSED, so live queries (roadmap 2.2) can maintain filtered views against change-set events instead of re-running opaque closures. Context
Constraints
Discretion grantedExact operator vocabulary (recommend a WatermelonDB-informed minimum: eq/neq/gt/gte/lt/lte/in/nin/and/or/not, field-exists; add more only with evaluator+test coverage), builder-API ergonomics, error shape (match existing repo patterns until the M6 error taxonomy exists), ADR number, file naming. Acceptance criteria
Verification (DoR gate)cd core/projects/colada-db-project/colada-db && CI=true pnpm test && pnpm typecheck && pnpm lint && pnpm buildExpected: all suites green including new Blast radiusThis chip: additive, dev-only — no existing behavior touched. Downstream severity HIGH: a wrong classifier verdict later means silently stale live-query results, which is why the adversarial test set is done-defining now rather than deferred. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (6)
📝 WalkthroughWalkthroughAdds a serializable JSON-pure matcher AST with fail-closed parsing and classification, strict evaluation semantics, canonical serialization, typed builders, public exports, design documentation, and adversarial Vitest coverage. ChangesMatcher AST subsystem
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant classifyFilter
participant parseMatcher
participant evaluateMatcher
participant serializeMatcher
Client->>classifyFilter: Submit matcher input
classifyFilter->>parseMatcher: Validate and normalize
parseMatcher-->>classifyFilter: Encodable AST or parse failure
classifyFilter-->>Client: AST classification
Client->>evaluateMatcher: Evaluate AST against entity
evaluateMatcher-->>Client: Boolean result
Client->>serializeMatcher: Serialize validated AST
serializeMatcher-->>Client: Canonical JSON string
Note 🎁 Summarized by CodeRabbit FreeYour organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login. Comment |
Goal
Query filters become serializable data: a JSON-pure matcher AST (
eq/neq, ordered ops,in/nin,exists,and/or/not) with builderM, a strict coercion-free evaluator, canonical sorted-key serialization, and the fail-closed two-tier gateclassifyFilter— the substrate live queries (roadmap 2.2) re-evaluate against change events, and the shape agent surfaces can safely accept. Closes audit blocker #7 (DAN-575 council audit).Design law
encodableis returned ONLY for input that fully validates; the verdict carries the canonical frozen tree so consumers never re-trust raw input. Closures, unknown operators, malformed shapes, over-deep/over-budget trees →opaque(a re-run is always correct; a missed update never is). Normative semantics table indocs/design/matcher-semantics.md= the contract the DAN-579 worker SQL tier compiles against. ADR-009 filed.Gate evidence
CI=true pnpm test→ 238/238 (29 new matcher tests incl. adversarial catalog: trap bombs, revoked proxies, depth bombs, index-planted getters asserted UNREAD, prototype pollution, aggregate-cost DoS)pnpm typecheck/pnpm lint/pnpm build→ cleandist/index.mjsthrough the agent-boundary path (JSON wire → classify → evaluate) — PASSReview verdicts
-0normalization, non-enumerable key refusal).MATCHER_MAX_COSTaggregate budget — over-budget routes to opaque, zero correctness loss).Linear: DAN-605 (parent DAN-579 / epic DAN-575)
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Security
Documentation
Tests