feat(web): honour GATEWAY_ENABLED across every remote-assignment surface - #1506
Conversation
Assignments are served through the gateway, and the API only loads AssignmentsModule and GatewayModule when GATEWAY_ENABLED. The frontend only partly reflected that: the sidebar item read the flag back from GET /v1/setup, the subject tab read it from the env config, and the two routes plus the tutorial step were gated on nothing at all. All four now read config.setup.isGatewayEnabled, which is the same env variable the backend switches on. The routes redirect in beforeLoad rather than rendering a page whose endpoints are not mounted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Okay so I see the gateway ,env variable. The problem with using a variable is that the person doing the setup needs to know that they should configure it (and understand what it the flag does) instead of just naturally finding it while poking at the software. If you want to keep it that way, you need to modify the comment in the .env since currently it says: Whether or not the gateway should be activatedThis makes no mention of how it's needed for the remote assignemnts to work. When I first setup ODC I thought gateway = a second server that is outside of the hospital nework, not that gateway was needed for remote assignment functionality. You should change the comment to something like: Controls gateway activation; must be set to true to send remote assignmentsPersonally I'm find with both a .env variable (for those that like them), and having a toggle that overwrites that variable that stores a DB value - your call |
joshunrau
left a comment
There was a problem hiding this comment.
Premise and mechanism both look right — GATEWAY_ENABLED is injected into the bundle at container
start, so config.setup.isGatewayEnabled really is the same value the API switches its module list
on, and the guards sit where apps/web/AGENTS.md says redirects go. Lint is green on the merge
result and the nav-item test does fail when the condition is removed, so it is a real test. Three
things before this merges:
-
/group/email-templatesis a fifth remote-assignment surface and is still ungated. Its entire
body is the assignment-email template manager — the heading is literally "Remote Assignment
Templates" and the subtitle is "Used when emailing a remote assignment link"
(apps/web/src/components/GroupEmailTemplates/GroupEmailTemplates.tsx:188) — and the endpoint
that sends the mail lives in the gateway-gatedAssignmentsModule. Add
config.setup.isGatewayEnabledto the nav condition atapps/web/src/hooks/useNavItems.ts:90and
abeforeLoadguard inapps/web/src/routes/_app/group/email-templates.tsx, the same shape as
the two you added. -
The two new guards have no unit test.
useNavItems.test.tscovers the sidebar only, so the
redirect itself — the part that protects a bookmarked link — is untested in both tiers, which is
not quite what the PR description says. They are easy to reach without a router: mock@/config
withisGatewayEnabled: false, import the route module, and callRoute.options.beforeLoad— it
throws the redirect. I checked that this runs undervitest --project web. The test belongs in
apps/web/src/__tests__/, not undersrc/routes/. -
The Default Assignment Validity (Days) field on
/admin/settings
(apps/web/src/routes/_app/admin/settings.tsx:191) has the same problem in miniature: with the
gateway off it configures something that can never apply. Either gate it too, or add a line to
the PR saying why it is intentionally left alone — theabout.tsx"diagnostics readout"
rationale does not obviously cover a settings input.
If you hand this to Claude Code, Opus 5 is the right size — three files across apps/web plus
new tests, and one of the items is a judgment call rather than a mechanical edit.
Reviewed at commit 3400c0b.
…NABLED Addresses review on #1506. /group/email-templates is a fifth remote-assignment surface: its page is the assignment-email template manager, and the endpoint that sends that mail lives in the gateway-gated AssignmentsModule. Its nav item and route now read config.setup.isGatewayEnabled like the other four. The Default Assignment Validity setting configures the expiry of a remote assignment, so with the gateway off it sets something that can never apply. Its section is hidden rather than left inert. The three beforeLoad guards now have unit tests, so the redirect that protects a bookmarked link is covered rather than only the sidebar. The GATEWAY_ENABLED comment in .env.template said only that it activates the gateway, which does not tell an operator that remote assignments depend on it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replaces #1502, which was closed with:
This is that rewrite. There is no new setting, no schema change and no migration — nothing in
packages/schemas,apps/apior the settings page is touched.What
GATEWAY_ENABLEDalready reaches the frontend asconfig.setup.isGatewayEnabled(
apps/web/src/config.ts), andapps/api/src/main.tsalready mountsAssignmentsModuleandGatewayModulebehindwhen: 'GATEWAY_ENABLED'. But only one of the six surfaces that offer remoteassignments read it — the datahub tab. The sidebar read the API's copy of the flag out of
GET /v1/setup, and the rest checked nothing at all.So on an instance deployed without the gateway you still got a Remote Assignment item in the
sidebar, a tutorial step pointing at an assignments tab that is not rendered, two routes that render
a page whose endpoints were never mounted, a Remote Assignment Templates page whose only consumer
is
POST /v1/assignments/:id/email, and a setting for the default validity of an assignment that cannever be created.
All six now read the config:
setupStateQuery.data.isGatewayEnabledconfig.setup.isGatewayEnabled/session/remote-assignment/dashboard/datahub/$subjectId/assignments/group/email-templates+ its nav item/dashboardisGatewayEnabledstays on$SetupState:about.tsxdisplays it and gates the gateway healthcheckloader on it. That is a diagnostics readout of what the API booted with, which is a genuinely
different question from what the frontend should render, so it keeps using the API value.
Why the validity setting is hidden rather than left alone
It is the one place this rule reaches a setting rather than a route, so it is worth stating. The
value it writes,
defaultAssignmentDurationDays, is read in exactly one place — seeding the expiryfield when creating a remote assignment. With the gateway off it configures nothing. An inert input
is worse than an absent one: an admin who changes it gets a save confirmation and no way to learn it
had no effect. The section and its separator are hidden together, so the card does not grow a stray
divider.
.env.templateThe comment on
GATEWAY_ENABLEDsaid only "Whether or not the gateway should be activated", whichdoes not tell an operator that remote assignments depend on it — the word "gateway" reads as a
deployment topology detail, not a feature switch. It now says it must be true to send remote
assignments.
Tests
apps/web/src/hooks/__tests__/useNavItems.test.ts— the remote-assignment item appears when thegateway is deployed and the user can create an assignment, and is absent when either does not
hold; the email-templates item additionally requires mail to be configured.
apps/web/src/__tests__/gateway-route-guards.test.ts— new, table-driven over all threebeforeLoadguards: each throws a redirect to the right destination with the gateway off, andreturns cleanly with it on. This is the part that protects a bookmarked link, which the sidebar
test does not reach.
testing/src/specs/remote-assignment.spec.ts— a direct-URL navigation to the assignments tab,which exercises
beforeLoadon a cold document load rather than a client-side tab click.The gateway-disabled branch of the guards has no e2e coverage by construction: the suite runs a
single environment with
GATEWAY_ENABLED=true, and the API decides at boot whether the assignmentendpoints exist, so the flag cannot be flipped mid-suite. It is covered in the unit tier instead.
I did get an incidental full-stack look at the disabled path — a local run with
GATEWAY_ENABLED=falsefailed 25 tests, every one of them a test asserting that a remote-assignmentsurface exists, and nothing else. That is the suite reading correct gating as an outage, and it is
about as close to a gateway-off integration check as this repo's shape allows.
pnpm lint(33/33) andpnpm test(726 passed, 1 skipped) are green.pnpm test:e2eis 143/145 ontwo consecutive runs, with a different pair failing each time —
authorization.spec.ts:147twiceon the first run, then
static-pages.spec.ts:52andsubject-detail.spec.ts:51on the second.authorization.spec.tspasses 29/29 run on its own. None of the four touches a gateway surface;they are parallel-load flakes on this machine.
🤖 Generated with Claude Code