Operations
Runbooks and operational notes. Variable **names** only — never paste real values here.
Operations
Runbooks and operational notes. Variable names only — never paste real values here.
In this section
| File | Purpose |
|---|---|
| This file | Local dev, env variable purposes, technical runbooks |
| product-launch-checklist.md | Master demo tracker — GEO indexing, off-site authority, multi-tenant leads, demo readiness (client_id: jsglobtech) |
| client-engagement-sop.md | Outreach → demo → close loop, plus the recurring obligations each sale creates |
| production-security-audit.md | Production security findings (Critical → Info), blockers, and remediation tracking |
Local development
npm install
cp .env.example .env.local # then fill CRM_WEBHOOK_URL for live lead delivery
npm run dev # http://localhost:3000
- Node.js 20.9+ required (
engines.node);.nvmrcpins major20. - npm scripts:
dev,build,start,lint,kb:sync.
npm run build && npm start # production build check
npm run lint # eslint (flat config, eslint.config.mjs)
Environment variables (purposes, from .env.example)
| Variable | Purpose | Required? |
|---|---|---|
CRM_WEBHOOK_URL |
Default/fallback POST target for validated consultation leads. Without any webhook resolved for the tenant, leads are validated and logged server-side only. | Production (for delivery) |
CLIENT_WEBHOOK_<CLIENT_ID> |
Per-tenant webhook (e.g. CLIENT_WEBHOOK_JSGLOBTECH). Uppercase; non-alphanumeric chars in client_id become _. |
No — multi-tenant |
CLIENT_WEBHOOK_MAP |
JSON map of client_id → webhook URL. Checked before per-tenant env vars. |
No — multi-tenant |
RESEND_API_KEY |
Reserved for future contact-form email delivery. Not wired yet. | No |
CONTACT_TO_EMAIL |
Reserved destination for future contact-form email. Not wired yet. | No |
Resolution order: CLIENT_WEBHOOK_MAP → CLIENT_WEBHOOK_<ID> → CRM_WEBHOOK_URL (lib/leads.ts resolveClientWebhookUrl). Dogfood tenant checklist: ../sales/tenant-demo-checklist.md.
Real values live in .env.local locally and in the host's environment settings for production.
Runbook: lead delivery to Google Sheets
Full guide: scripts/google-apps-script/SETUP.md. Summary:
- Create a Google Sheet (a
Leadstab is auto-created if missing; headers are added on the first lead). - Extensions → Apps Script, paste
scripts/google-apps-script/Code.gs, save. - Deploy → New deployment → Web app: Execute as Me, Who has access Anyone (required so the server can POST without a Google login).
- Authorize, copy the
/execWeb App URL. - Set
CRM_WEBHOOK_URLto that URL in.env.local(and in the host env for production), then restart the dev server.
Keep the Web App URL private — anyone holding it can write rows into the Sheet.
Runbook: leads are not arriving
- Confirm
CRM_WEBHOOK_URLis set in the running environment (unset ⇒ log-only by design). - Check server logs for
LeadWebhookError(includes the upstream HTTP status). - Send a direct test:
POST /api/leads/submitwith a valid payload; avalidation_errorresponse means the payload, not the webhook, is the problem. - Verify the Apps Script deployment is still the active version and access is still Anyone.
Runbook: knowledge base sync
npm run kb:sync # or: bash scripts/kb-sync.sh
bash scripts/kb-sync.sh --no-commit # write files, leave them unstaged
Behaviour: reads knowledge/.kb-state, collects commits on main since that SHA, writes a dated DRAFT to knowledge/changelog/, updates .kb-state, and commits only the files it wrote under knowledge/. It never pushes.
If .kb-state drifts (for example after a history rewrite), the script refuses to run and asks you to reset it. Fix it by setting last_synced_sha= to a commit that is an ancestor of main, or blank it to trigger a fresh backfill.
Install the merge hook once per clone:
bash scripts/install-git-hooks.sh
CI / hosting
- No
.github/workflowsin the repo as of 2026-07-30. - Production hosting / deployment linkage was not verified locally — confirm in the deployment dashboard.
Production security
Before shipping multi-tenant or CRM-backed lead capture, read production-security-audit.md. Summary verdict as of 2026-07-30: not production-ready without hardening (Apps Script auth, real tenant API keys, MCP rate limits, PII/log redaction, input caps, security headers).