Feat/auth#3
Conversation
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
There was a problem hiding this comment.
Pull request overview
This PR replaces the legacy front-end setup (React apps + in-repo router/infra packages) with a new SolidJS-based apps/platform application and introduces new shared UI styles/utilities to support an auth/login experience (including OAuth link buttons).
Changes:
- Added a new SolidJS
apps/platformapp with login page, basic routing, and auth service helpers. - Introduced shared stylesheet set (
stylesheets/) plus small DOM/clock/animation utilities in@repo/shared. - Removed legacy packages/apps (
apps/web,apps/challenge-mf,packages/router,packages/infra) and updated workspace lock/config files (including Git LFS attributes/assets).
Reviewed changes
Copilot reviewed 87 out of 103 changed files in this pull request and generated 20 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Workspace dependency graph updated (adds Solid + new deps; removes React/router/infra deps). |
| packages/shared/tsconfig.json | Adjusts TS config for shared package root dir. |
| packages/shared/src/stylesheets/variables.css | Adds global design tokens (colors/typography/layout). |
| packages/shared/src/stylesheets/typo.css | Adds Google Fonts imports used by the UI. |
| packages/shared/src/stylesheets/reset.css | Updates reset stylesheet used by the new app/shared styles. |
| packages/shared/src/stylesheets/default.css | Adds/adjusts default component styles (buttons, scrollbars, shake anim trigger). |
| packages/shared/src/stylesheets/animations.css | Adds shared keyframe animations (blink/progress-line/shake). |
| packages/shared/src/lib/stateful.ts | Removes old helper (previously used by removed apps). |
| packages/shared/src/lib/double-dollar.ts | Removes old default-export DOM helper (replaced by new dom.ts). |
| packages/shared/src/lib/dom.ts | Adds $$ DOM query helper (throwing querySelector). |
| packages/shared/src/lib/clock.ts | Adds wait(ms) async delay helper. |
| packages/shared/src/lib/anim.ts | Adds text “encryption” animation + shake helper used by login UI. |
| packages/shared/package.json | Updates exports to new stylesheets + new utilities. |
| packages/router/tsconfig.json | Removes legacy router package config. |
| packages/router/tsconfig.build.json | Removes legacy router package build config. |
| packages/router/src/types.ts | Removes legacy router types. |
| packages/router/src/index.ts | Removes legacy client router implementation. |
| packages/router/src/defaults/500.ts | Removes legacy router default error page. |
| packages/router/src/defaults/404.ts | Removes legacy router default not-found page. |
| packages/router/package.json | Removes legacy router package metadata. |
| packages/router/eslint.config.mjs | Removes legacy router ESLint config. |
| packages/infra/src/http/api-client.ts | Removes placeholder infra API client. |
| packages/infra/package.json | Removes infra package metadata. |
| packages/infra/eslint.config.mjs | Removes infra ESLint config. |
| package.json | Renames workspace package + updates formatting script glob. |
| apps/website/.gitkeep | Keeps placeholder website app directory. |
| apps/web/vite.config.js | Removes legacy React app Vite config. |
| apps/web/tsconfig.json | Removes legacy React app TS config. |
| apps/web/src/styles.css | Removes legacy app styles (now moved to shared stylesheets). |
| apps/web/src/main.ts | Removes legacy app entrypoint. |
| apps/web/src/domains/home/layout.ts | Removes legacy home layout template. |
| apps/web/src/domains/home/layout.module.css | Removes legacy home layout styles. |
| apps/web/src/domains/challenge/styles.css | Removes legacy challenge page styles. |
| apps/web/src/domains/challenge/page.ts | Removes legacy challenge page (and MF mounting logic). |
| apps/web/src/app/routes.ts | Removes legacy router route definitions. |
| apps/web/src/app/middleware.ts | Removes legacy route middleware. |
| apps/web/src/app/bootstrap.ts | Removes legacy app bootstrap. |
| apps/web/package.json | Removes legacy app package metadata. |
| apps/platform/vite.config.ts | Adds Solid/Vite config for the new platform app. |
| apps/platform/tsconfig.json | Adds Solid app TS config (paths/JSX settings). |
| apps/platform/src/styles.css | Adds platform-level global layout styling for root/html/body. |
| apps/platform/src/services/auth.service.ts | Adds auth API client + cookie persistence. |
| apps/platform/src/lib/helpers/cookies.ts | Adds cookie set/get/delete helper. |
| apps/platform/src/lib/exceptions/fetch.exceptions.ts | Adds structured request error class. |
| apps/platform/src/lib/env.ts | Adds Vite env accessor helper. |
| apps/platform/src/lib/constants.ts | Adds cookie key constants. |
| apps/platform/src/index.tsx | Adds Solid entrypoint + route definitions + shared stylesheet imports. |
| apps/platform/src/hooks/.gitkeep | Placeholder for hooks directory. |
| apps/platform/src/components/ui/spinner/index.tsx | Adds spinner UI component. |
| apps/platform/src/components/ui/spinner/index.module.css | Adds spinner styling. |
| apps/platform/src/components/molescules/oauth-links/index.module.css | Adds OAuth button styling. |
| apps/platform/src/components/molescules/oauth-links/google.tsx | Adds Google OAuth button component. |
| apps/platform/src/components/molescules/oauth-links/github.tsx | Adds GitHub OAuth button component. |
| apps/platform/src/components/molescules/oauth-links/discord.tsx | Adds Discord OAuth button component. |
| apps/platform/README.md | Adds template README for the new app. |
| apps/platform/public/social-media.png | Adds OAuth icon sprite (via Git LFS). |
| apps/platform/public/rounded.svg | Adds logo SVG. |
| apps/platform/public/rounded.png | Adds logo PNG (via Git LFS). |
| apps/platform/public/mesh.png | Adds background mesh image (via Git LFS). |
| apps/platform/public/long-curlyline.svg | Adds decorative SVG. |
| apps/platform/public/favicon.svg | Adds favicon SVG. |
| apps/platform/public/favicon.png | Adds favicon PNG (via Git LFS). |
| apps/platform/public/curlyline.svg | Adds decorative SVG. |
| apps/platform/public/black-waves.mp4 | Adds background video (via Git LFS). |
| apps/platform/pnpm-lock.yaml | Adds an app-local pnpm lockfile (in addition to workspace lockfile). |
| apps/platform/pages/login/index.tsx | Implements login/sign-up UI, OAuth links, effects, and form validation. |
| apps/platform/pages/login/index.module.css | Styles the login/sign-up page. |
| apps/platform/pages/-/layout/index.tsx | Adds authenticated layout route wrapper with redirect. |
| apps/platform/pages/-/layout/index.module.css | Placeholder stylesheet for layout page. |
| apps/platform/pages/-/home.tsx | Adds a basic authenticated home page reading session cookie. |
| apps/platform/pages/-/game.tsx | Adds a basic game page placeholder. |
| apps/platform/package.json | Adds platform app package metadata/deps/scripts. |
| apps/platform/index.html | Updates HTML entry/root element + title/meta + entry script. |
| apps/platform/eslint.config.mjs | Adds ESLint config for platform app. |
| apps/platform/@types/svg.d.ts | Adds TS module declarations for SVG imports. |
| apps/platform/@types/css-module.d.ts | Adds TS module declarations for CSS imports. |
| apps/platform/.gitignore | Adds app-local gitignore. |
| apps/docs/.gitkeep | Keeps placeholder docs app directory. |
| apps/challenge-mf/vite.config.js | Removes legacy micro-frontend Vite config. |
| apps/challenge-mf/tsconfig.json | Removes legacy micro-frontend TS config. |
| apps/challenge-mf/src/types/css-module.d.ts | Removes legacy CSS module typing file. |
| apps/challenge-mf/src/services/readme/styles.css | Removes legacy readme-renderer styles. |
| apps/challenge-mf/src/services/readme/index.service.ts | Removes legacy readme markdown-to-HTML transformer. |
| apps/challenge-mf/src/components/ui/grid/index.tsx | Removes legacy grid UI component. |
| apps/challenge-mf/src/components/ui/grid/index.module.css | Removes legacy grid styling. |
| apps/challenge-mf/src/components/ui/badge/index.tsx | Removes legacy badge UI component. |
| apps/challenge-mf/src/components/ui/badge/index.module.css | Removes legacy badge styling. |
| apps/challenge-mf/src/components/templates/test-runner/index.tsx | Removes legacy test-runner template. |
| apps/challenge-mf/src/components/templates/test-runner/index.module.css | Removes legacy test-runner styling. |
| apps/challenge-mf/src/components/templates/summary/index.tsx | Removes legacy summary template. |
| apps/challenge-mf/src/components/templates/summary/index.module.css | Removes legacy summary styling. |
| apps/challenge-mf/src/components/templates/code-editor/index.tsx | Removes legacy code-editor template. |
| apps/challenge-mf/src/components/templates/code-editor/index.module.css | Removes legacy code-editor styling. |
| apps/challenge-mf/src/App.tsx | Removes legacy micro-frontend root component. |
| apps/challenge-mf/package.json | Removes legacy micro-frontend package metadata. |
| apps/challenge-mf/lib/entry-server.tsx | Removes legacy SSR entry. |
| apps/challenge-mf/lib/entry-client.tsx | Removes legacy MF mount entry. |
| apps/challenge-mf/eslint.config.mjs | Removes legacy ESLint config. |
| .prettierrc.json | Updates formatting/import-sorting rules (Solid-specific ordering, etc.). |
| .prettierignore | Expands ignored artifacts and ignores lockfile. |
| .gitattributes | Adds Git LFS tracking rules for media assets. |
Files not reviewed (2)
- apps/platform/pnpm-lock.yaml: Language not supported
- pnpm-lock.yaml: Language not supported
Comments suppressed due to low confidence (2)
packages/shared/src/stylesheets/reset.css:5
- Setting
outline: noneglobally removes the default focus indicator for keyboard users, which is a significant accessibility regression. Prefer keeping outlines, or replacing them with an explicit:focus-visiblestyle rather than disabling outlines across all elements.
apps/platform/src/index.tsx:45 routesis an array ofRouteDefinitionobjects, but it is being passed as children to<Router>. In@solidjs/router, route definitions typically need to be converted viauseRoutes(routes)(or rendered via<Route ...>elements). As-is, this likely won’t register any routes and may render[object Object]/ nothing.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| cookies.set(CookieKeys.AccessToken, data.tokens.accessToken, { | ||
| secure: true, | ||
| sameSite: 'Strict', | ||
| expires: new Date(Date.now() + 24 * 60 * 60 * 1000), // 1 day | ||
| }); | ||
| cookies.set(CookieKeys.RefreshToken, data.tokens.refreshToken, { | ||
| secure: true, | ||
| sameSite: 'Strict', | ||
| expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days | ||
| }); | ||
| cookies.set(CookieKeys.Session, JSON.stringify(data.data), { | ||
| secure: true, | ||
| sameSite: 'Strict', | ||
| expires: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days | ||
| }); |
There was a problem hiding this comment.
@copilot can you please create an issue for this exact comment?
There was a problem hiding this comment.
I don't have access to a GitHub issue-creation tool in this environment (the available GitHub MCP tools are read-only, and direct API access to api.github.com is blocked here). Here is the full issue content ready to paste — you can create it at https://github.com/dojoh-dev/platform/issues/new:
Title: Security: Auth tokens stored in JS-readable cookies are vulnerable to XSS token theft
Body:
## Summary
Auth tokens (access/refresh) are currently stored in client-set cookies that are readable by JavaScript. This makes them vulnerable to XSS attacks where malicious scripts can steal tokens.
## Problem
In `apps/platform/src/services/auth.service.ts` (lines 41–55), the login flow stores access/refresh tokens in cookies set via JavaScript. Because these cookies do not have the `HttpOnly` flag, any JavaScript running on the page — including injected scripts via XSS — can read and exfiltrate them.
## Impact
- **High severity**: If an attacker can inject JavaScript (e.g., via XSS in another part of the app), they can steal the user's session tokens and impersonate them.
- Stolen tokens could be used to access protected resources until they expire.
## Recommended Fix
Prefer one of the following approaches:
1. **Server-set `HttpOnly` cookies**: Have the backend set the tokens as `HttpOnly` cookies in the response. This prevents JavaScript from accessing them at all.
2. **In-memory storage**: Keep the access token in memory (a JS variable/signal) and use a refresh token stored in an `HttpOnly` cookie (set by the server). This limits the blast radius of XSS.
3. **Avoid `localStorage` as an alternative** — it is equally vulnerable to XSS.
## References
- [OWASP: Session Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html)
- [OWASP: XSS Prevention Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html)
## Related
Originated from a code review comment on the `Feat/auth` PR, in `apps/platform/src/services/auth.service.ts`.
Suggested label: security
| // Typewriter effect | ||
| createEffect(() => { | ||
| const typewritter = $$<HTMLHeadingElement>('#typewriter'); | ||
| const cursor = $$<HTMLSpanElement>(`#cursor`); | ||
|
|
||
| const phrases = [ | ||
| 'Face another developer in a live coding duel.', | ||
| 'One problem. Two programmers. One winner.', | ||
| 'Compete head-to-head in real-time code battles.', | ||
| 'Your next opponent is already in the queue.', |
There was a problem hiding this comment.
@copilot please suggest the code for this change
There was a problem hiding this comment.
Done in commit c998429. Here's what was changed across all three createEffect blocks:
Typewriter effect — added a stopped flag and tracked timeoutId so the recursive loop is cancelled on unmount:
let stopped = false;
let timeoutId: ReturnType<typeof setTimeout> | null = null;
const typeLoop = async () => {
if (stopped) return;
// ...
if (!stopped) {
timeoutId = setTimeout(typeLoop, 150);
}
};
typeLoop();
onCleanup(() => {
stopped = true;
if (timeoutId !== null) clearTimeout(timeoutId);
});Bubble cursor effect — extracted the three anonymous listeners to named functions so they can be removed:
const onMouseLeave = () => { ... };
const onMouseEnter = () => { ... };
const onMouseMove = (e: MouseEvent) => { ... };
leftSide.addEventListener('mouseleave', onMouseLeave);
leftSide.addEventListener('mouseenter', onMouseEnter);
document.addEventListener('mousemove', onMouseMove);
onCleanup(() => {
leftSide.removeEventListener('mouseleave', onMouseLeave);
leftSide.removeEventListener('mouseenter', onMouseEnter);
document.removeEventListener('mousemove', onMouseMove);
});Sign-up link effect — same pattern for the click listener:
const onClick = (e: MouseEvent) => { ... };
linkTag.addEventListener('click', onClick);
onCleanup(() => { linkTag.removeEventListener('click', onClick); });|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
1 similar comment
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
0a5000f to
633ed57
Compare
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
Auth tokens (access/refresh) are currently stored in client-set cookies that are readable by JavaScript. This makes them vulnerable to XSS attacks where malicious scripts can steal tokens. ProblemIn
|
…route unmount Agent-Logs-Url: https://github.com/dojoh-dev/platform/sessions/ec6becc2-b8ff-4ff1-8c35-53db06a278f8 Co-authored-by: itssimmons <62354548+itssimmons@users.noreply.github.com>
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
|
🧹 Preview no longer available |
|
🚀 Preview deployed: https://platform-preview-3-nnratsflva-uc.a.run.app |
Description
Briefly describe the purpose of this PR.
Changes
How to Test
Describe how reviewers can verify this change.
Checklist