Skip to content

πŸ› fix(auth): serverConfig never re-fetched after in-SPA login β€” auth-gated config keys invisible for the whole first sessionΒ #4538

Closed

Description

@PierreBrisorgueil

What β€” The server config is fetched once, pre-auth (anonymous), and nothing re-fetches it after a successful in-SPA signin/signup. Config keys the API returns only to authenticated callers (e.g. billing.{enabled, meterMode, equivalences} since Node#3566) are therefore absent from serverConfig for the entire first session.

Why β€” Everything gated on those keys silently fails exactly when it matters most β€” a user's first session:

  • app.vue's nav compute gauge (v-if="isLoggedIn && meterMode", meterMode reads serverConfig?.billing?.meterMode) never mounts.
  • signin()'s own post-login meter refresh (auth.store.js:157) is guarded on the same expression β€” dead code in a real session, since the anonymous fetch can never contain billing.
  • A full page reload "fixes" it (the router guard re-fetches with the cookie), which is why the bug hides. OAuth is unaffected (full-page redirect β†’ fresh fetch with cookie).

The bug is generic: any consumer whose config exposes authenticated-only keys has it.

Scope β€” src/modules/auth/stores/auth.store.js:

  • In signin() and signup() success paths (both flip auth in-SPA without a reload): await this.fetchServerConfig() right after the auth state is set, before the meterMode guard, so the guard evaluates against the authenticated config.
  • Failure semantics unchanged (decision 2026-08-04): fetchServerConfig() keeps setting serverConfig = null on failure β€” accepted; a transient failure right after login degrades the config until the next fetch, no special-casing.
  • Tests β€” the existing billing: nav compute gauge not refreshed on login (only on mount/window.focus) β€” stale/empty until page refreshΒ #4261 tests pre-set serverConfig = { billing: { meterMode: true } }, a state unreachable pre-auth, which is exactly what masked this bug. Rework: anonymous config without billing β†’ signin β†’ re-fetch resolves with billing.meterMode: true β†’ fetchUsageMeter called; re-fetch fails β†’ no crash, no meter call; signup path equivalent.

Scope: validated 2026-08-04

Activity

  1. PierreBrisorgueil commented on Aug 4, 2026

    @PierreBrisorgueil
    CollaboratorAuthor

    WIP β€” 2026-08-04T08:28Z β€” autonomous drain

  2. PierreBrisorgueil commented on Aug 4, 2026

    @PierreBrisorgueil
    CollaboratorAuthor

    merged via drain (Automerge: absent, --review: false) β€” PR #4539, squash @ aa47dca. Panel 3/3 merge-safe; the catastrophic probe (authenticated payload failing the sign.in/up validation β†’ serverConfig null after every login) was refuted against the Node controller: the authenticated branch only ADDS keys.

    Non-blocking findings on record (no tickets filed):

    1. signout() never nulls serverConfig β€” stale authenticated config persists into the next anonymous session (pre-existing).
    2. The post-auth /config GET shares the IP-keyed auth rate-limit bucket (10 req/15min prod) β€” a high-friction login (several failed attempts, shared NAT) can get the re-fetch 429'd, probabilistically reintroducing the hidden-gauge symptom for that session.
    3. The two signup re-fetch tests spy on fetchServerConfig itself rather than the axios layer β€” a failure-semantics regression on the signup path would pass CI (signin path tests exercise the real shape).
  3. PierreBrisorgueil commented on Aug 4, 2026

    @PierreBrisorgueil
    CollaboratorAuthor

    Follow-up decision (2026-08-04): finding 1 filed as #4540; findings 2 (rate-limit edge) and 3 (signup spy-only tests) accepted as-is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions