Calendar Day
Thursday, July 9, 2026 (PR 3 of 3)
Planned Effort
2 story points (Low) — sprint item #7
Companion PRs: Independent of Thursday PR 1–2; can land in parallel with MessageDict or dispatch work.
Problem
get_session and get_session_stats in api/sessions.py and export_session in api/export_api.py each repeat:
- Resolve base dir from
current_app.config["CLAUDE_PROJECTS_DIR"]
safe_join for path-traversal prevention
os.path.isfile check
get_cached_session load
is_session_excluded check
- Broad exception tuple → structured
ErrorCode
The exception tuple is duplicated: _PARSE_ERRORS in api/sessions.py vs _EXPORT_ERRORS from utils/export_engine.py in export_api.py. Low severity today, but the tuple must stay synchronized and every new session endpoint copies the pattern.
api/search.py uses a different corpus-scan path — out of scope unless index changes per-session safe_join access.
Goal
One merged PR that introduces a shared decorator (or Flask helper) encapsulating the resolve → load → exclude → error pattern and refactors the three session handlers to use it.
Scope
Touch points
- New shared helper/decorator (e.g. in
api/sessions.py or api/_session_handlers.py) that:
- Resolves
(project_name, session_id) → loaded session
- Centralizes try/except →
error_response mapping
- Defines the broad exception tuple in one place
- Refactor
get_session, get_session_stats, export_session to use it.
- Preserve exception-leakage policy (
tests/test_error_propagation.py).
Out of scope
api/search.py handlers.
- New session endpoints beyond the three listed.
- Changes to
ErrorCode values or HTTP status mapping.
Acceptance Criteria
Verification
cd C:\Users\Jasen\CppAliance\claude-code-chat-browser
.\.venv\Scripts\Activate.ps1
pytest tests/test_error_propagation.py tests/test_api_routes.py tests/test_export_api_bulk.py -q
pytest -q
mypy .
ruff check .
Calendar Day
Thursday, July 9, 2026 (PR 3 of 3)
Planned Effort
2 story points (Low) — sprint item #7
Companion PRs: Independent of Thursday PR 1–2; can land in parallel with MessageDict or dispatch work.
Problem
get_sessionandget_session_statsinapi/sessions.pyandexport_sessioninapi/export_api.pyeach repeat:current_app.config["CLAUDE_PROJECTS_DIR"]safe_joinfor path-traversal preventionos.path.isfilecheckget_cached_sessionloadis_session_excludedcheckErrorCodeThe exception tuple is duplicated:
_PARSE_ERRORSinapi/sessions.pyvs_EXPORT_ERRORSfromutils/export_engine.pyinexport_api.py. Low severity today, but the tuple must stay synchronized and every new session endpoint copies the pattern.api/search.pyuses a different corpus-scan path — out of scope unless index changes per-sessionsafe_joinaccess.Goal
One merged PR that introduces a shared decorator (or Flask helper) encapsulating the resolve → load → exclude → error pattern and refactors the three session handlers to use it.
Scope
Touch points
api/sessions.pyorapi/_session_handlers.py) that:(project_name, session_id)→ loaded sessionerror_responsemappingget_session,get_session_stats,export_sessionto use it.tests/test_error_propagation.py).Out of scope
api/search.pyhandlers.ErrorCodevalues or HTTP status mapping.Acceptance Criteria
safe_join, isfile check, cached-session load, exclusion check, and exception→ErrorCodemapping.get_session,get_session_stats, andexport_sessionrefactored to use it.tests/test_error_propagation.pyandtests/test_api_routes.pypass.pytest,mypy --strict, andruffpass.Verification