Adds legal-metadata filtering and the payload to color by it (foundation for
the color-by selector in the analytics PR).
Backend (web/graph_api.py, web/app.py) — read-only, G2:
- GraphNode += court, date (ISO) — precedents carry them for filter/color-by.
- build_corpus_graph += server-side WHERE filters (G5): court, precedent_level,
chair, district, year_from, year_to (EXTRACT(YEAR FROM date)). Neighborhood
query also selects court/date.
- New GET /api/graph/facets (response_model GraphFacets, UI2) → distinct
courts/levels/chairs/districts so the UI doesn't hardcode Hebrew strings.
Frontend:
- graph.ts: GraphNode += court/date; GraphFilters += the six params;
buildParams; useGraphFacets() hook.
- graph-filter-panel: an "advanced" Accordion with court/precedent_level/chair/
district Selects (from facets) + year-from/year-to Selects.
- graph-view: new controls wired into filters; facets fetched and passed down.
Verified read-only against the live DB (precedent_level=עליון&year_from=2015
filters correctly; facets populated: 36 courts / 3 levels / 19 chairs / 4
districts). web-ui build + lint pass.
Invariants: G2 (SELECT-only via db.get_pool), G5 (filters server-side),
UI2 (explicit response_models). api:types to be regenerated post-deploy.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>