# Codebase Structure

**Analysis Date:** 2026-05-03

## Directory Layout

```
pulse/
├── app/                          # Next.js App Router pages + API routes
│   ├── api/                      # API route handlers (GET/POST/PATCH/DELETE)
│   │   ├── admin/                # Admin settings, users, roles, integrations
│   │   ├── analyzer/             # Ticket analysis, aggregate reports, IT Glue
│   │   ├── auth/                 # Better Auth endpoints
│   │   ├── webhooks/             # Autotask webhook endpoint (public)
│   │   ├── sync/                 # Sync trigger endpoints (public, called by scheduler)
│   │   ├── health                # Health check (public)
│   │   ├── integrations/         # Integration status (public)
│   │   └── …/                    # Other feature APIs (companies, tickets, etc.)
│   ├── admin/                    # /admin landing page + sub-pages (sync, workflow, RMM, IT Glue)
│   ├── analyzer/                 # /analyzer/* pages (tickets, reports, queue)
│   ├── dashboard/                # /dashboard — KPI home
│   ├── status/                   # /status — integration + worker health
│   ├── configuration-items/      # /configuration-items — CI browser
│   ├── engagement/               # /engagement/* — MS Graph employee data
│   ├── backup-status/            # /backup-status — Veeam RPO dashboard
│   ├── veeam-*/                  # Veeam comparison + ticket analysis pages
│   ├── auth/                     # /auth/sign-in, /auth/2fa — magic link flow
│   ├── settings/                 # /settings, /settings/security — user profile
│   ├── kiosk/                    # /kiosk/* — public field app (no nav)
│   ├── mobile/                   # /mobile/* — mobile API endpoints (no nav)
│   ├── styles/                   # CSS modules (brand.css, globals.css)
│   ├── layout.tsx                # Root layout (AppNavigation, CommandPalette, Toaster)
│   └── page.tsx                  # Redirect to /dashboard
│
├── lib/                          # Shared utilities, services, types
│   ├── services/                 # Integration clients + sync/worker logic (~50 files)
│   │   ├── autotask-*.ts         # Autotask API client + sync
│   │   ├── datto-rmm-*.ts        # Datto RMM client + sync
│   │   ├── itglue-*.ts           # IT Glue client + sync
│   │   ├── veeam-*.ts            # Veeam VSPC client + sync
│   │   ├── msgraph-*.ts          # MS Graph client + engagement sync
│   │   ├── engagement-*.ts       # Engagement dashboard data
│   │   ├── analyzer/             # Analyzer pipeline (8 subdirs + 20 files)
│   │   │   ├── pipeline.ts       # 7-stage orchestration
│   │   │   ├── worker.ts         # 2s polling loop (auto-starts in production)
│   │   │   ├── persistence.ts    # Read/write analyzer_analyses
│   │   │   ├── link-discovery.ts # Find related tickets
│   │   │   ├── itglue-search.ts  # Redacted IT Glue lookups
│   │   │   ├── asset-audit/      # IT Glue write-back audits
│   │   │   ├── stages/           # 7 pipeline stages
│   │   │   └── fixtures/         # Test data
│   │   ├── rmm/                  # RMM executor + Overshell
│   │   │   ├── executor.ts       # Validate + enqueue
│   │   │   ├── worker.ts         # 5s polling loop
│   │   │   ├── scripts/          # Script registry (code-defined)
│   │   │   ├── target-resolver.ts
│   │   │   └── …/
│   │   ├── llm/                  # LLM dispatch + cost tracking
│   │   │   ├── call.ts           # Claude + OpenRouter routing
│   │   │   ├── models.ts         # Stage → model mapping
│   │   │   └── pricing.ts        # Cost estimation
│   │   ├── b2/                   # Backblaze B2 object storage
│   │   ├── sync-scheduler.ts     # node-cron singleton (auto-starts)
│   │   ├── sync-service.ts       # Incremental sync orchestration
│   │   ├── entity-sync.ts        # Per-entity Autotask → Postgres
│   │   ├── postgres-client.ts    # DB singleton (query/transaction/upsert)
│   │   ├── integration-health.ts # Health check orchestration
│   │   ├── email.ts              # Email service (magic link)
│   │   ├── webhook-service.ts    # HMAC verification
│   │   ├── redis-client.ts       # Redis cache (optional)
│   │   ├── rate-limiter.ts       # RMM execute limits
│   │   ├── audit.ts              # Audit log writes
│   │   └── (25+ other services for Zoom, Duo, Mimecast, S1, etc.)
│   │
│   ├── types/                    # TypeScript type definitions
│   │   ├── autotask.ts           # Autotask API shapes
│   │   ├── analyzer.ts           # Analysis, stage execution, aggregate report shapes
│   │   ├── database.ts           # DB row types (tickets, companies, etc.)
│   │   ├── sync.ts               # Sync schedule + progress shapes
│   │   ├── veeam.ts              # Veeam shapes
│   │   ├── workflow.ts           # Workflow engine shapes
│   │   ├── datto-rmm.ts          # RMM types
│   │   └── …/
│   │
│   ├── auth.ts                   # Better Auth config + session type
│   ├── auth-utils.ts             # requireAuth(), requireAdmin(), requirePermission()
│   ├── auth-client.ts            # Client-side Better Auth SDK
│   ├── permissions.ts            # Role → resource → action matrix
│   ├── bootstrap.ts              # DEFAULT_ADMIN_EMAIL user creation
│   ├── status-registry.ts        # Priority/status color maps (shared UI state)
│   ├── utils.ts                  # Misc helpers
│   │
│   └── utils/                    # Utility modules
│       ├── env.ts                # Type-safe env var access
│       └── …/
│
├── components/                   # React components
│   ├── ui/                       # shadcn/ui primitives (50+ files)
│   │   ├── button.tsx            # Base button component
│   │   ├── card.tsx              # Card + CardHeader/CardTitle/CardContent
│   │   ├── dialog.tsx            # Modal + trigger + close
│   │   ├── table.tsx             # HTML table wrapper with Tailwind classes
│   │   ├── input.tsx, select.tsx, checkbox.tsx, etc.
│   │   ├── skeleton.tsx           # Loading placeholder
│   │   ├── skeleton-helpers.tsx   # SkeletonRow, SkeletonCard, etc.
│   │   ├── empty-state.tsx        # Zero-data UI
│   │   ├── status-badge.tsx       # Status pill driven by status-registry
│   │   ├── status-light.tsx       # Status indicator dot
│   │   ├── form.tsx              # react-hook-form bridge
│   │   └── …/
│   │
│   ├── navigation/               # Top bar + page structure
│   │   ├── app-navigation.tsx    # NavigationMenu + UserMenu + ThemeToggle
│   │   ├── page-header.tsx       # Title + breadcrumbs + action slot
│   │   ├── command-palette.tsx   # Cmd+K launcher
│   │   ├── mobile-nav.tsx        # Mobile hamburger menu
│   │   ├── user-menu.tsx         # User profile dropdown
│   │   └── status-indicator.tsx  # Top-bar integration health
│   │
│   ├── admin/                    # Admin-specific components
│   │   ├── DataTable.tsx         # Paginated/sortable/searchable table (@tanstack/react-table)
│   │   ├── DetailModal.tsx       # Ticket deep-dive (tabs: status, priority maps)
│   │   ├── SyncScheduler.tsx     # Edit sync schedules
│   │   └── …/
│   │
│   ├── analyzer/                 # Analyzer-specific components
│   │   ├── analyze-button.tsx    # Trigger analysis from ticket
│   │   ├── share-modal.tsx       # Email share dialog
│   │   ├── provider-toggle.tsx   # Anthropic/OpenRouter switch
│   │   ├── related-tickets-panel.tsx
│   │   ├── itglue-suggestions-panel.tsx
│   │   └── …/
│   │
│   ├── rmm/                      # RMM components
│   │   ├── rmm-dispatch-dialog.tsx   # Pick + execute script
│   │   ├── rmm-script-picker.tsx     # Script browser
│   │   ├── rmm-execution-stream.tsx  # Live output tail
│   │   └── …/
│   │
│   ├── dashboard/                # Dashboard-specific components
│   │   ├── kpi-card.tsx          # KPI with delta
│   │   ├── volume-trend.tsx      # 30-day ticket volume chart
│   │   ├── resolution-trend.tsx  # Resolution time chart
│   │   ├── queue-heatmap.tsx     # Queue × priority heatmap
│   │   ├── active-engineers.tsx  # Today's hours logged
│   │   └── …/
│   │
│   ├── configuration-items/      # CI browser components
│   │   └── config-item-modal.tsx # CI detail shell
│   │
│   ├── branding/                 # Wulf branding
│   │   ├── wulf-mark.tsx         # W glyph or wordmark
│   │   └── tagline-footer.tsx    # "Don't be afraid to cry" footer
│   │
│   ├── auth/                     # Auth flow components
│   │   └── auth-provider.tsx     # Better Auth session context
│   │
│   ├── status/                   # Status page components
│   │   ├── worker-pulse.tsx      # Analyzer/RMM/sync heartbeats
│   │   ├── activity-sparkline.tsx # 24h per-worker activity
│   │   └── …/
│   │
│   └── (other feature dirs: backup, settings, tickets, tasks, etc.)
│
├── migrations/                   # Numbered SQL migrations (001–089)
│   ├── 001_initial_schema.sql    # Core schema, audit columns
│   ├── 012_create_auth_tables.sql # Better Auth tables
│   ├── 030_create_workflow_engine_tables.sql
│   ├── 041_create_engagement_tables.sql
│   ├── 069_create_analyzer_tables.sql
│   ├── 077_create_rmm_overshell_tables.sql
│   └── …/
│
├── scripts/                      # One-off operations scripts
│   ├── apply-migrations           # Manual migration runner for existing DB
│   └── …/
│
├── docs/                         # Long-form guides (linked from CLAUDE.md)
│   ├── AUTOTASK_API_GUIDE.md
│   ├── POSTGRES_SYNC_SETUP.md
│   ├── ANALYZER_RUNBOOK.md
│   ├── RMM_OVERSHELL_SPEC.md
│   ├── LOGLIFT_SPEC.md
│   ├── IT_GLUE_AUDIT_SPEC.md
│   └── …/
│
├── public/                       # Static assets (favicon, logos, branding)
│   ├── favicon.png
│   ├── wulff-logo.png
│   └── branding/
│
├── hooks/                        # React hooks (useSearchParams, fetch helpers, etc.)
├── tasks/                        # (Reserved for background tasks; unused today)
├── .planning/                    # GSD planning documents (generated)
├── .env                          # Committed env vars (treat as potentially real secrets)
├── next.config.js                # Turbopack, React compiler, output: standalone
├── tsconfig.json                 # Path alias @/*, strict mode
├── package.json                  # Next 16, React 19, Tailwind 4, shadcn/ui, etc.
├── Dockerfile                    # Standalone build, port 3100
├── docker-compose.yml            # Postgres 16, Redis 7, app
├── CLAUDE.md                     # Repo guide for Claude (read first)
├── ARCHITECTURE.md               # Runtime topology, data flow, workers (read before touching workers)
└── DESIGN.md                     # UI tokens, nav IA, component conventions
```

## Directory Purposes

**`app/`:**
- Purpose: Next.js App Router pages + API routes
- Contains: Page components (`'use client'` with fetch), route handlers (GET/POST/PATCH/DELETE), layout shells
- Key files: `layout.tsx` (root shell), `page.tsx` (redirect to /dashboard)

**`app/api/`:**
- Purpose: HTTP API endpoints called by client or external systems
- Contains: Route handlers exporting GET/POST/PATCH/DELETE
- Patterns: Auth check via `requireAuth()`, delegate to service layer, return `NextResponse.json()`
- Subdirs mirror resources: `admin/`, `analyzer/`, `sync/`, `webhooks/`, etc.

**`lib/services/`:**
- Purpose: Business logic, integration clients, sync orchestration, background workers
- Contains: ~50 files including factories, sync services, analyzer pipeline, RMM executor, integration health checks
- Patterns: Factory pattern for clients, incremental sync via `lastTrackedModificationDateTime`, side-effect import auto-start for workers

**`lib/types/`:**
- Purpose: TypeScript type definitions (no runtime code)
- Contains: Entity shapes (ticket, company, analysis, rmm_execution, etc.), API request/response envelopes
- Organized: By domain (autotask, analyzer, database, sync, workflow, etc.)

**`lib/auth.ts`, `lib/auth-utils.ts`, `lib/permissions.ts`:**
- Purpose: Session management, role-based authorization, permission matrix
- Contains: Better Auth config, `requireAuth()` / `requireAdmin()` / `requirePermission()`, resource → action matrix
- Used by: Every API route handler for access control

**`components/ui/`:**
- Purpose: shadcn/ui primitives (Button, Card, Dialog, Input, Select, Table, etc.)
- Contains: Radix-based components with Tailwind styling
- Pattern: One component per file (e.g., `button.tsx`), default export is the component

**`components/navigation/`:**
- Purpose: Top bar, page headers, breadcrumbs, command palette, mobile menu
- Contains: `app-navigation.tsx` (sticky top bar), `page-header.tsx` (title + actions), `command-palette.tsx` (Cmd+K)
- Used by: Root layout + all pages

**`components/admin/`, `components/analyzer/`, `components/rmm/`, etc.:**
- Purpose: Feature-specific components
- Contains: Reusable UI for that domain (e.g., DataTable, DetailModal, analyze-button)
- Pattern: Exported from kebab-case files (e.g., `analyze-button.tsx` exports `<AnalyzeButton />`)

**`migrations/`:**
- Purpose: Database schema versioning
- Contains: Numbered SQL files (001–089), applied in alphabetical order on Postgres init
- Patterns: `IF NOT EXISTS` for idempotence, `ON CONFLICT DO NOTHING` for seed data, audit columns (`created_at`, `updated_at`, `is_deleted`)
- Important: Never edit a committed migration; add a new one instead. Duplicate numbers exist (002, 004, 009) — apply order is filesystem-alphabetical.

**`scripts/`:**
- Purpose: One-off operations and utilities
- Contains: `apply-migrations` (manual migration runner for existing DB)
- Important: Not tests; not part of the build

**`docs/`:**
- Purpose: Long-form integration and feature guides
- Contains: Setup guides for Autotask, sync architecture, analyzer runbook, RMM/LogLift specs, IT Glue audit spec
- Pattern: One file per major system; referenced from CLAUDE.md, not duplicated in code

**`public/`:**
- Purpose: Static web assets (favicon, logos, branding images)
- Contains: PNG/SVG files served at `/favicon.png`, `/wulff-logo.png`, etc.

## Key File Locations

**Entry Points:**
- `app/page.tsx` — Root page (redirect to /dashboard)
- `app/layout.tsx` — Root layout (AppNavigation, CommandPalette, Toaster, theme provider)
- `app/auth/sign-in/page.tsx` — Magic link entry
- `app/dashboard/page.tsx` — KPI home

**Configuration:**
- `lib/auth.ts` — Better Auth config (magic link, 2FA, Microsoft OAuth)
- `lib/permissions.ts` — Role → resource → action matrix
- `next.config.js` — Turbopack, React compiler, `output: 'standalone'`
- `tsconfig.json` — Path aliases (`@/*`), strict mode
- `.env` — Committed env vars (API keys, secrets — treat as real)

**Core Logic:**
- `lib/services/postgres-client.ts` — DB singleton (query, transaction, upsert)
- `lib/services/sync-scheduler.ts` — node-cron scheduler (auto-starts, self-initializes)
- `lib/services/entity-sync.ts` — Per-entity incremental sync (Autotask, etc.)
- `lib/services/analyzer/pipeline.ts` — 7-stage LLM analysis orchestration
- `lib/services/analyzer/worker.ts` — 2s polling loop (auto-starts in production)
- `lib/services/rmm/executor.ts` — Script validation + rate limiting
- `lib/services/rmm/worker.ts` — 5s polling loop for RMM executions

**Authentication & Authorization:**
- `lib/auth.ts` — Better Auth instance + session type
- `lib/auth-utils.ts` — `requireAuth()`, `requireAdmin()`, `requirePermission()`
- `lib/bootstrap.ts` — Admin user creation from `DEFAULT_ADMIN_EMAIL`
- `middleware.ts` — Session cookie verification (no role checks here)

**Testing:**
- `lib/services/analyzer/*.test.ts` — Unit tests for analyzer (preprocessor, pipeline, link-discovery, itglue-search, itglue-redact)
- `lib/services/rmm/executor.test.ts` — RMM executor tests (rate limiting, script validation)
- `lib/services/b2/client.test.ts` — B2 client tests

**UI & Components:**
- `components/ui/` — shadcn primitives (50+ files)
- `components/navigation/app-navigation.tsx` — Top bar + PageHeader
- `components/navigation/page-header.tsx` — Title + breadcrumbs + action slot
- `components/admin/DataTable.tsx` — Paginated/sortable table (@tanstack/react-table)
- `components/admin/DetailModal.tsx` — Ticket detail tabs

**Types & Schemas:**
- `lib/types/autotask.ts` — Autotask API shapes (ticket, company, contact, etc.)
- `lib/types/analyzer.ts` — Analysis, stage execution, aggregate report shapes
- `lib/types/database.ts` — DB row types (all tables)
- `lib/types/sync.ts` — Sync schedule + progress shapes

**Status Registry (Shared State):**
- `lib/status-registry.ts` — Priority/status color maps, state labels
- Used by: DetailModal, StatusBadge, all pages that display ticket status/priority

## Naming Conventions

**Files:**
- kebab-case: `auth-utils.ts`, `sync-scheduler.ts`, `app-navigation.tsx`
- Pattern: service/factory files end in `-service.ts`, `-factory.ts`, `-client.ts`
- Example: `autotask-client.ts`, `datto-rmm-sync-service.ts`, `msgraph-factory.ts`

**Directories:**
- kebab-case: `api/`, `lib/`, `services/`, `rmm/`, `admin/`
- Resource-based: `app/api/analyzer/`, `app/api/admin/`, `app/analyzer/`
- Subdomain grouping: `lib/services/analyzer/` (pipeline stages + persistence), `lib/services/rmm/` (executor + scripts + worker)

**Components:**
- PascalCase exports from kebab-case files: `analyze-button.tsx` exports `<AnalyzeButton />`
- Wrapper types: `*Modal`, `*Panel`, `*Dialog`, `*Card` (e.g., `DetailModal`, `related-tickets-panel`)

**Functions & Variables:**
- camelCase: `requireAuth()`, `postgresClient.query()`, `getAutotaskClient()`
- Factories: `get<Name>Client()`, `is<Name>Configured()` (e.g., `getDattoRmmClient()`, `isAutotaskConfigured()`)
- Hooks: `useSearchParams()`, `useEffect()`, `useState()`

**Database:**
- snake_case columns: `ticket_id`, `company_id`, `created_at`, `updated_at`, `is_deleted`
- Audit columns: `created_at`, `updated_at`, `synced_at`, `is_deleted`, `deleted_at`
- Tables named for entity plurals: `tickets`, `companies`, `resources`, `contacts`, `analyst_analyses`

**API Responses:**
- camelCase keys (transformed from DB snake_case in route handlers)
- Example: `{ ticketId, companyId, createdAt, updatedAt, isDeleted }`
- Transformation happens in route handler, not ORM-based

## Where to Add New Code

**New Feature (e.g., new integration):**
- Primary code: `lib/services/<integration>-client.ts` + `lib/services/<integration>-factory.ts` + `lib/services/<integration>-sync-service.ts`
- Types: `lib/types/<integration>.ts`
- API routes: `app/api/<resource>/route.ts`
- Pages: `app/<resource>/page.tsx`
- Components: `components/<resource>/*.tsx`
- Tests: `lib/services/<integration>/*.test.ts` (if logic is testable)

**New Component/Module:**
- Implementation: `components/<feature>/<kebab-case-name>.tsx` (or `components/ui/` if it's a primitive)
- Usage: Import via `@/components/<feature>/<kebab-case-name>`

**New Page:**
- File: `app/<route>/page.tsx`
- Layout: Use `PageHeader` + `container mx-auto px-6 py-6` (standard padding)
- Components: Import shared components from `components/`

**Utilities:**
- Shared helpers: `lib/utils/<name>.ts` (e.g., `lib/utils/env.ts` for type-safe env access)
- Service-local helpers: Inline in `lib/services/<name>.ts` if not reused

**Migrations:**
- File: `migrations/NNN_*.sql` (next number in sequence)
- Pattern: `IF NOT EXISTS` for idempotence, `ON CONFLICT DO NOTHING` for seed data
- Audit columns: Include `created_at`, `updated_at`, `is_deleted`, `deleted_at` where applicable
- Important: Never edit a committed migration; create a new one instead

**Tests:**
- Location: `__tests__/` sibling to source file or `.test.ts` / `.spec.ts` suffix
- Framework: `vitest` (import from `vitest`, not `jest`)
- Patterns: Unit tests for analyzer, RMM, B2; other areas are type-checked only

## Special Directories

**`.planning/`:**
- Purpose: Generated GSD (Goal, Scope, Definition) planning documents
- Generated: By `/gsd-map-codebase` with focus areas (tech, arch, quality, concerns)
- Committed: Yes (consumed by `/gsd-plan-phase` and `/gsd-execute-phase`)
- Contains: STACK.md, INTEGRATIONS.md, ARCHITECTURE.md, STRUCTURE.md, CONVENTIONS.md, TESTING.md, CONCERNS.md

**`.env`:**
- Purpose: Environment variables (API keys, secrets, connection strings)
- Committed: Yes (treat values as potentially real production secrets)
- Secrets: DATABASE_URL, REDIS_URL, AUTOTASK_API_URL, BETTER_AUTH_SECRET, LLM keys, etc.
- Important: Never echo or log `.env` contents; don't add `.env.local` to version control

**`node_modules/`, `.next/`, `.git/`:**
- Purpose: Generated directories
- Committed: No (git-ignored)
- Cleaned: `rm -rf node_modules && npm install`, `npm run build && rm -rf .next`

**`public/`:**
- Purpose: Static web assets
- Served: At `/path` (e.g., `/favicon.png`)
- Committed: Yes

**`docs/`:**
- Purpose: Long-form guides
- Committed: Yes
- Pattern: One file per major system (Autotask, Postgres, Analyzer, RMM, etc.)
- Updated: As integration behavior changes; link from CLAUDE.md, don't duplicate in inline comments

---

*Structure analysis: 2026-05-03*
