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
13 KiB
13 KiB
External Integrations
Analysis Date: 2026-05-03
APIs & External Services
Autotask PSA:
- Primary integration — syncs projects, tickets, time entries, contacts, configuration items to Postgres
- SDK/Client:
lib/services/autotask-factory.ts→getAutotaskClient(),lib/services/autotask-client.ts - Auth env vars:
AUTOTASK_API_URL,AUTOTASK_USERNAME,AUTOTASK_SECRET,AUTOTASK_API_INTEGRATION_CODE - Webhook secret:
AUTOTASK_WEBHOOK_SECRET— HMAC-SHA1 verification inlib/services/webhook-service.ts - Sync service:
lib/services/entity-sync.ts(incremental vialastTrackedModificationDateTimewhen supported) - Webhook handler:
/api/webhooks/autotask(public endpoint)
Microsoft Graph:
- User/employee engagement data (calendar, presence, mail metrics)
- SDK/Client:
lib/services/msgraph-factory.ts→getMsgraphClient(),isMsgraphConfigured(),lib/services/msgraph-client.ts - Auth env vars:
MSGRAPH_CLIENT_ID,MSGRAPH_CLIENT_SECRET,MSGRAPH_TENANT_ID(specific tenant, NOT 'common') - Flow: client_credentials OAuth — no user interaction required
- Sync service:
lib/services/engagement-sync-service.ts - API:
/api/engagement/sync(POST fire-and-forget, GET status),/api/engagement/summary,/api/engagement/users,/api/engagement/user/[userId] - Scheduler:
engagement-dailytask (disabled by default, 6am UTC)
Microsoft OAuth (Login):
- SSO via Microsoft identity
- Auth env vars:
MICROSOFT_CLIENT_ID,MICROSOFT_CLIENT_SECRET(same as above; tenant-aware) - Integrated into Better Auth 1.4 —
lib/auth.tsconfiguresmicrosoftsocial provider - Account linking enabled: Microsoft OAuth can link to existing accounts
Datto RMM:
- Remote device management — sites, devices, alerts
- SDK/Client:
lib/services/datto-rmm-factory.ts→getDattoRMMClient(),lib/services/datto-rmm-client.ts - Auth env vars:
DATTO_RMM_API_URL,DATTO_RMM_API_KEY,DATTO_RMM_API_SECRET - Sync service:
lib/services/datto-rmm-sync-service.ts(on-demand or scheduled) - API:
/api/datto-rmm/sync(public POST, fire-and-forget) - Alternate simpler client:
lib/services/datto-rmm-client-simple.tsavailable
Veeam Backup & Replication:
- Backup infrastructure data — sites, repositories, jobs, backup chains
- SDK/Client:
lib/services/veeam-factory.ts→getVeeamClient(),isVeeamConfigured(),lib/services/veeam-client.ts - Auth env vars:
VEEAM_VSPC_URL,VEEAM_VSPC_API_KEY - Shadow mode:
VEEAM_RPO_SHADOW_MODE=true(default) - Sync service:
lib/services/veeam-sync-service.ts - API:
/api/veeam/sync(public POST),/api/veeam/rpo-check(public POST, RPO health check)
Auvik:
- Network monitoring — devices, interfaces, metrics
- SDK/Client:
lib/services/auvik-factory.ts→getAuvikClient(),lib/services/auvik-client.ts - Auth env vars:
AUVIK_API_URL,AUVIK_API_USER,AUVIK_API_KEY
Addigy:
- Apple device management
- SDK/Client:
lib/services/addigy-factory.ts→getAddigyClient(),clearAddigyClientCache(),lib/services/addigy-client.ts - Auth env vars:
ADDIGY_API_URL(default:https://api.addigy.com/api/v2),ADDIGY_API_TOKEN,ADDIGY_ORG_ID(optional)
IT Glue:
- Documentation platform — organizations, configurations, passwords, flexible assets
- SDK/Client:
lib/services/itglue-client.ts(direct client, no factory) - Auth env var:
ITGLUE_API_KEY(x-api-key header) - Base URL:
https://api.itglue.com - Format: JSON:API (application/vnd.api+json)
- Search function for analyzer:
lib/services/analyzer/itglue-search.ts(redacted output before LLM prompts) - Sync service:
lib/services/itglue-sync-service.ts - API:
/api/itglue/sync(public POST, fire-and-forget)
Mimecast:
- Email security — threat/policy logs
- SDK/Client:
lib/services/mimecast-client.ts(direct client, no factory) - Auth env vars:
MIMECAST_CLIENT_ID,MIMECAST_CLIENT_SECRET,MIMECAST_ACCOUNT_CODE,MIMECAST_BASE_URL(default:https://api.services.mimecast.com)
SentinelOne:
- EDR/XDR — agents, threats, sites, groups
- SDK/Client:
lib/services/sentinelone-client.ts(direct client, no factory) - Auth env var:
S1_API_KEYorSENTINELONE_API_KEY - Sync service:
lib/services/sentinelone-sync-service.ts - API:
/api/sentinelone/sync(public POST, fire-and-forget)
Duo Security:
- 2FA/MFA monitoring — users, phones, auth logs, accounts
- SDK/Client:
lib/services/duo-client.ts(direct client, no factory) - Auth env vars:
DUO_IKEY,DUO_SKEY,DUO_HOST— HMAC-SHA1 request signing - Supports both Accounts API (parent) and Admin API (parent + child accounts)
- API:
/api/duo(public POST; Duo-specific endpoints for sync, data retrieval)
Zoom:
- Videoconferencing — meeting analytics, users
- SDK/Client:
lib/services/zoom-factory.ts→getZoomClient(),isZoomConfigured(),lib/services/zoom-client.ts - Auth env vars:
ZOOM_ACCOUNT_ID,ZOOM_CLIENT_ID,ZOOM_CLIENT_SECRET— Server-to-Server OAuth - Sync service:
lib/services/zoom-sync-service.ts - API:
/api/zoom/sync(public POST, fire-and-forget)
QuickBooks Online:
- Accounting — invoices, payments, deposits, purchases, journal entries
- SDK/Client:
lib/services/qbo-client.ts(singleton, uses DATABASE_URL) - Auth env vars:
QBO_CLIENT_ID,QBO_CLIENT_SECRET,QBO_REALM_ID - OAuth2 token management: tokens stored in
qbo_tokenstable (migration 014), auto-refreshed - Sandbox mode:
QBO_SANDBOX=trueswitches to sandbox URL - Callback:
/api/qbo/auth(public POST, OAuth redirect),/api/qbo/disconnect(public POST) - Sync service:
lib/services/qbo-sync-service.ts - API:
/api/qbo/sync(public POST, fire-and-forget)
Zabbix:
- Infrastructure monitoring — events, problems, hosts, metrics
- SDK/Client:
lib/services/zabbix-client.ts(direct client, no factory) - Auth env vars:
ZABBIX_API_URL,ZABBIX_API_TOKEN - Webhook handler:
/api/zabbix/webhook(public POST)
SalesBldr:
- Sales engagement platform
- SDK/Client:
lib/services/salesbldr-client.ts(direct client, no factory) - Auth env vars:
SALESBLDR_API_URL,SALESBLDR_API_KEY
ipinfo.io:
- IP geolocation (optional)
- Auth env var:
IPINFO_TOKEN(optional, defaults to empty)
Data Storage
Databases:
- PostgreSQL 16 — Primary data store
- Connection:
POSTGRES_HOST,POSTGRES_PORT(5432),POSTGRES_DB,POSTGRES_USER,POSTGRES_PASSWORD(orDATABASE_URL) - Client:
lib/services/postgres-client.tssingleton viapostgresClient.query(),.transaction(),.upsert(),.bulkUpsert() - Migrations:
migrations/*.sql(numbered sequentially, applied in alphabetical order on Postgres init) - All columns:
snake_case; API responses:camelCase(manual transformation) - Audit columns:
created_at,updated_at,synced_at,is_deleted,deleted_at
- Connection:
Cache:
- Redis 7 (optional)
- Connection:
REDIS_URL(e.g.,redis://localhost:6380in Docker) - Client:
lib/services/redis-client.tsviagetRedisClient(),getCachedData(),setCachedData(),flushCache() - TTL default: 300 seconds (5 minutes)
- Graceful fallback: if REDIS_URL unset or connection fails, caching disabled
- Connection:
Authentication & Identity
Auth Provider:
- Better Auth 1.4 — Magic link + TOTP 2FA + Microsoft OAuth
- Implementation:
lib/auth.tsconfigures plugins, session TTL, roles (user, admin, super-admin) - Database: Tables created in migration 012 (user, session, account, verification)
- Default admin bootstrap: via
DEFAULT_ADMIN_EMAILenv var,lib/bootstrap.ts - Session cookie handling: next-js plugin enabled
- Account linking: Microsoft OAuth can link to existing accounts
- Roles:
super-admin,admin,user - RBAC:
lib/permissions.tsdefinesac(access-control) rules
- Implementation:
API Route Auth:
- Helpers in
lib/auth-utils.ts:requireAuth(),requireAdmin(),requireSuperAdmin(),requirePermission(resource, action) - Middleware:
middleware.tschecks session cookie existence; role verification happens in API routes - Public routes: hardcoded in
middleware.ts(webhooks, sync endpoints, health checks, auth callbacks, mobile, openclaw, kiosk, legal)
Monitoring & Observability
Error Tracking:
- None (no Sentry/DataDog integration detected)
Logs:
- Console logging:
console.log(),console.error() - Slow query warnings: queries > 1000ms logged in
postgresClient.query()
AI & LLM
Analyzer Pipeline:
- Primary: Anthropic Claude API
- SDK:
@anthropic-ai/sdk0.91.1 - Auth:
ANTHROPIC_API_KEYenv var - Models: Haiku (stage 1, 6), Sonnet (stage 2, 5), Opus (stage 3, 4)
- Worker:
lib/services/analyzer/worker.ts(auto-starts in production, polled every 2s) - Pipeline:
lib/services/analyzer/pipeline.ts(6 stages: triage, analysis, reasoning, fingerprint, aggregate, link-discovery) - Cost guard:
lib/services/analyzer/cost-guard.ts(skips Opus above $2.00 estimated cost, flags for review) - Idempotency: per-request provider-scoped (
anthropic|openrouter); same ticket can have both
- SDK:
Alternate Provider:
- OpenRouter (opt-in per request)
- SDK: HTTP client, OpenAI-compatible format
- Auth:
OPENROUTER_API_KEYenv var - Models: DeepSeek V4 Flash (fast), DeepSeek V4 Pro (standard), DeepSeek R1 (reasoning)
- Call layer:
lib/services/llm/openrouter-call.ts - Provider hints:
data_collection: 'deny'(privacy floor),sort: 'throughput',allow_fallbacks: true
Model Constants:
lib/services/llm/models.ts— canonical model IDs and stage-model mappings- Anthropic:
claude-haiku-4-5,claude-sonnet-4-6,claude-opus-4-7 - OpenRouter:
deepseek/deepseek-v4-flash,deepseek/deepseek-v4-pro,deepseek/deepseek-r1-0528
- Anthropic:
Pricing & Token Tracking:
lib/services/llm/pricing.ts— per-token cost calculationlib/services/analyzer/cost-guard.ts— estimated cost ceiling enforcement
File Storage
Backblaze B2 (S3-compatible):
- LogLift evidence upload/download
- Auth env vars:
B2_KEY_ID,B2_APP_KEY - Config env vars:
B2_BUCKET(default:wulf-audits),B2_REGION(default:us-west-002),B2_ENDPOINT(default:s3.us-west-002.backblazeb2.com) - SDK/Client:
lib/services/b2/client.ts— presigned URLs (AWS SigV4), download/upload with object-key validation - Max download: 25 MB
- Object key format validation:
{client_id_or_uuid}/{computer_name}/eventlogs_{timestamp}.json.gz(path-traversal guard)
CI/CD & Deployment
Hosting:
- Docker Compose (provided in
docker-compose.yml) - Traefik labels for reverse-proxy routing at
pulse.wulfconsulting.cloud - Standalone Next.js output for containerization
CI Pipeline:
- None detected; local testing only (vitest)
- Build:
npm run build(turbopack) - Type check:
npx tsc --noEmit --pretty - Lint:
npm run lint(eslint)
Webhooks & Callbacks
Incoming Webhooks:
/api/webhooks/autotask— Autotask event notifications (public, HMAC-SHA1 verified)/api/zabbix/webhook— Zabbix problem notifications (public)/api/rmm/loglift— LogLift evidence uploads (public, verified viax-openclaw-keyheader)/api/qbo/auth— QuickBooks OAuth callback (public)/api/qbo/disconnect— QBO token revocation (public)
Outgoing Webhooks:
- Autotask write-back: workflow engine executes Autotask API calls (POST notes, status updates, custom fields)
- Workflow execution:
lib/services/workflow-engine.tschains actions after classification
Fire-and-Forget Sync Endpoints:
/api/datto-rmm/sync(POST)/api/veeam/sync(POST)/api/veeam/rpo-check(POST)/api/itglue/sync(POST)/api/sentinelone/sync(POST)/api/engagement/sync(POST)/api/zoom/sync(POST)/api/qbo/sync(POST)- All public, triggered by admin UI or cron schedule in sync-scheduler
Environment Configuration
Required env vars (production):
BETTER_AUTH_URL— must match deployed domainBETTER_AUTH_SECRET— session signing secretDATABASE_URLorPOSTGRES_*— database connectionAUTOTASK_API_URL,AUTOTASK_USERNAME,AUTOTASK_SECRET,AUTOTASK_API_INTEGRATION_CODE— Autotask APIMICROSOFT_CLIENT_ID,MICROSOFT_CLIENT_SECRET,MICROSOFT_TENANT_ID— OAuth loginANTHROPIC_API_KEY— AI Analyzer (required if analyzer enabled)DEFAULT_ADMIN_EMAIL— initial super-admin account
Optional env vars:
REDIS_URL— enables caching; graceful no-op if missingMSGRAPH_*— Microsoft Graph (engagement sync)DATTO_RMM_*,VEEAM_VSPC_*,AUVIK_*,ADDIGY_*,ITGLUE_API_KEY,MIMECAST_*,S1_API_KEY,DUO_*,ZOOM_*,QBO_*,ZABBIX_*,SALESBLDR_*— per-integrationOPENROUTER_API_KEY— alternate LLM providerB2_*— LogLift evidence storageIPINFO_TOKEN— optional IP geolocation
Secrets location:
.env.local(development, mounted read-only in Docker)- Environment variables passed to container (production)
- Note:
.envfile is committed to the repository; treat values as potentially real.
Integration disable mechanism:
- Two sources (merged):
INTEGRATIONS_DISABLEDenv var (legacy, comma/space-separated keys; aliases:sentinelone→s1,datto→datto_rmm,it-glue→itglue,ms-graph→msgraph)integration_settingstable (migration 081) — admin-toggled at/admin/integrationswithout restart; cache invalidation immediate; audit columns:disabled_by,disabled_at,disabled_reason
Integration audit: 2026-05-03