Skip to content

Parent Alert Route Rehearsals

Status: Non-default route-table, live Gateway, and parent-web browser proof; not default-route promotion proof.

This proof covers the parent-facing alert read surface that can be rehearsed against notification-service while default traffic remains legacy-proxied. It does not promote the default route table.

Route Tables

TableTarget
deploy/gateway/routes.jsonDefault rollback table; broad notification, alert, admin, and fallback routes stay legacy_proxy.
deploy/gateway/routes.parent-alerts-native-example.jsonCompose non-default rehearsal targeting http://notification-service:8080.
deploy/gateway/routes.parent-alerts-native-localhost-example.jsonLocalhost non-default rehearsal targeting http://localhost:8092.

The parent-web client keeps normal /parent/alerts navigation on session-local fixtures. It sends the bounded owner read/write requests only for the explicit candidate URL:

text
/parent/alerts?parentAlertsGateway=native

Use that URL only against one of the non-default tables above. This keeps the native-only request set off the default legacy-proxied Gateway route.

When a native alert supplies a child progress link, the client derives the linked childId and keeps it in the alert action URL. Xem tiến độ therefore opens /parent/children/{childId}/progress for that alert rather than silently falling back to the currently selected child. Alerts without a recognized child link use the currently selected child as the UI fallback.

Native Rehearsal Scope

The non-default parent-alert route tables may route only these paths to notification-service:

  • GET /api/parent/alerts
  • POST /api/parent/alerts/{notificationId}/read
  • POST /api/parent/alerts/read-all

Each route must require gateway auth and the global PARENT role. It must not require organization at the gateway because the parent alert UI is scoped by the current parent actor.

Still Legacy

These parent/alert surfaces remain legacy until a separate proof selects and validates them:

  • GET /api/parent/alerts/{notificationId}
  • POST /api/parent/alerts/{notificationId}/delete
  • weak-topic alert creation
  • parent-child relationship lookup
  • broad /api/parent/alerts, /api/notifications, /api/alerts, /api/admin, and fallback behavior

Verification

bash
make test-parent-alert-routes

The guard verifies default rollback state, both non-default route tables, method/suffix specificity, route ordering before broad parent-alert legacy routes, auth requirement, PARENT role enforcement, and absence of gateway organization requirements.

Current Live And Browser Recheck (2026-07-12)

The current Compose notification-service was started on :8092. A temporary Gateway on :18092 used only deploy/gateway/routes.parent-alerts-native-localhost-example.json; the shared default deploy/gateway/routes.json was not changed. Two isolated weak-topic events with one disposable PARENT recipient were created through the Notification Service event owner API.

An HS256 parent bearer token reached GET /api/parent/alerts with 200, X-Hoctapaz-Gateway-Route: parent-alerts-list, and X-Hoctapaz-Gateway-Route-State: native_read.

The parent Vite app then ran against that temporary Gateway. The historical browser rehearsal loaded both owner rows, sent the exact read request for one notification, then sent POST /api/parent/alerts/read-all. The rendered state changed from two unread items to zero, emitted no browser console errors, and the 390px viewport had scrollWidth=390 after the responsive side-panel single-column fix. The isolated rows are removed after the proof; this remains a non-default route rehearsal with explicit fallback behavior in the UI.

The current client guard is covered by apps/parent-web/src/App.test.tsx: normal /parent/alerts makes no owner request and keeps local mark-read behavior, while the explicit candidate URL issues the Gateway list/read/read-all requests and preserves the owner alert's child-specific progress action. The historical runtime capture proves the non-default Gateway route, not default parent-alert promotion.

Result-Release Browser Recheck (2026-07-15)

EXAM_RESULT_RELEASE_RUNTIME_CONFIRM=exam-result-release-isolated make test-exam-result-release-parent-browser creates a MANUAL exam, releases its hidden attempt through the durable Exam to Attempt handoff, resolves the parent only through Profile, and persists the resulting GRADE_RELEASED_PARENT row in Notification before the browser starts. The parent Vite app opens the explicit candidate URL with a signed PARENT token, receives parent-alerts-list / native_read, then marks that exact owner row read with parent-alerts-read / native_write. The latest disposable artifact is output/qa/exam-result-release-notification-runtime-20260715-044805/parent-browser/; its owner list latency was 17 ms and its screenshot proves the 390px viewport.

The proof creates a temporary Gateway route-table copy that targets the disposable Notification port. The shared default route table, local stack, and all legacy data remain untouched; this is still candidate-route evidence only.

Promotion Conditions

Before any default parent-alert route promotion:

  • run the static guard above
  • retain live Gateway proof with a disposable parent account
  • retain browser proof for the parent alert UI path
  • prove rollback by returning to deploy/gateway/routes.json
  • document which weak-topic, parent-child, detail, and delete routes remain legacy

Go-platform documentation is generated from repository Markdown.