Migrate pal-e-app auth + data fetching to client-side #52

Closed
opened 2026-03-27 00:22:26 +00:00 by forgejo_admin · 2 comments

Type

Feature

Lineage

Depends on forgejo_admin/pal-e-app#51 (convention-sveltekit-spa must exist first as the spec).

Repo

forgejo_admin/pal-e-app

User Story

As pal-e-app
I want to authenticate via keycloak-js + PKCE and fetch data client-side with Bearer tokens
So that I have no server secrets and work as a true SPA

Context

pal-e-app currently uses Auth.js with server-side Keycloak OIDC sessions and loads all data via +page.server.ts files. The platform SvelteKit convention (Phase 29) requires keycloak-js + PKCE for client-side auth and client-side fetch() with Bearer tokens. mcd-tracker-app already implements this pattern successfully. This migration is a prerequisite for switching to adapter-static (issue #53).

The app currently uses TypeScript with typed API responses via src/lib/api.ts. The replacement client-side API module should remain TypeScript (api-client.ts) to preserve the type system.

Keycloak client pal-e-app should be created in the pal-e realm (matching existing platform apps) as a public client with PKCE. Current code references the master realm — this must change.

File Targets

Files to create:

  • src/lib/keycloak.ts — keycloak-js OIDC wrapper (model on ~/mcd-tracker-app/src/lib/keycloak.js, but in TypeScript)
  • src/lib/api-client.ts — client-side fetch with Bearer token (model on ~/mcd-tracker-app/src/lib/api.js, but in TypeScript preserving existing type interfaces)

Files to modify:

  • src/routes/+layout.svelte — add keycloak init + auth guard, remove Auth.js session references
  • src/routes/+page.svelte — client-side data loading instead of server data prop
  • src/routes/boards/+page.svelte — client-side data loading
  • src/routes/boards/[slug]/+page.svelte — client-side data loading
  • src/routes/notes/+page.svelte — client-side data loading
  • src/routes/notes/[slug]/+page.svelte — client-side data loading
  • src/routes/notes/[slug]/edit/+page.svelte — client-side data loading (if kept) or remove
  • src/routes/projects/+page.svelte — client-side data loading
  • src/routes/projects/[slug]/+page.svelte — client-side data loading
  • src/routes/repos/+page.svelte — client-side data loading
  • src/routes/search/+page.svelte — client-side data loading
  • src/routes/dashboard/+page.svelte — client-side data loading
  • src/routes/tags/+page.svelte — client-side data loading
  • src/routes/tags/[name]/+page.svelte — client-side data loading (if exists)
  • src/lib/components/QuickJot.svelte — update to use client-side API + auth token
  • src/lib/slugCache.ts — update or remove if it depends on server-side imports
  • package.json — remove @auth/sveltekit and Auth.js deps, add keycloak-js

Files to remove:

  • src/auth.ts — Auth.js configuration
  • src/hooks.server.ts — Auth.js server hooks
  • src/routes/+layout.server.ts — server-side session loading
  • src/routes/+page.server.ts — server-side data loading
  • src/routes/boards/+page.server.ts
  • src/routes/boards/[slug]/+page.server.ts
  • src/routes/notes/+page.server.ts
  • src/routes/notes/[slug]/+page.server.ts
  • src/routes/notes/[slug]/edit/+page.server.ts (if exists)
  • src/routes/projects/+page.server.ts
  • src/routes/projects/[slug]/+page.server.ts
  • src/routes/repos/+page.server.ts
  • src/routes/search/+page.server.ts
  • src/routes/dashboard/+page.server.ts
  • src/routes/tags/+page.server.ts
  • src/routes/tags/[name]/+page.server.ts (if exists)
  • src/routes/signin/ — entire directory
  • src/routes/signout/ — entire directory
  • src/routes/api/ — entire directory (proxy routes no longer needed)
  • src/lib/api.ts — server-side API client (replaced by api-client.ts)

Files the agent should NOT touch:

  • svelte.config.js — adapter switch is issue #53
  • Dockerfile — Dockerfile switch is issue #53
  • k8s/ — k8s changes are issue #53

Acceptance Criteria

  • keycloak-js handles login/logout/token refresh
  • All routes load data client-side with Bearer tokens
  • No +page.server.ts files remain
  • No $env/dynamic/private imports remain anywhere
  • Auth.js fully removed (src/auth.ts, hooks.server.ts, @auth/sveltekit from package.json)
  • Public routes (unauthenticated) still work without login
  • Authenticated routes redirect to Keycloak login
  • Keycloak client pal-e-app created in pal-e realm (public client, PKCE)
  • TypeScript type interfaces preserved in api-client.ts
  • QuickJot component works with client-side auth

Test Expectations

  • E2E: unauthenticated user sees public content
  • E2E: authenticated user can access boards, dashboard, quick-jot
  • E2E: login redirects to Keycloak and returns with session
  • Build: npm run check passes (no type errors)
  • Run command: npm run test:e2e && npm run check

Constraints

  • Model auth on ~/mcd-tracker-app/src/lib/keycloak.js — proven pattern
  • Model API client on ~/mcd-tracker-app/src/lib/api.js — proven pattern
  • Keep TypeScript — do not downgrade to JavaScript
  • Must create Keycloak client in pal-e realm (not master)
  • No Tailwind — pure CSS (per existing convention)
  • Keep adapter-node during this ticket — adapter switch is issue #53

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • forgejo_admin/pal-e-app#51 — convention must exist first
  • forgejo_admin/pal-e-app#53 — depends on this ticket
  • project-pal-e-docs — pal-e-app is the frontend for this project
  • convention-sveltekit-spa — the spec this follows
### Type Feature ### Lineage Depends on `forgejo_admin/pal-e-app#51` (convention-sveltekit-spa must exist first as the spec). ### Repo `forgejo_admin/pal-e-app` ### User Story As pal-e-app I want to authenticate via keycloak-js + PKCE and fetch data client-side with Bearer tokens So that I have no server secrets and work as a true SPA ### Context pal-e-app currently uses Auth.js with server-side Keycloak OIDC sessions and loads all data via +page.server.ts files. The platform SvelteKit convention (Phase 29) requires keycloak-js + PKCE for client-side auth and client-side fetch() with Bearer tokens. mcd-tracker-app already implements this pattern successfully. This migration is a prerequisite for switching to adapter-static (issue #53). The app currently uses TypeScript with typed API responses via `src/lib/api.ts`. The replacement client-side API module should remain TypeScript (`api-client.ts`) to preserve the type system. Keycloak client `pal-e-app` should be created in the `pal-e` realm (matching existing platform apps) as a public client with PKCE. Current code references the `master` realm — this must change. ### File Targets Files to create: - `src/lib/keycloak.ts` — keycloak-js OIDC wrapper (model on ~/mcd-tracker-app/src/lib/keycloak.js, but in TypeScript) - `src/lib/api-client.ts` — client-side fetch with Bearer token (model on ~/mcd-tracker-app/src/lib/api.js, but in TypeScript preserving existing type interfaces) Files to modify: - `src/routes/+layout.svelte` — add keycloak init + auth guard, remove Auth.js session references - `src/routes/+page.svelte` — client-side data loading instead of server data prop - `src/routes/boards/+page.svelte` — client-side data loading - `src/routes/boards/[slug]/+page.svelte` — client-side data loading - `src/routes/notes/+page.svelte` — client-side data loading - `src/routes/notes/[slug]/+page.svelte` — client-side data loading - `src/routes/notes/[slug]/edit/+page.svelte` — client-side data loading (if kept) or remove - `src/routes/projects/+page.svelte` — client-side data loading - `src/routes/projects/[slug]/+page.svelte` — client-side data loading - `src/routes/repos/+page.svelte` — client-side data loading - `src/routes/search/+page.svelte` — client-side data loading - `src/routes/dashboard/+page.svelte` — client-side data loading - `src/routes/tags/+page.svelte` — client-side data loading - `src/routes/tags/[name]/+page.svelte` — client-side data loading (if exists) - `src/lib/components/QuickJot.svelte` — update to use client-side API + auth token - `src/lib/slugCache.ts` — update or remove if it depends on server-side imports - `package.json` — remove @auth/sveltekit and Auth.js deps, add keycloak-js Files to remove: - `src/auth.ts` — Auth.js configuration - `src/hooks.server.ts` — Auth.js server hooks - `src/routes/+layout.server.ts` — server-side session loading - `src/routes/+page.server.ts` — server-side data loading - `src/routes/boards/+page.server.ts` - `src/routes/boards/[slug]/+page.server.ts` - `src/routes/notes/+page.server.ts` - `src/routes/notes/[slug]/+page.server.ts` - `src/routes/notes/[slug]/edit/+page.server.ts` (if exists) - `src/routes/projects/+page.server.ts` - `src/routes/projects/[slug]/+page.server.ts` - `src/routes/repos/+page.server.ts` - `src/routes/search/+page.server.ts` - `src/routes/dashboard/+page.server.ts` - `src/routes/tags/+page.server.ts` - `src/routes/tags/[name]/+page.server.ts` (if exists) - `src/routes/signin/` — entire directory - `src/routes/signout/` — entire directory - `src/routes/api/` — entire directory (proxy routes no longer needed) - `src/lib/api.ts` — server-side API client (replaced by api-client.ts) Files the agent should NOT touch: - `svelte.config.js` — adapter switch is issue #53 - `Dockerfile` — Dockerfile switch is issue #53 - `k8s/` — k8s changes are issue #53 ### Acceptance Criteria - [ ] keycloak-js handles login/logout/token refresh - [ ] All routes load data client-side with Bearer tokens - [ ] No +page.server.ts files remain - [ ] No $env/dynamic/private imports remain anywhere - [ ] Auth.js fully removed (src/auth.ts, hooks.server.ts, @auth/sveltekit from package.json) - [ ] Public routes (unauthenticated) still work without login - [ ] Authenticated routes redirect to Keycloak login - [ ] Keycloak client `pal-e-app` created in `pal-e` realm (public client, PKCE) - [ ] TypeScript type interfaces preserved in api-client.ts - [ ] QuickJot component works with client-side auth ### Test Expectations - [ ] E2E: unauthenticated user sees public content - [ ] E2E: authenticated user can access boards, dashboard, quick-jot - [ ] E2E: login redirects to Keycloak and returns with session - [ ] Build: `npm run check` passes (no type errors) - Run command: `npm run test:e2e && npm run check` ### Constraints - Model auth on `~/mcd-tracker-app/src/lib/keycloak.js` — proven pattern - Model API client on `~/mcd-tracker-app/src/lib/api.js` — proven pattern - Keep TypeScript — do not downgrade to JavaScript - Must create Keycloak client in `pal-e` realm (not `master`) - No Tailwind — pure CSS (per existing convention) - Keep adapter-node during this ticket — adapter switch is issue #53 ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `forgejo_admin/pal-e-app#51` — convention must exist first - `forgejo_admin/pal-e-app#53` — depends on this ticket - `project-pal-e-docs` — pal-e-app is the frontend for this project - `convention-sveltekit-spa` — the spec this follows
Author
Owner

Scope Review: NEEDS_REFINEMENT

Review note: review-413-2026-03-26

File targets are incomplete -- 6 files missing from scope (auth.ts, hooks.server.ts, notes/[slug]/edit/, tags/[name]/, QuickJot.svelte, slugCache.ts). Dependency #51 (convention-sveltekit-spa) is still open and the convention note does not exist yet.

Must fix before READY:

  • Add src/auth.ts and src/hooks.server.ts to "Files to remove"
  • Add src/routes/notes/[slug]/edit/ and src/routes/tags/[name]/ to both modify and remove lists
  • Add src/lib/components/QuickJot.svelte to "Files to modify" (uses /api/notes proxy being removed)
  • Add src/lib/slugCache.ts to "Files to modify" (imports from $lib/api being removed)
  • Document type migration strategy (6 files import TS types from $lib/api)
  • Clarify Keycloak realm (master in current code vs pal-e in issue) and client creation method
  • Add missing acceptance criteria: no $env/dynamic/private imports remain; type imports resolve
  • Add story:X label to board item #413
  • Document VITE_ env var naming for client-side API URL
  • Wait for #51 (convention-sveltekit-spa) to be completed first
## Scope Review: NEEDS_REFINEMENT Review note: `review-413-2026-03-26` File targets are incomplete -- 6 files missing from scope (auth.ts, hooks.server.ts, notes/[slug]/edit/, tags/[name]/, QuickJot.svelte, slugCache.ts). Dependency #51 (convention-sveltekit-spa) is still open and the convention note does not exist yet. **Must fix before READY:** - Add `src/auth.ts` and `src/hooks.server.ts` to "Files to remove" - Add `src/routes/notes/[slug]/edit/` and `src/routes/tags/[name]/` to both modify and remove lists - Add `src/lib/components/QuickJot.svelte` to "Files to modify" (uses `/api/notes` proxy being removed) - Add `src/lib/slugCache.ts` to "Files to modify" (imports from `$lib/api` being removed) - Document type migration strategy (6 files import TS types from `$lib/api`) - Clarify Keycloak realm (`master` in current code vs `pal-e` in issue) and client creation method - Add missing acceptance criteria: no `$env/dynamic/private` imports remain; type imports resolve - Add `story:X` label to board item #413 - Document `VITE_` env var naming for client-side API URL - Wait for #51 (convention-sveltekit-spa) to be completed first
Author
Owner

Closing — work completed and merged. Board item confirmed done.

Closing — work completed and merged. Board item confirmed `done`.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/pal-e-docs-app#52
No description provided.