diff --git a/README.md b/README.md new file mode 100644 index 0000000..6939bc3 --- /dev/null +++ b/README.md @@ -0,0 +1,278 @@ +# 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