# Job Info Test - Project Overview ## What is this? **Job-Info-Test** is a modern, modular application testbed for exploring and validating: - **Microsoft Graph API interactions** - token acquisition, caching, refresh, data queries - **PocketBase integration** - OAuth2 flows, user management, data persistence - **Industry-standard UI/UX patterns** - reactive components, state management, real-time updates - **Developer experience (DX)** - clean APIs, TypeScript support, proper error handling, observability - **Architecture best practices** - modular design, separation of concerns, testability It uses a **Mode system** where different technology implementations can be built and tested in parallel without interfering with each other. ## Purpose This is not just an auth test—it's a **reference implementation playground** for: - Building **real, production-quality features** with Graph API (user data, calendar, files, etc.) - Implementing **reactive, modern UI** with Svelte and industry best practices - Creating **clean, maintainable code architecture** that teams can learn from - Testing **complex workflows** combining Graph + PocketBase + custom logic - Demonstrating **proper error handling, loading states, and data synchronization** - Building **DX-first APIs** that are a pleasure to use and extend ## Development Standards **These rules MUST be followed on every code change. Review before editing.** ### 1. Variable Naming — Strict Consistency - Auth and token variable names are **NOT flexible** — they are fixed throughout the project - Use **identical names** every time a value is referenced, passed, or used - **Examples of correct consistency:** - Graph token: always `graphToken` (never `graph_token`, `token`, or `accessToken`) - PocketBase token: always `pbToken` (never `pocketbaseToken`, `pb_token`, or `userToken`) - User ID: always `userId` (never `user_id`, `uid`, or `id`) - Current user: always `currentUser` (never `user`, `loggedInUser`, or `authUser`) - **Why:** Eliminates confusion about what value is being used and where it comes from - **Enforcement:** If a variable name changes, it must change everywhere it's used in that mode ### 2. Mode Independence — Standalone Projects - **Each mode is completely independent** — can run on any machine without parent directory - **Copy modules in, never depend on them externally** - If `auth-module` is used in multiple modes, copy it into each mode's directory - Never import from `../auth-module` or `../../auth-module` - Each mode has its own complete copy of all dependencies - **Modes must not reference each other** - No imports between Mode1 and Mode1Svelte - No shared backend code between modes - **Benefit:** Can delete, move, or duplicate a mode without breaking anything else ### 3. Development Scope — Edit Only Your Mode - **Only edit the mode you're actively working on** — all other modes untouched - **You can reference other modes** for patterns/examples, but don't code in them - **Exception:** Only modify another mode if explicitly agreed upon in writing - **Corollary:** If shared logic needs updating (like auth-module), update it in your working mode, test it, then copy it to other modes if approved ### 4. Ports — 3005 & 3006 ONLY - **Work exclusively with ports 3005 and 3006** - Port 3005: Active mode backend + frontend - Port 3006: ModeSwitch orchestrator - **Do NOT check any other ports** — ignore them entirely - **Ignore all other running services** — focus only on these two ports ### 5. Service Restart — Kill, Then Start - **Always assume something is running** on the port before starting - **Always kill first, then start:** ```bash pkill -f "bun.*server.ts" || true sleep 1 PORT=3005 bun run backend/server.ts ``` - **This prevents port-binding conflicts** and ensures clean startup ### 6. Service Validation — One Check, Then Stop - **Do ONE comprehensive health check after startup** - Verify backend is listening on correct port - Verify frontend is accessible - Verify all critical endpoints respond (auth endpoints, health checks) - Verify no error messages in logs - **Then STOP checking** — if health is good, leave it running - **Do NOT check 3, 4, or multiple times** — it wastes time and adds no value - **If health check passes, service is ready** — move forward to next task ### 7. Git Commits & Sync — Developer Agreement Required - **Never commit or sync without explicit developer approval** - **Only prompt for commit/sync AFTER code verification** - Code must be working as intended - Tests passing (if applicable) - Health checks passing - Developer has confirmed the feature/fix is complete - **Workflow:** Build → Test → Confirm Working → **Then ask about commit** - **No automatic commits or premature prompts** ## Architecture ``` Job-Info-Test/ ├── auth-module/ # Shared, reusable auth component (root copy) ├── Mode1/ # Hono + vanilla JavaScript (LOCKED/READ-ONLY reference) ├── Mode1Svelte/ # Hono + SvelteKit (active development - modern DX/UX) ├── ModeSwitch/ # Orchestrator to manage mode switching ├── Mode6Test/ # Legacy testing environment └── README.md # This file ``` ## The Mode System Each **Mode** is a completely independent project that: - Has its own copy of `auth-module` (no cross-dependencies) - Runs on the same ports (3005 backend, 3006 orchestrator) - Can be swapped via ModeSwitch without affecting others - Shares the same secret configuration (`/home/admin/secrets/.env`) ### Current Modes #### **Mode1** (READ-ONLY Reference Implementation) - **Frontend:** Vanilla HTML + JavaScript - **Backend:** Hono (TypeScript) - **Status:** Reference implementation, locked to prevent accidental changes - **Port:** 3005 #### **Mode1Svelte** (Active Development) - **Frontend:** SvelteKit (Svelte components, reactive) - **Backend:** Hono (same as Mode1) - **Status:** Being converted to full SvelteKit following industry best practices - **Port:** 3005 ## Key Components ### Auth Module (`/auth-module/`) Reusable authentication component with: - **Backend** (`backend.ts`): - `AuthConfigManager` - Loads and provides configuration - `GraphTokenManager` - Acquires Microsoft Graph tokens via MSAL - `PocketBaseValidator` - Validates user tokens - `BackendAuth` - Orchestrates backend auth flow - **Frontend** (`frontend.ts`): - `PocketBaseAuth` - OAuth2 login/logout/state management - `initPocketBaseAuth()` - Initialize with callbacks - **Types** (`types.ts`): - `FrontendConfig` - Configuration provided to frontend - `AuthState` - Frontend authentication state ### ModeSwitch Orchestrator (`/ModeSwitch/`) - Listens on port 3006 - Manages active mode switching via `POST /switch/:mode` - Returns mode status and health checks - Starts/stops backend servers as needed ## How It Works ### Startup Flow 1. **ModeSwitch starts** on port 3006 (orchestrator) 2. **Active mode backend starts** on port 3005 3. **Frontend served** at `http://localhost:3005` (or `https://ji-test.ccllc.pro`) 4. **Frontend fetches config** from `/api/auth/config` 5. **Backend loads secrets** from `/home/admin/secrets/.env` ### Auth Flow 1. **Frontend OAuth Login:** - User clicks login button - Browser redirected to PocketBase OAuth provider - PocketBase returns user and token - Frontend stores token in `pbAuth.getAuthState()` 2. **Backend Graph Token:** - Frontend calls `/api/auth/graph/token` - Backend uses MSAL to acquire Microsoft Graph token - Token cached with 60-second expiration buffer - Frontend receives token with JWT payload details 3. **Token Comparison:** - Frontend sends PocketBase token to `/api/auth/compare-tokens` - Backend validates PB token and decodes Graph token JWT - Returns side-by-side comparison showing they're different systems ## Running the Project ### Via ModeSwitch (Recommended) ```bash # Start ModeSwitch (listens on 3006) cd /home/admin/Job-Info-Test/ModeSwitch PORT=3006 bun run backend/orchestrator.ts # In another terminal, switch to desired mode curl -X POST http://localhost:3006/switch/Mode1Svelte # Access frontend open https://ji-test.ccllc.pro # or open http://localhost:3005 ``` ### Direct Mode Start ```bash # Start Mode1Svelte directly cd /home/admin/Job-Info-Test/Mode1Svelte PORT=3005 bun run backend/server.ts # Access frontend open http://localhost:3005 ``` ## Configuration **Secrets** (`/home/admin/secrets/.env`): ``` CLIENT_ID= TENANT_ID= CLIENT_SECRET= PB_URL= PB_DB= ``` These are loaded: - **Backend:** Automatically on server startup via `dotenv` - **Frontend:** Via API endpoint `/api/auth/config` (no hardcoded URLs) ## Project Structure Details ### Mode1 (Reference - READ-ONLY) ``` Mode1/ ├── auth-module/ # Self-contained copy ├── backend/ │ └── server.ts # Hono + auth endpoints ├── frontend/ │ ├── index.html # Test dashboard │ └── dist/ # Built assets └── package.json ``` ### Mode1Svelte (In Development) ``` Mode1Svelte/ ├── auth-module/ # Self-contained copy ├── backend/ │ └── server.ts # Hono + auth endpoints ├── src/ │ ├── routes/ # SvelteKit pages (to be added) │ ├── lib/ # Svelte components (to be added) │ └── app.svelte # Root component (to be added) └── svelte.config.js # SvelteKit config (to be added) ``` ## Development Notes - **Mode1 is locked** to preserve the reference implementation - **Mode1Svelte** is the active development branch - Both modes can run simultaneously on different orchestrator instances - No code dependencies between modes—each is fully independent - Auth-module changes should be made in root `/auth-module/`, then copied to each mode ## Testing **Dashboard at** `https://ji-test.ccllc.pro`: - ✅ Complete auth flow (PocketBase OAuth2) - ✅ Microsoft Graph token acquisition, caching, refresh - ✅ Real Graph API interactions (user profile, mail, calendar, files, etc.) - ✅ PocketBase data queries and mutations - ✅ Token comparison and validation - ✅ Error states and loading indicators - ✅ Timestamped logs and observability - ✅ Real-time data synchronization patterns ## Next Steps 1. **Convert Mode1Svelte to full SvelteKit** with modern component architecture 2. **Build Graph API features** - implement real use cases beyond auth 3. **Create reactive Svelte components** - proper state management, stores, lifecycle 4. **Add TypeScript throughout** - strict types, better DX 5. **Implement data layers** - abstracting Graph API and PocketBase queries 6. **Build responsive UI** - mobile-first design, accessibility (a11y) 7. **Add observability** - logging, error tracking, performance monitoring 8. **Create component library** - reusable, well-documented Svelte components 9. **Write comprehensive tests** - unit, integration, E2E 10. **Document patterns** - make this a reference for modern full-stack Svelte apps