Skip to content

Classroom Read Runtime Smoke

Status: local-non-default-candidate-not-promotion.

This opt-in smoke proves the named Classroom read candidate without using a legacy database, an existing process, or the default Gateway route table. It starts a memory-backed classroom-service and api-gateway on temporary local ports, seeds two organization-scoped classroom snapshots directly through the internal snapshot endpoint, and removes every process it starts and all memory state on exit. With the browser flag, it also starts a disposable Admin Vite candidate and captures its Gateway request, response, headers, telemetry, and screenshot.

Command

bash
cd go-platform
CLASSROOM_READ_RUNTIME_SMOKE_CONFIRM=disposable-runtime \
CLASSROOM_READ_RUNTIME_SMOKE_ADMIN_BROWSER=1 \
CLASSROOM_READ_RUNTIME_SMOKE_ARTIFACT_DIR=output/qa/classroom-read-runtime-$(date +%Y%m%d-%H%M%S) \
make test-classroom-read-runtime

The localhost candidate deliberately fixes its targets to:

  • Classroom service: 127.0.0.1:18101
  • Gateway: 127.0.0.1:18102
  • Admin Vite candidate: 127.0.0.1:18104 when CLASSROOM_READ_RUNTIME_SMOKE_ADMIN_BROWSER=1

The smoke exits before starting if any selected port is already in use. It only stops the process trees it started itself.

Candidate

deploy/gateway/routes.classroom-read-native-localhost-example.json contains only these non-default public shapes:

  • GET /api/classrooms -> GET /v1/classrooms
  • GET /api/classrooms/{classroomId} -> GET /v1/classrooms/{classroomId}

Both require a JWT, organization context, and ADMIN or TEACHER role. The broad /api/classrooms fallback remains legacy_proxy; all write, member, join, purge, progress, lesson, material, tuition, and admin paths remain legacy-proxied.

Assertions

  • A TEACHER token for organization A sends a list request containing organizationId=organization-B; the response remains limited to A and carries X-Hoctapaz-Gateway-Route: classrooms-teacher-list with state native_read.
  • Teacher detail for the A classroom uses classrooms-teacher-detail, returns the A-owned row, and excludes teacherName, fullName, email, profile, and organizationName.
  • A teacher from organization B receives 404 for the A classroom through the same native detail candidate.
  • A PARENT JWT receives 403 AUTH_FORBIDDEN at Gateway; an anonymous request receives 401 AUTH_UNAUTHORIZED.
  • The list request records a local latency sanity value below five seconds. It is diagnostic only and is not a production latency SLO.
  • With CLASSROOM_READ_RUNTIME_SMOKE_ADMIN_BROWSER=1, the Admin candidate restores the canonical nested Gateway session (session.user.defaultOrganizationId), makes exactly one authenticated GET /api/classrooms?limit=100, forwards X-Organization-Id, and renders only the organization A classroom. The captured response must echo the Vite origin through credentialed CORS and identify classrooms-teacher-list / native_read; the browser telemetry latency remains below five seconds.

Latest Local Proof

On 2026-07-13, the disposable runtime plus opt-in Admin browser candidate passed. Both direct Gateway and browser telemetry latencies were below five seconds; the browser sent one organization-scoped request and rendered one class. Artifacts include Gateway headers and response bodies for list, detail, cross-tenant, PARENT, and anonymous requests, plus a redacted browser request, response, headers, telemetry summary, and screenshot:

text
output/qa/classroom-read-admin-browser-runtime-20260713/

Boundary And Rollback

This is local runtime and browser evidence for a non-default candidate only. It is not a default-route change, production deploy, or legacy response parity sign-off. Keep deploy/gateway/routes.json active to rollback; that table did not change in this slice.

Go-platform documentation is generated from repository Markdown.