Task ID: audit-routing-fixes-2026-05-14 Layer: Atlas (artifact / notebook / cite routes) Date: 2026-05-14 v1 carve-out: user-authorized; v1 still serves scidex.ai
Four small route-level fixes uncovered by the 2026-05-13 audit
(/tmp/audit-2026-05-13).
/artifact/<missing-id> returned HTTP 200 with a not-found bodyartifact_detail rendered the "Artifact Not Found" content via
page_template(...) but FastAPI wrapped the string in a default 200
HTMLResponse. Bots, monitoring, and the audit harness all saw 200 →
unable to distinguish "real page" from "missing artifact." Wrap in
HTMLResponse(..., status_code=404) so the status code matches the
body.
/idea-collider returned 404The Forge idea-collider lives at /forge/idea-collider. A small
number of homepage / nav emitters use the short /idea-collider
path. Rather than chase them all (the audit identified some at line
33919, 49289, 54311 but there may be more elsewhere), add a 301
alias route that preserves the ids and seed query parameters.
file_path_resolve_notebook_paths returns Path("") for notebooks with a
NULL or empty file_path. Path("").exists() is True (it
resolves to CWD), so the existing guard at api.py:74826
(if ipynb_local_path and ipynb_local_path.exists()) lets the
empty path through. The next line called
ipynb_local_path.with_suffix(".html") → ValueError: PosixPath('.'), surfacing as HTTP 500 on 3 sampled notebooks.
has an empty name
Add ipynb_local_path.name to the guard so empty / dot paths
fall through to the existing associated_analysis_id fallback.
/cite?fmt=csl returned 400artifact_cite validates fmt in {"bibtex", "ris", "endnote",. External citation managers (Zotero, Better BibTeX)
"csl_json"}
sometimes probe with the short alias csl. Accept csl as a synonym
for csl_json by coercing it before the validator runs.
python3 -c "import ast; ast.parse(open('api.py').read())" → OK/tmp/audit-2026-05-13/reverify.py. The fourscidex-api restart.Low.
.name check.csl_json branch is unchanged.