Eight sub-phases per docs/ticket-analyzer-phase2-spec.md:
2.1 Schema (migration 070): analyzer_stage_executions table; source_snapshot,
aggregate_fingerprint, fingerprint_generated_at columns on analyzer_analyses.
model_traces marked LEGACY (kept for back-compat).
2.2 Every pipeline stage records a row to analyzer_stage_executions, success
or failure. Worker persists a status='failed' analyzer_analyses row when
the pipeline throws so partial stage records have a parent. Pipeline
exposes raw triage/sonnet/opus responses for downstream stages.
2.3 Stage 3 prompt updated with markdown formatting rules + banned filler
phrases. Added react-markdown + remark-gfm + @tailwindcss/typography.
New <AnalysisMarkdown> component replaces <ProseText>; coerces stray
headers to bold paragraphs.
2.4 Stage 6 fingerprint (Haiku) runs after persistence, failure-tolerant.
scripts/backfill-fingerprints.ts reconstructs Stage 6 input from the
legacy model_traces blob.
2.5 Browse UI rebuild at /analyzer/tickets: multi-select for client/issue/
queue/status/priority/assignee, sticky filter bar, active-filter chips,
bulk selection persisted via localStorage, "Analyze N selected" +
"Generate aggregate report" actions. New <MultiSelect> primitive.
Staleness uses last_activity_date > completed_at heuristic per spec C.1.
2.6 Aggregate reports (migration 071): runner is fire-and-forget, persists
SQL distributions immediately so UI shows partial state during the
Sonnet reduce call. Three endpoints, three pages (/analyzer/reports[/new
/:id]). IT Glue context fetcher capped at 200 doc titles.
2.7 Cost guards (migration 072): per-request $5 confirmation, soft-warn at
$20/day, hard-block at $50/day with ANALYZER_DAILY_COST_OVERRIDE_USERS
override. Every gating decision audited.
2.8 Runbook + build notes updated.
128 vitest tests passing, tsc clean. Migrations 070/071/072 idempotent
(IF NOT EXISTS). model_traces double-write retained — drop in a future
migration once aggregate reports have soaked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .firecrawl | ||
| .windsurf/workflows | ||
| app | ||
| components | ||
| dev | ||
| docs | ||
| hooks | ||
| lib | ||
| migrations | ||
| public | ||
| scripts | ||
| tasks | ||
| .dockerignore | ||
| .gitignore | ||
| _clientMiddlewareManifest.json | ||
| ADDIGY_API_GUIDE.md | ||
| AUTOTASK_API_GUIDE.md | ||
| CLAUDE.md | ||
| components.json | ||
| docker-compose.yml | ||
| DOCKER_README.md | ||
| Dockerfile | ||
| eslint.config.mjs | ||
| favicon.0b3bf435.ico | ||
| FIX_TICKET_SYNC.md | ||
| get-config-text.js | ||
| LCI_FEATURE_DESIGN.md | ||
| mcp.json | ||
| middleware.ts | ||
| next-development.log | ||
| next-devtools-config.json | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| postcss.config.mjs | ||
| POSTGRES_SYNC_SETUP.md | ||
| PULSE_DATABASE_SKILL.md | ||
| README.md | ||
| routes.d.ts | ||
| test-config.js | ||
| test-time-entry.js | ||
| tsconfig.json | ||
| vitest.config.ts | ||
Pulse
Internal PSA management dashboard for Wulf Consulting. Pulse syncs Autotask data into Postgres and layers dashboards, ticket workflow automation, and analytics across a number of MSP tooling integrations (Microsoft 365, Datto RMM, Veeam, Auvik, Addigy, IT Glue, Mimecast, SentinelOne, Duo, Zoom, QuickBooks Online, Zabbix, and more).
Stack
- Next.js 16 (App Router) + React 19, TypeScript
- PostgreSQL 16 via
pg(no ORM); Redis for caching - Better Auth — magic link, TOTP 2FA, Microsoft OAuth
- Tailwind 4 + shadcn/ui, recharts, sonner, lucide
- Anthropic SDK for AI triage and analysis features
- node-cron scheduler embedded in the app process
- Docker Compose for local and prod (Traefik-fronted)
Quick start
Prerequisites: Docker + Docker Compose, or Node 20+ and a local Postgres/Redis.
cp .env.example .env.local # if present, otherwise see docker-compose.yml
docker compose up -d # Postgres applies migrations/ on first init
npm install
npm run dev # http://localhost:3100
The first user to authenticate is bootstrapped as super-admin from
DEFAULT_ADMIN_EMAIL.
Scripts
| Command | What it does |
|---|---|
npm run dev |
Next.js dev server on port 3100 |
npm run build |
Production build (turbopack) |
npm start |
Run the built app |
npm run lint |
ESLint |
npx tsc --noEmit --pretty |
Type check (the project's only automated check — there is no test suite or CI) |
Project layout
app/ Next.js App Router — pages and app/api/**/route.ts handlers
components/ Feature components; components/ui/ is shadcn primitives
lib/services/ Integration clients, sync services, scheduler
lib/types/ Shared TypeScript types per domain
lib/auth*.ts Better Auth config and helpers
migrations/ Numbered SQL migrations applied on Postgres init
scripts/ One-off ops/diagnostic scripts (not tests)
docs/ Deep-dive guides per integration and feature
Configuration
All credentials come from environment variables. The major groups:
- Database / cache:
POSTGRES_HOST/PORT/DB/USER/PASSWORD(orDATABASE_URL),REDIS_URL - Auth:
BETTER_AUTH_SECRET,BETTER_AUTH_URL,MICROSOFT_CLIENT_ID/SECRET/TENANT_ID,DEFAULT_ADMIN_EMAIL - Autotask:
AUTOTASK_API_URL,AUTOTASK_USERNAME,AUTOTASK_SECRET,AUTOTASK_API_INTEGRATION_CODE,AUTOTASK_WEBHOOK_SECRET - Microsoft 365 Graph (app):
MSGRAPH_CLIENT_ID/SECRET/TENANT_ID - Other integrations:
DATTO_RMM_*,VEEAM_VSPC_*,AUVIK_*,ADDIGY_*,ITGLUE_*,MIMECAST_*,S1_*,DUO_*,ZOOM_*,QBO_*,ZABBIX_*,SALESBLDR_* - AI:
ANTHROPIC_API_KEY
See AUTOTASK_API_GUIDE.md and ADDIGY_API_GUIDE.md for credential setup.
docs/ has per-integration guides for the rest.
Documentation
CLAUDE.md— repo orientation for AI coding sessions; also a useful overview for new contributorsAUTOTASK_API_GUIDE.md,ADDIGY_API_GUIDE.md— credential setupPOSTGRES_SYNC_SETUP.md— database initializationDOCKER_README.md— Docker workflowPULSE_DATABASE_SKILL.md— diagnostic SQL queriesdocs/wulf-pulse-ticket-analyzer-runbook.md— AI ticket analyzer operator runbook (cost monitoring, IT Glue alias map, failure triage)docs/— sync behavior, webhook setup, workflow editor, per-integration guides
Deployment
Production runs via docker compose up -d behind Traefik. The app is reachable
at pulse.wulfconsulting.cloud. There is no CI/CD pipeline — deploys are manual
(rebuild image, recreate containers).
License
Internal use only.