Files
claudetools/projects/msp-tools/security-assessment/app/questions.json
Mike Swanson 260be8c2ad security.azcomputerguru.com: scaffold the client security-assessment intake app
New MSP tool — single-assessor consult intake. Stack: PHP + MySQL on the IX cPanel
host, gated by Cloudflare Access (only mike@azcomputerguru.com; app re-checks the
Cf-Access-Authenticated-User-Email header).

- app/questions.json — risk-ordered question framework (9 sections); each field tagged
  source=syncro/rmm/scan/ask so the consult asks only what a human knows and the
  post-meeting scan fills the technical reality.
- app/index.php — wizard UI: Syncro phone lookup -> prefill, section rail with live
  progress, importance-colored question cards, in-meeting 365/Google consent links,
  review + export.
- app/api.php — Syncro lookup-by-phone, save/load/list, consent-URL generation (reuses
  the read-only Security Investigator app bfbc12a4-...), HTML export.
- app/schema.sql, config.sample.php, DEPLOY.md, README.md.

Consent links let the client approve read-only 365/Google access during the consult so
the audit scan runs afterward. Read-only by design (reads Syncro, generates consent; no
tenant writes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:20:05 -07:00

156 lines
11 KiB
JSON

{
"version": 1,
"title": "ACG Client Security Assessment",
"note": "Consult intake. Fields marked source=syncro/rmm prefill automatically; source=scan are filled by the post-meeting automated scan (do not ask). Ask only what a human knows.",
"sections": [
{
"id": "identify",
"title": "Client",
"icon": "building",
"intro": "Enter the client's primary phone number to pull their record from Syncro.",
"fields": [
{ "id": "syncro_phone", "label": "Primary phone (Syncro lookup)", "type": "phone", "source": "input", "lookup": true, "required": true, "help": "Identifies the client. Pulls name, address, contact, domain, asset count." },
{ "id": "business_name", "label": "Business name", "type": "text", "source": "syncro" },
{ "id": "syncro_customer_id", "label": "Syncro customer ID", "type": "hidden", "source": "syncro" },
{ "id": "address", "label": "Address", "type": "text", "source": "syncro" },
{ "id": "primary_contact", "label": "Primary contact", "type": "text", "source": "syncro" },
{ "id": "contact_email", "label": "Contact email", "type": "email", "source": "syncro" },
{ "id": "assessment_date", "label": "Assessment date", "type": "date", "source": "auto" }
]
},
{
"id": "scope",
"title": "Scope & Context",
"icon": "target",
"intro": "Sets the scope and risk weighting for the whole audit.",
"fields": [
{ "id": "email_domains", "label": "Email / primary domain(s)", "type": "tags", "source": "syncro", "required": true, "help": "Used to target the 365/Google tenant + DNS/DMARC checks." },
{ "id": "industry", "label": "Industry", "type": "text", "source": "ask" },
{ "id": "employees", "label": "# employees", "type": "number", "source": "ask" },
{ "id": "users", "label": "# of computer/email users", "type": "number", "source": "ask" },
{ "id": "compliance", "label": "Compliance drivers", "type": "multiselect", "source": "ask", "importance": "critical",
"options": ["HIPAA", "PCI-DSS", "CMMC / DFARS", "SOC 2", "GLBA", "FTC Safeguards", "Cyber-insurance requirement", "None / unsure"],
"help": "Drives required controls and report framing." },
{ "id": "sensitive_data", "label": "Sensitive data handled", "type": "multiselect", "source": "ask", "importance": "critical",
"options": ["PHI (health)", "PII (personal)", "Cardholder / payment", "Financial records", "Legal / privileged", "Intellectual property", "None significant"] },
{ "id": "reason", "label": "Reason for assessment", "type": "select", "source": "ask",
"options": ["Proactive / baseline", "Cyber-insurance renewal", "Compliance requirement", "Recent incident / scare", "Client request / concern", "M&A / due diligence"] },
{ "id": "past_incidents", "label": "Known past incidents or breaches?", "type": "textarea", "source": "ask", "help": "Any ransomware, BEC, account takeover, data loss." }
]
},
{
"id": "identity",
"title": "Identity & Email",
"icon": "key",
"intro": "Top attack surface. Capture consent here so the scan can run after the meeting.",
"fields": [
{ "id": "mail_platform", "label": "Email platform", "type": "select", "source": "ask", "importance": "critical",
"options": ["Microsoft 365", "Google Workspace", "On-prem Exchange", "Hybrid (365 + on-prem)", "Other / unsure"], "drivesConsent": true },
{ "id": "tenant_domain", "label": "Tenant / workspace primary domain", "type": "text", "source": "syncro", "help": "Used to resolve the tenant ID + generate the consent link." },
{ "id": "mailbox_count", "label": "# mailboxes / users", "type": "number", "source": "ask" },
{ "id": "global_admins", "label": "# of global/super admins", "type": "number", "source": "ask", "help": "Shared admin accounts are a flag." },
{ "id": "shared_admin", "label": "Shared admin account(s) in use?", "type": "boolean", "source": "ask" },
{ "id": "mfa_belief", "label": "MFA enforced for all users? (their understanding)", "type": "select", "source": "ask",
"options": ["Yes, all users", "Admins only", "Some users", "No", "Unsure"], "help": "Scan verifies the reality." },
{ "id": "conditional_access", "label": "Conditional Access / security defaults?", "type": "select", "source": "ask",
"options": ["Conditional Access policies", "Security defaults on", "Neither", "Unsure"] },
{ "id": "mail_security_layer", "label": "Email security layer", "type": "multiselect", "source": "ask",
"options": ["Mailprotector / CloudFilter", "INKY", "Proofpoint", "Mimecast", "Native EOP / Defender", "None"] },
{ "id": "consent_365", "label": "365 read-only assessment consent", "type": "consent", "provider": "m365", "source": "consent",
"help": "Generates the admin-consent link for the client to approve on the spot." },
{ "id": "consent_google", "label": "Google Workspace read-only consent", "type": "consent", "provider": "google", "source": "consent" }
]
},
{
"id": "backup",
"title": "Backup & Recovery",
"icon": "shield",
"intro": "Business-critical: the difference between an incident and a catastrophe.",
"fields": [
{ "id": "backup_solution", "label": "Backup solution(s)", "type": "text", "source": "ask", "importance": "high" },
{ "id": "backup_scope", "label": "What is backed up", "type": "multiselect", "source": "ask",
"options": ["Servers", "Microsoft 365 / Google data", "Workstations", "NAS / file shares", "Nothing formal"] },
{ "id": "backup_offsite", "label": "Offsite / immutable copy?", "type": "select", "source": "ask",
"options": ["Yes, immutable/air-gapped", "Yes, offsite (mutable)", "Local only", "Unsure"] },
{ "id": "backup_tested", "label": "Last tested restore", "type": "select", "source": "ask",
"options": ["< 3 months", "3-12 months", "> 12 months / never", "Unsure"], "importance": "high" },
{ "id": "rto_rpo", "label": "Recovery expectations (RTO / RPO)", "type": "text", "source": "ask", "help": "How long down / how much data loss is tolerable." }
]
},
{
"id": "endpoints",
"title": "Endpoints",
"icon": "monitor",
"intro": "Counts prefill from GuruRMM where the client is enrolled.",
"fields": [
{ "id": "workstation_count", "label": "# workstations", "type": "number", "source": "rmm" },
{ "id": "server_count", "label": "# servers", "type": "number", "source": "rmm" },
{ "id": "os_mix", "label": "OS mix / any end-of-life?", "type": "multiselect", "source": "rmm",
"options": ["Windows 11", "Windows 10", "Windows 7/8 (EOL)", "Windows Server 2016+", "Server 2012/older (EOL)", "macOS", "Linux"], "importance": "high" },
{ "id": "edr", "label": "Endpoint protection / EDR", "type": "multiselect", "source": "ask",
"options": ["Microsoft Defender", "GuruRMM / managed AV", "SentinelOne", "CrowdStrike", "Other AV", "None / unmanaged"] },
{ "id": "patching", "label": "Patch management", "type": "select", "source": "ask",
"options": ["Managed (us / RMM)", "Managed (other MSP)", "WSUS / internal", "Manual / ad-hoc", "None"] },
{ "id": "disk_encryption", "label": "Disk encryption (BitLocker/FileVault)?", "type": "select", "source": "ask",
"options": ["Yes, enforced", "Some devices", "No", "Unsure"] },
{ "id": "local_admin", "label": "Users have local admin rights?", "type": "select", "source": "ask",
"options": ["No (standard users)", "Some", "Yes (most)", "Unsure"] }
]
},
{
"id": "network",
"title": "Network & Perimeter",
"icon": "globe",
"intro": "External exposure. Exposed RDP is the #1 ransomware entry point.",
"fields": [
{ "id": "firewall", "label": "Firewall make/model", "type": "text", "source": "ask" },
{ "id": "remote_access", "label": "Remote access method(s)", "type": "multiselect", "source": "ask",
"options": ["VPN (UniFi/firewall)", "RDP exposed to internet", "RMM remote (us)", "TeamViewer/AnyDesk", "RD Gateway", "None"], "importance": "critical" },
{ "id": "port_forwards", "label": "Known port-forwards / open inbound services?", "type": "textarea", "source": "ask", "help": "Scan verifies via external port check." },
{ "id": "guest_wifi", "label": "Guest WiFi separated from internal?", "type": "select", "source": "ask",
"options": ["Yes, isolated VLAN/SSID", "Shared with internal", "No guest WiFi", "Unsure"] },
{ "id": "sites", "label": "# of physical sites", "type": "number", "source": "ask" }
]
},
{
"id": "access",
"title": "Access & Operations",
"icon": "users",
"intro": "People and process — where most breaches actually start.",
"fields": [
{ "id": "password_policy", "label": "Password policy / password manager", "type": "select", "source": "ask",
"options": ["Enforced policy + password manager", "Policy only", "Password manager only", "Neither / unsure"] },
{ "id": "offboarding", "label": "Onboarding/offboarding process documented?", "type": "select", "source": "ask",
"options": ["Yes, documented", "Informal", "No"] },
{ "id": "service_accounts", "label": "Shared / service accounts?", "type": "textarea", "source": "ask" },
{ "id": "vendor_access", "label": "Third-party / vendor access to systems?", "type": "textarea", "source": "ask" },
{ "id": "awareness_training", "label": "Security awareness training?", "type": "select", "source": "ask",
"options": ["Yes, ongoing (KnowBe4/etc.)", "One-time", "None"], "importance": "high" }
]
},
{
"id": "cloud",
"title": "Cloud, SaaS & DNS",
"icon": "cloud",
"fields": [
{ "id": "file_sharing", "label": "File sharing / storage", "type": "multiselect", "source": "ask",
"options": ["SharePoint / OneDrive", "Google Drive", "Dropbox", "On-prem file server", "Egnyte / other"] },
{ "id": "critical_saas", "label": "Other critical SaaS apps", "type": "tags", "source": "ask", "help": "Line-of-business apps, accounting, CRM, etc." },
{ "id": "dns_control", "label": "Who controls DNS + domain registrar?", "type": "text", "source": "ask", "help": "Registrar hijack is a top BEC vector." }
]
},
{
"id": "physical",
"title": "Physical & Insurance",
"icon": "lock",
"fields": [
{ "id": "physical_security", "label": "Server/network gear physically secured?", "type": "select", "source": "ask",
"options": ["Locked room/rack", "Office only", "Open / exposed", "Unsure"] },
{ "id": "byod", "label": "BYOD / personal devices on company data?", "type": "select", "source": "ask",
"options": ["No / managed only", "Allowed, managed (MDM)", "Allowed, unmanaged", "Unsure"] },
{ "id": "cyber_insurance", "label": "Cyber-insurance carrier", "type": "text", "source": "ask", "help": "Carrier questionnaires often dictate required controls." }
]
}
]
}