Real architectural gap found and fixed during Phase 2A testing, not part of
the original plan: scenario validate/answer requests proxied through
/lab/<token>/api/scenarios/:id/{validate,answer} were writing progress into
that ephemeral Lab container's own SQLite — which is destroyed on every
reset/reap. Confirmed by testing: solving a scenario never showed up on the
dashboard's curriculum view, and would have been silently lost on lab
recreate, directly contradicting "academic progress must survive lab
reset/recreate."
Root tension: scenario validation must run against the student's own live
cluster (only exists inside their Lab container) — it can't be re-run
anywhere else. But the canonical progress record needs to live on the
persistent identity instance, which never has the student's actual cluster
state applied to it.
Fix: this endpoint (POST /api/progress/record) records an outcome WITHOUT
re-running validation — it exists purely so the Gateway can relay a
validate/answer result it already obtained from the real Lab. The Gateway
forwards the real request to the Lab, returns that real response to the
browser unchanged, and separately calls this endpoint with the outcome. See
platform/gateway/src/server.js's relayScenarioOutcome().
Verified end-to-end: a scenario solved through a student's Lab shows up in
their curriculum immediately, survives their lab being destroyed and reset,
and is correctly attributed only to that student (not visible to a second
student's own curriculum view).
Co-Authored-By: Claude Sonnet 5 <[email protected]>