Decoded the Syncro RMM installer URL from 4 client samples:
base64(v1-{customer_id}-{A}-48753-{policy_folder_id}). 48753 = our account id (constant);
customer_id + policy_folder_id are API-readable; A is an unguessable per-client security token
NOT exposed anywhere in the API -> the URL is NOT constructible and must be harvested per client
and vaulted. Installer is an MSI -> deploy uses msiexec /qn /norestart.
deploy-agent now reads clients/<slug>/syncro-agent-installer (credentials.installer_url) from
the vault (cascades-tucson, grabb-durando, reliant, howard-test seeded) and pushes via GuruRMM.
Findings recorded in test-findings.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Test campaign on Howard Test sandbox (customer 36118743) surfaced traps the skill must not
re-learn:
- invoice/estimate email endpoints return 200 "Email sent" even with NO recipient
(customer.email null) -> never report delivery from the 200; verify customer.email first.
- customer.email is UNIQUE tenant-wide; PUT /customers failure returns
{success:false,message:[...]} not {customer:{...}} -> check .success.
- POST/PUT /contacts return a FLAT object (.id), not {contact:{...}}; contact recipient
flags (primary/receives_invoices) are ignored via API.
- POST /contracts write succeeds but body doesn't echo the object; /contracts?customer_id
doesn't filter server-side -> GET-verify + client-filter.
New living log .claude/standards/syncro/test-findings.md; critical items folded into
syncro.md Hard Rules + Verified Response Shapes. Correction logged to errorlog.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add comprehensive Syncro coverage beyond PSA core:
- New .claude/standards/syncro/api-reference.md: complete verified inventory of ~180
endpoints across 38 resource types (generated from live OpenAPI 3.0 spec + tenant
probe 2026-07-10), with worked GET/POST/PUT/DELETE templates and token-capability matrix.
- /syncro: asset read intelligence (patches, installed_applications), asset create/update,
policy-folder move (move-asset), RMM alerts, and deploy-agent (hybrid installer push via
GuruRMM using SyncroSetup --console --allow-force-reboot).
- move-asset ships a capability preflight (GET /policy_folders?customer_id -> 401 = missing
Assets-Policy-Change) + mandatory post-write verify, because an under-scoped token returns
HTTP 200 and silently no-ops the move.
Correct the "Syncro RMM is API-impossible" belief: it was a token-scope gap, not an API
limit. Live-verified the asset move (flip-and-restore 692253->692278->692253). Token scope
today: Howard + Winter full; Mike (vaulted ...ebbeb3) still 401 pending re-vault.
Corrects memory reference-syncro-rmm-api-gui-only; correction logged to errorlog.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Point the superproject at the tested guru-scan commit: RKill -w process
whitelist (spares the PowerShell host + running GuruRMM/Syncro/Datto EDR/
ScreenConnect/Bitdefender/MSP360/Splashtop agents), Datto EDR folders added to
the HitmanPro/Emsisoft exclusion list, and cleanup guard so scan logs/archives
are never deleted.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two defects found while running /wiki-compile, both from tooling assuming
a path instead of resolving it.
1. Plaintext Syncro API keys. Mike's and Howard's live PSA keys were
copy-pasted into three command files, a script, and two catalog docs --
despite both already being vaulted at msp-tools/syncro and
msp-tools/syncro-howard. Replaced with reads from the SOPS vault via a
new sourced helper, .claude/scripts/syncro-env.sh. Write paths fail
closed; read-only paths degrade to skipped enrichment rather than a
wrong key. Per-user mapping is unchanged, so Syncro attribution is too.
2. Hardcoded repo root. wiki-compile/wiki-lint/inject-standards and
gen_b64.py hardcoded D:/claudetools; this machine is C:/claudetools.
syncro.md also read ~/.claude/identity.json before the repo copy -- the
same bug that made remediation-tool's consent-audit report a fully
consented tenant as RED. Root now resolves from the script's own
location, with identity.json claudetools_root as the override.
get-identity.sh had a chicken-and-egg bug: it read ${CLAUDETOOLS_ROOT:-.}
but never set it, so every caller had to already know the root. It now
self-resolves and exports CLAUDETOOLS_ROOT + VAULT_ROOT.
Verified: all three command setup blocks authenticate against live Syncro;
get-identity.sh works from any cwd and honors a pre-set root; gps-rmm
autoenroll resolves its key from the vault. security-review: no findings.
NOTE: both keys remain valid in git history. Rotation in the Syncro portal
is the required follow-up -- this commit does not resolve that exposure.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extension 109 (Kayla Guerrero) - Phone MAC last 4: 73b7
Extension 117 (Jesse III) - Phone MAC last 4: 6cf5
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 113 (Chris Guerrero) - Phone MAC last 4: 755b
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 106 (Tammy) - Phone MAC last 4: 6a36
Documented for device assignment workflow after second CSV batch.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 103 (Rose Guerrero) - Phone MAC last 4: 5217
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 110 (Ron Winger) - Phone MAC last 4: 6509
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 105 (J.R. Guerrero) - Phone MAC last 4: 7441
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 114 (Ty Fetters) - Phone MAC last 4: 6d01
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Extension 102 (Jesse Sr) - Phone MAC last 4: 7559
Extension 116 (Bart) - Phone MAC last 4: a890
Documented for device assignment workflow.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
CLARIFIED (2026-07-10):
- Extension 117: Jesse III
- Email: jesse@nescoap.com (external domain)
- Similar to ext 114 (Ty@CASARICA.NET - external domain)
- Status: Ready to add to second CSV batch
UPDATED:
- Matched users: 12 -> 13 (Jesse III now matched)
- Unmatched users: 6 -> 5 (removed Jesse III from unmatched list)
- Will be included in second CSV import with other clarified/shared extensions
FILES MODIFIED:
- extension-mapping.md: Updated ext 117 to show jesse@nescoap.com
- PROVISIONING-STATUS.md: Moved ext 117 to clarified section
- README.md: Updated user counts and user summary
CURRENT STATUS:
- 11 users in CSV ready for bulk import (102-116 minus gaps)
- 2 users for separate provisioning (101 Natalya, 117 Jesse III)
- 5 users still need clarification (106, 108, 111, 112, 118)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Removing onmicrosoft.com from M365 usernames needs sifoidak.com verified as a custom
Entra domain, which needs a DNS TXT record at GoDaddy. Mike confirmed ACG has no
registrar access to that account, so UPNs stay on sifoidak.onmicrosoft.com and new
users follow the same convention. Recorded as decided rather than blocked so it is
not re-proposed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sif-oidak was documented as a hybrid AD/M365 environment. It is not: there is no
Entra Connect on either DC, no AD object carries msDS-ConsistencyGuid, and every
M365 user has onPremisesSyncEnabled=null. AD and M365 are disjoint, and email is a
third system entirely (sifoidak.com at GoDaddy; the O365_BUSINESS SKU carries the
EXCHANGE_S_FOUNDATION no-mailbox stub).
That mismatch caused a real failure: Dwayne Ortega had a cloud account only, so he
could not log in to a domain-joined workstation. Created his AD account and recorded
the two-account onboarding rule.
Also documented: printer error 740 (Point-and-Print driver install needs admin,
UAC prompt never surfaces), a GPO pushing the MX-6240N queue from the wrong server,
SIF-SERVER2 confirmed as a backup DC, and refreshed stale laptop agent UUIDs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>