aewing 135087e096 feat: Complete Mode2Svelte with file viewer and token management
- Implemented Graph token lifecycle management with 60s safety buffer
- Added automatic token refresh scheduled 5min before expiry
- Fixed token expiration handling with env variable fallback
- Resolved SharePoint link parsing for both URL formats (RootFolder param and direct pathname)
- Handled URL-encoded spaces in file paths with proper decoding
- Implemented internal file viewer modal staying within app context
- Added file categorization system (Manager Info, Contracts, Plans, Submittals, Other)
- Integrated SVG icons for file types (PDF, Word, Excel, Presentation, Images)
- Added search/filter capability for files in folder view
- Enhanced auth module with improved button click debugging
- Fixed mobile responsiveness for file listing

Changes:
- Mode2Svelte/src/routes/+page.svelte: Complete component rewrite with token management
- Mode2Svelte/src/lib/auth/frontend.ts: Added comprehensive logging for auth flow
- Mode2Svelte/src/routes/api/job-files/+server.ts: Created file access endpoint
- Mode2Svelte/src/routes/api/jobs/list/+server.ts: Added jobs list endpoint

Status: Files now load and display in grouped categories with internal viewer
Next: Fix mobile app authentication issue and further refinements
2026-01-23 05:28:53 +00:00
2025-12-12 10:52:35 -06:00

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:
    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

# 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

# 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=<Azure app client ID>
TENANT_ID=<Azure tenant ID>
CLIENT_SECRET=<Azure app client secret>
PB_URL=<PocketBase server URL>
PB_DB=<PocketBase database name>

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
S
Description
No description provided
Readme 13 MiB
Languages
HTML 41.8%
TypeScript 38.2%
Svelte 16%
JavaScript 3.8%
CSS 0.2%