# ADR-001: All PWAs Pass ?next= When Redirecting to Hub Login

## Status

Accepted, 2026-06-25.

## Status History

```yaml
status_history:
  - date: 2026-06-25
    status: Proposed
    changed_by: hkl
    reason: Formalising decision already in force across all PWAs
    changed_via: adr-kit (360lm)
  - date: 2026-06-25
    status: Accepted
    changed_by: hkl
    reason: Pattern proven across 19+ PWAs, no exceptions
    changed_via: adr-kit (360lm)
```

## Context

All 360lm PWAs require hub authentication. When a user lands on a PWA without a valid session, the PWA redirects to `/hub/`. Without encoding the originating URL, after login the hub sends the user to the hub home screen — the user must then manually navigate back to where they were. This was a repeated UX complaint during early PWA rollout. The hub login handler already supports a `?next=` query parameter that accepts same-origin relative paths and redirects there after successful login.

## Decision

Every PWA that redirects to `/hub/` for authentication MUST append `?next=<encodeURIComponent(current relative path)>` to the redirect URL.

**Decision Maker:** hkl

## Alternatives Considered

- **Redirect to /hub/ without ?next=.** Rejected: user lands on hub home after login, loses their place — confirmed UX bug in early rollout.
- **Store intended destination in localStorage before redirecting.** Rejected: localStorage is origin-scoped but adds statefulness that breaks multi-tab flows and requires cleanup logic in hub.
- **Use hub session cookie to store return URL server-side.** Rejected: over-engineered; ?next= is stateless, simple, and already implemented in hub.

## Consequences

**Positive:**
- Zero navigation friction after login — user lands exactly where they were going.
- Stateless: no localStorage, no server-side session storage for redirect URL.
- Works correctly in multi-tab scenarios.

**Negative / Trade-offs:**
- Every new PWA developer must know this convention; easy to forget on first PWA.
- URLs with special characters must be properly encoded (use `encodeURIComponent`, not `encodeURI`).

**Risks and mitigations:**
- Open redirect risk if ?next= accepts external URLs — mitigated: hub validates same-origin (relative path only) before following.

## Related Decisions

- None.

## Scope Notes

- Applies to **auth redirects only** (missing/expired/invalid session → hub login, and login links/buttons on a PWA's own login-choice screen). Deliberate navigation (🏡 Hub buttons) and logout redirects go to bare `/hub/` — the user chose to leave.
- `?next=` value MUST be a same-origin **relative path** (`encodeURIComponent(location.pathname + location.search)`). Hub rejects absolute URLs (`hub/index.html` ~line 931) — passing `location.href` silently fails and lands the user on hub home (this exact bug shipped in printing).

## References

- `memory/feedback_hub_next_redirect.md` — original rule capture
- Hub login handler: `hub/index.html` ~line 925 (same-origin validation + redirect)
- Style guide: `docs/style/identity-and-design-system.md` §1 Auth gate row (the canonical snippet every new PWA copies)
- Compliance: full-repo fix 2026-07-12 (activity/expense/hr/production/vehicle/dispatch/printing/oc-admin) after audit `docs/audit_full_adr_sweep_2026-07-03.md`
