main has been red since 2026-09-22. Because ci.yml's deploy job has needs: [lint, typecheck, test, test-postgres, build], nothing has deployed since - production is still serving 50be0ca, the last green commit, so the auth rework in 437970e has never been live.
Seven tests were failing in both test and test-postgres. Four of them were one bug.
The bug: the app's Auth actions were shadowed by the framework defaults
storage/framework/auto-imports/actions.ts is tracked, and was last regenerated at 2dc1c68 - before 437970e added app/Actions/Auth/. So the four names that commit introduced were still mapped to the framework's own actions:
'Actions/Auth/LoginAction': '../defaults/app/Actions/Auth/LoginAction.ts',
'Actions/Auth/RegisterAction': '../defaults/app/Actions/Auth/RegisterAction.ts',The router's string-handler resolver consults that map first and does not check whether an app file of the same name exists, so every route.post('/login', 'Actions/Auth/LoginAction') in routes/auth.ts resolved to the framework default. The entire auth rework was dead code at runtime:
| Behaviour the app's action implements | What actually happened |
|---|---|
| 10-character password policy | a 9-character password registered fine, 200 |
| email lowercased before lookup | USER@x.test refused 401 |
email-taken pre-check, 409 | 422 from a unique-constraint path |
| the app's own sign-in rate limiting | not applied at all |
201 on register | 200 |
The generator already prefers app/Actions over the defaults - generatePathIndex scans path.appPath("Actions") before frameworkDefaultsDir("app/Actions") and keeps the first key it sees - which is why statushq's registry is correct. This file was simply never regenerated after the actions were added. Regenerated here on the locked 0.74.5; it changes only those four lines.
Worth knowing for next time: autoImportsAreStale() decides by mtime. A fresh CI checkout stamps every file at checkout time, so a stale committed registry is used as though it were current. The resulting failure is silent, because the name still resolves to a real action - just not yours.
The three stale assertions
All three were written against the client pre-paint guard that 437970e deleted along with resources/partials/AuthGuard.stx.
- marketing-links scanned
resources/partials/AuthGuard.stx, which no longer exists, so the test died inreadFileSyncrather than failing an assertion. - reports-surface required
/var/www/reviewos-reviewos/releases/3e057f9/resources/views/layouts/app.stx:3620:2492: include error: Error loading include file AuthGuard: ENOENT: no such file or directory, open '/var/www/reviewos-reviewos/releases/3e057f9/resources/views/partials/AuthGuard.stx' [1m[31m╭──────────────────────────────────────────────────────────────╮[0m [1m[31m│[0m [1m[41m ERROR [0m [31mInclude Error[0m [1m[31m│[0m [1m[31m╰──────────────────────────────────────────────────────────────╯[0m [36m[1mFile:[0m [2mapp.stx[0m [90m(line 3620, col 2492)[0m [33m[1mMessage:[0m Error loading include file AuthGuard: ENOENT: no such file or directory, open '/var/www/reviewos-reviewos/releases/3e057f9/resources/views/partials/AuthGuard.stx' [34m[1mContext:[0m [2m 3618: 3619:mainhas been red since 2026-09-22. Becauseci.yml's deploy job hasneeds: [lint, typecheck, test, test-postgres, build], nothing has deployed since - production is still serving50be0ca, the last green commit, so the auth rework in437970ehas never been live.Seven tests were failing in both
testandtest-postgres. Four of them were one bug.The bug: the app's Auth actions were shadowed by the framework defaults
storage/framework/auto-imports/actions.tsis tracked, and was last regenerated at2dc1c68- before437970eaddedapp/Actions/Auth/. So the four names that commit introduced were still mapped to the framework's own actions:'Actions/Auth/LoginAction': '../defaults/app/Actions/Auth/LoginAction.ts', > 3620: 'Actions/Auth/RegisterAction': '../defaults/app/Actions/Auth/RegisterAction.ts',The router's string-handler resolver consults that map first and does not check whether an app file of the same name exists, so every
route.post('/login', 'Actions/Auth/LoginAction')inroutes/auth.tsresolved to the framework default. The entire auth rework was dead code at runtime:Behaviour the app's action implements What actually happened 10-character password policy a 9-character password registered fine, 200email lowercased before lookup USER@x.testrefused401email-taken pre-check, 409422from a unique-constraint paththe app's own sign-in rate limiting not applied at all 201on register200The generator already prefers
app/Actionsover the defaults -generatePathIndexscanspath.appPath("Actions")beforeframeworkDefaultsDir("app/Actions")and keeps the first key it sees - which is why statushq's registry is correct. This file was simply never regenerated after the actions were added. Regenerated here on the locked 0.74.5; it changes only those four lines.Worth knowing for next time:
autoImportsAreStale()decides by mtime. A fresh CI checkout stamps every file at checkout time, so a stale committed registry is used as though it were current. The resulting failure is silent, because the name still resolves to a real action - just not yours.The three stale assertions
All three were written against the client pre-paint guard that
437970edeleted along withresources/partials/AuthGuard.stx.- marketing-links scanned
resources/partials/AuthGuard.stx, which no longer exists, so the test died inreadFileSyncrather than failing an assertion. - reports-surface required
/var/www/reviewos-reviewos/releases/3e057f9/resources/views/layouts/app.stx:3724:31: include error: Error loading include file AuthGuard: ENOENT: no such file or directory, open '/var/www/reviewos-reviewos/releases/3e057f9/resources/views/partials/AuthGuard.stx' [1m[31m╭──────────────────────────────────────────────────────────────╮[0m [1m[31m│[0m [1m[41m ERROR [0m [31mInclude Error[0m [1m[31m│[0m [1m[31m╰──────────────────────────────────────────────────────────────╯[0m [36m[1mFile:[0m [2mapp.stx[0m [90m(line 3724, col 31)[0m [33m[1mMessage:[0m Error loading include file AuthGuard: ENOENT: no such file or directory, open '/var/www/reviewos-reviewos/releases/3e057f9/resources/views/partials/AuthGuard.stx' [34m[1mContext:[0m [2m 3722: 3723:and an> 3724: Sign in to comment on this pull request. 3725:
3726: @else[0m#auth-requiredelement on both report pages - that is, it asserted the browser guard was still there. Inverted to assert what the test's own name claims: the server reads the session, data is withheld from an unidentified visitor, and nothing gates in the browser. Matched as the directive and the element rather than the bare word, since both pages mention AuthGuard in a comment explaining its removal. Mutation-checked: re-adding/var/www/reviewos-reviewos/releases/3e057f9/resources/views/layouts/app.stx:3752:1: include error: Error loading include file AuthGuard: ENOENT: no such file or directory, open '/var/www/reviewos-reviewos/releases/3e057f9/resources/views/partials/AuthGuard.stx' [1m[31m╭──────────────────────────────────────────────────────────────╮[0m [1m[31m│[0m [1m[41m ERROR [0m [31mInclude Error[0m [1m[31m│[0m [1m[31m╰──────────────────────────────────────────────────────────────╯[0m [36m[1mFile:[0m [2mapp.stx[0m [90m(line 3752, col 1)[0m [33m[1mMessage:[0m Error loading include file AuthGuard: ENOENT: no such file or directory, open '/var/www/reviewos-reviewos/releases/3e057f9/resources/views/partials/AuthGuard.stx' [34m[1mContext:[0m [2m 3750:
- marketing-links scanned