wulf-pulse/.planning/codebase/STRUCTURE.md
lorentz 9658640c04 fix(04-01): restore phase 2/3 work lost by worktree soft-reset
The soft reset to 77073ba inadvertently staged deletions of all phase 2
and 3 artifacts. This commit restores them from their source commits so
subsequent task commits build on the complete prior-phase foundation:
- components/mobile/{BottomNav,HeaderBar,KpiCardMobile,MoreDrawer,NeedsAttentionStrip,WorkerStatusRow}
- app/mobile/layout.tsx, dashboard/page.tsx, analyzer/page.tsx
- app/api/mobile/dashboard/route.ts
- All .planning/** files from phases 01-04
- CLAUDE.md, app/layout.tsx, app/styles/brand.css, public/manifest.json
2026-05-03 18:01:14 -04:00

22 KiB
Raw Blame History

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 (001089)
│   ├── 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 (001089), 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.tsrequireAuth(), 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