You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
HTTP boundary untested beyond integration smoke — ~2,500 lines of parser/export utility tests exist, but blueprint wiring (query parsing, status codes, headers, export zip responses) is only partially covered. tests/test_export_api_bulk.py registers blueprints in isolation, not through create_app. Routes such as GET /api/sessions/.../stats and GET /api/export/session/... have no full-app tests.
CLI behavior untested end-to-end — tests/test_cli_args.py validates argparse flags only; no test runs scripts/export.py list|stats|export and asserts exit codes, stderr on bad input, or artifact output.
Errors are not machine-readable — Responses use {"error": "..."} without a "code" field. Programmatic clients cannot distinguish SESSION_NOT_FOUND from PARSE_ERROR without fragile string matching. This blocks Thursday API reference documentation and future API versioning.
Grep guard: no remaining bare jsonify({"error": ...}) in api/ without code.
B4 — Catalog stub for Thursday
Short table in README.md or docs/error-codes.md listing each ErrorCode, HTTP status, and meaning (Thursday API reference expands this).
Acceptance criteria
HTTP + CLI tests (issue fab633e4-...)
Every blueprint endpoint in api/projects.py, api/sessions.py, api/search.py, api/export_api.py has ≥1 happy-path and ≥1 error-path test using Flask test client with create_app
GET /api/sessions/<project>/<id>/stats covered (happy + 404 + invalid path)
GET /api/export/session/<project>/<id> covered (md + json + 404)
POST /api/export and GET /api/export/state exercised through full app (not isolated blueprint only)
CLI scripts/export.py has ≥1 e2e test each for list, stats, and export path; invalid --since asserts non-zero exit
Problem
tests/test_export_api_bulk.pyregisters blueprints in isolation, not throughcreate_app. Routes such asGET /api/sessions/.../statsandGET /api/export/session/...have no full-app tests.tests/test_cli_args.pyvalidatesargparseflags only; no test runsscripts/export.py list|stats|exportand asserts exit codes, stderr on bad input, or artifact output.{"error": "..."}without a"code"field. Programmatic clients cannot distinguishSESSION_NOT_FOUNDfromPARSE_ERRORwithout fragile string matching. This blocks Thursday API reference documentation and future API versioning.Eval clusters: verification-gap (test 31 — Test Depth) and error-versioning-trajectory (test 10 — Error Design).
Scope (one PR)
Block A — HTTP endpoint and CLI tests (5 pt)
A1 — Route matrix (
tests/test_api_routes.py)Reuse
client,client_empty,client_thinkingfromtests/conftest.py. Do not re-test scenarios already intests/test_api_integration.py(projects list, project sessions, session detail, search happy/400/default).//api/projects/<name>/sessions[](document current behavior)/api/sessions/<proj>/<id>/statsconversation_turns,cost_estimate_usd); 404; invalid path 400/api/searchlimit=0→ 400;limit=1.5→ 400;limit=9999capped at 500/api/sessions/<proj>/<id>ValueError/Tracebackleak/api/export/statecreate_app/api/exportsince; 400 non-object JSON body/api/export/session/<proj>/<id>?format=json; 404; invalid path 400Port assertions from
tests/test_export_api_bulk.pyinto full-app tests where applicable.A2 — CLI e2e (
tests/test_cli_e2e.py)Use
subprocess.runwithsys.executableandscripts/export.py(pattern:tests/test_export_exclusion_filtering.py).listlist --project <unknown>stats--since yesterday(invalid)export --since allwith seeded dataDo not duplicate
tests/test_cli_args.pyparser parity tests.A3 — Shared helpers
assert_error_response(resp, expected_code=None)totests/conftest.py.tests/test_api_integration.py::_assert_error_shapeto require"code"after Block B lands.Slip if overloaded: CLI e2e (one subprocess test) → export session routes → defer remaining export POST happy-path to follow-up commit on same PR.
Block B — Structured error codes (3 pt)
B1 — Central module (
api/error_codes.py)Optional:
models/errors.pywithErrorResponseDictif Mondaymodels/package is on branch.B2 — Migrate all
api/*.pyerror sitesapi/search.pySEARCH_INVALID_LIMITon badlimitapi/sessions.pyINVALID_PATH,SESSION_NOT_FOUND,PARSE_ERROR,INTERNAL_ERRORapi/export_api.pyINVALID_REQUEST_BODY,INVALID_SINCE_MODE,EXPORT_NOTHING_TO_EXPORT,SESSION_NOT_FOUND,INVALID_PATHPreserve extra fields where they exist today (e.g.
"since"on invalid since mode). Keep human-readableerrortext unchanged for SPA compatibility.B3 — Tests
tests/test_error_codes.py— parametrized table: path/body → status +code.tests/test_search.py,tests/test_api_integration.py,tests/test_export_api_bulk.pyerror assertions.jsonify({"error": ...})inapi/withoutcode.B4 — Catalog stub for Thursday
Short table in
README.mdordocs/error-codes.mdlisting eachErrorCode, HTTP status, and meaning (Thursday API reference expands this).Acceptance criteria
HTTP + CLI tests (issue
fab633e4-...)api/projects.py,api/sessions.py,api/search.py,api/export_api.pyhas ≥1 happy-path and ≥1 error-path test using Flask test client withcreate_appGET /api/sessions/<project>/<id>/statscovered (happy + 404 + invalid path)GET /api/export/session/<project>/<id>covered (md + json + 404)POST /api/exportandGET /api/export/stateexercised through full app (not isolated blueprint only)scripts/export.pyhas ≥1 e2e test each forlist,stats, and export path; invalid--sinceasserts non-zero exiterrorkey, no stack trace / exception class leakage (issue Security: stop leaking exception details in HTTP error responses #25)Structured error codes (issue
8c01c675-...)"code"(stableUPPER_SNAKE_CASEstring) and"error"(human-readable message)ErrorCodeenum (or constants module) is single source of truth; documented in README ordocs/error-codes.mdapi/search.py,api/sessions.py,api/export_api.pymigrated toerror_response()helper"error"and"code"on every error response under testGET /api/search?q=test&limit=abcreturnscode: SEARCH_INVALID_LIMIT(or equivalent) with 400Overall Wednesday checkpoint
pytest -qandmypygreenOut of scope
docs/api-reference.md) — Thursday, 5 ptCONTRIBUTING.md/ architecture docs — Thursday, 3 ptErrorResponseDict