0008 — Gate the learner-web Sync monitor to admins
Status: done — built 2026-07-10, same day as opened
Opened: 2026-07-10 · Area: learner-web (/sync route, nav, home hero action)
Resolution: canSeeSyncMonitor (learner-web features/auth/lib/policy.ts, wrapping
hasAdminConsoleAccess — the claims were already client-side via the shared auth bindings) gates
the nav button, the home hero action, and the /sync route (no-flash home redirect for
authenticated non-admins). Deliberately no server-side enforcement, per the not-security framing
below. Predicate + redirect covered by unit and render tests.
Evidence
Section titled “Evidence”Surfaced during the prototype-copy rewrite (2026-07-10): the Sync monitor — mutation-queue tiles
(Pending/Sending/Acked/Failed), sync phase, and direct queue controls (flush/retry/reconcile) —
renders unconditionally for every signed-in learner: nav button (__root.tsx ~L228), home
hero action (index.tsx ~L67), and the /sync route itself (no guard, no beforeLoad). The
owner’s working assumption was that it was already restricted to org/platform admins; it is not.
Intent (Anton, verbatim framing)
Section titled “Intent (Anton, verbatim framing)”“This isn’t in any way a security measure, it is just distracting noise for anyone who is not an admin.” The data shown is the learner’s own synced dataset — no confidentiality issue; the queue controls are recoverable diagnostics. The gate is a UX concern: hide the nav item, the home hero action, and ideally the route for non-admin sessions.
Notes for implementation
Section titled “Notes for implementation”- Learner-web needs a client-side “is admin” signal to gate on — check what the session/authClaim actually carries in learner-web before designing (admin-console has scope data; learner-web may not surface roles today). If no signal exists, the smallest honest step is hiding the two links behind a dev/admin flag and leaving the route URL-reachable (explicitly fine given the not-security framing).
- Copy on the screen stays engineer-register (per the prototype-copy rulings); no learner rewrite needed once hidden.