- CODING_GUIDELINES.md: tighten parity rule wording to match Mike's intent:
"add feature X" means Windows + Linux + macOS in the same commit
- memory: add feedback_gururmm_agent_parity for future session enforcement
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Hook was querying only to_session=HOSTNAME/claude-main, missing messages
addressed to the short alias (e.g. "howard"). Now reads identity.json for
the alias and queries both, merging results before display.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Full tenant verification sweep: all Intune/Entra objects match session logs
- Entra Connect staging mode exited; 17 AD groups synced to cloud
- CA policies (Block-off-network, Sign-in-frequency-8h, Block-non-compliant) patched from SG-Caregivers-Pilot to AD-synced SG-Caregivers
- Registration Campaign exclusion updated to SG-Caregivers
- Deleted test accounts: howard.enos (AD) and pilot.test (M365)
- Documented Christine Nyanzunda collision risk, Ederick Yuzon open item, standing security-group rule
- Session log written
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Block inline pwsh -Command/-c (force .ps1 file approach) and
Windows backslash paths in Bash commands (enforce forward slashes).
Eliminates the 2-3 retry loop on PowerShell operations and prevents
the /tmp path mismatch that caused the stale-payload Syncro incident.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CLAUDE.md: triggers now query coordination API (/api/coord/status,
/api/coord/components, /api/coord/messages) instead of reading
PROJECT_STATE.md files
- COORDINATION_PROTOCOL.md: new doc covering locks, component states,
workflows, work items, and inter-session messages via ClaudeTools API
- guru-rmm/PROJECT_STATE.md: marked ARCHIVED, redirects to
COORDINATION_PROTOCOL.md for live state
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add hard rule: 9269129 (Prepaid Project Labor) is Exempt and does NOT deduct
from prepay_hours block — never use for normal work (verified 2026-05-04)
- Expand prepay_hours check from emergency-only to ALL billing workflows
- Fix emergency/prepaid branching table to use delivery-channel product instead
of hardcoding 26118 (Onsite) for remote and other labor types
- Clarify invoice step 15: $0.00 invoice total is correct for prepaid customers;
verify by checking customer.prepay_hours dropped by quantity
- Field 7 (Assigned Tech): add explicit default to API key owner; mark as MUST
always be included in POST payload to prevent null user_id on ticket create
- Add billing workflow hard rule: read prepay_hours before any billing, not just
emergency, so prepaid invoice behavior is known before execution begins
Triggered by ticket #32265 (Russo Law Firm) missing assignee/priority/billing.
Russo Law has 12.5 prepaid hrs — 0.5 hrs correctly deducted via invoice #67578.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Deletions (~1,500 lines of dead docs):
- .claude/hooks/ — docs-only directory, no executables. Referenced scripts
setup-context-recall.sh / test-context-recall.sh did not exist. Hooks
would have POSTed to localhost:8000; the API actually ran at
172.16.3.30:8001 and is no longer in use.
- .claude/AUTO_CONTEXT_SYSTEM.md — 347-line duplicate spec of CLAUDE.md's
Automatic Context Loading section, referencing unimplemented hooks.
- .claude/URGENT-vault-path-bug.md — 217-line urgency note for a fix that
already shipped weeks ago.
- .claude/context-recall-config.env.example — config template for the same
dead system.
Refactors (~500 lines net removed):
- /save and /sync now wrap bash .claude/scripts/sync.sh as the single
source of truth for git ops. /save adds a session-log-writing step in
front; /sync invokes the script directly.
- Dropped /sync's manual git phases that contradicted sync.sh.
- Dropped the cp -r ~/ClaudeTools/.claude/commands/* ~/.claude/commands/
step (clobbered per-user customization in the multi-user model).
- Dropped auto-invoke of /refresh-directives (command does not exist).
- Dropped references to directives.md (file does not exist).
- /save now documents the rm -f save_narrative_prompt.txt step, fixing
the stale-prompt bug Howard documented in feedback_tmp_path_windows.md.
Fixes:
- CLAUDE.md SESSION_STATE.md reference replaced with the canonical
PROJECT_STATE.md (per-project, with protocol at
.claude/PROJECT_STATE_PROTOCOL.md). 16 client folders already use
PROJECT_STATE.md; SESSION_STATE.md was only a stale reference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auth selection logic:
- Default: prefer cert when cert_thumbprint_b64url + cert_private_key_pem_b64
are present in the vault entry's credentials block; fall back to client_secret.
- REMEDIATION_AUTH=secret -> force client_secret flow.
- REMEDIATION_AUTH=cert -> force cert flow; error if cert fields missing.
- Logs [INFO] auth=cert/secret to stderr so users see which path was taken.
Cert flow signs an RS256 JWT (header includes x5t) via inline Python (PyJWT
+ cryptography), POSTs client_assertion_type +
client_assertion=<jwt> in place of client_secret. Same scope, same cache, same
error handling (AADSTS7000229 still emits the consent URL).
Single sops -d to a mktemp file feeds both field reads to avoid repeated
~1s decrypt invocations on Windows; trap removes plaintext on exit.
Verified end-to-end against tedards.net for all three modes after wiping
/tmp/remediation-tool/.
- Promote timer_entry → charge_timer_entry to default billing path; demote
bare add_line_item to a clearly-labeled fallback for non-time items only.
Mike caught the bare-add_line_item bug across 31 tickets on 2026-04-30;
repeated on 3 tickets 2026-05-01. Time entries are required for Syncro
reporting (hours per client, tech productivity, prepay burn).
- Replace /tmp/*.json payload pattern with heredoc throughout. /tmp resolves
to C:\tmp\ in the Write tool but %LOCALAPPDATA%\Temp\ in Git Bash on
Windows — different real directories. Caused a wrong-comment incident on
ticket #32225 2026-05-01 (rogue payload from prior session). Heredoc
avoids the file handoff entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three tickets billed today: #32225 Sombra ($525 onsite), #32229 Mineralogical
Record ($262.50 emergency), #32214 Cascades Entra (33.5 hrs project labor at $0
debits prepaid block). Hit a real incident on Sombra: rogue comment posted with
content from a different ticket because /tmp resolves differently in the Write
tool (C:/tmp/) vs Git Bash (%LOCALAPPDATA%/Temp/) on Windows. Howard manually
deleted from GUI; subsequent posts used heredoc to avoid the file handoff
entirely. Root cause documented in feedback_tmp_path_windows.md so future
sessions don't trip the same wire. Scheduled remote agent
trig_01CAfvwoQ4nLcKEqbU4UQmSa to update the syncro skill examples 2026-05-02.
Created memory entry documenting correct way to verify ticket-invoice linkage
in Syncro API after 2026-04-30 incident where faulty verification script
falsely claimed 31 tickets had no invoices (actually 29 had invoices properly,
2 were correctly Non-Billable).
Key lessons:
- List endpoint does NOT return ticket_id or line_items
- Must query individual invoices for full data
- Invoice numbers are strings, not integers
- Use ticket ID (internal), not ticket number (user-visible)
Added to memory index for future GrepAI semantic search.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Cascades caregiver shared-phone bypass pilot — 2026-04-29 evening into
2026-04-30 early morning continuation.
Major work:
- Adopted phased per-group CA rollout (corrects original tenant-wide §5
design that would have blocked off-site office users)
- Step A: backfilled admin@ into excludeUsers on all 8 existing Cascades
CA policies (mirrors sysadmin@ exclusion posture; Option 1 break-glass)
- Outlook + Helpany + LinkRx assigned to Cascades - Shared Phones group
and added to MHS kiosk app list (final dashboard: 5 caregiver apps)
- Created cloud-only pilot user pilot.test@cascadestucson.com,
SG-Caregivers-Pilot group, Business Premium license, vault entry
pushed to Gitea vault repo
- Built 4 CA changes: PATCH legacy all-users-MFA to exclude pilot group,
CREATE 3 new Report-only policies (block off-network, block
non-compliant, 8h sign-in frequency) with both admins excluded
- Pilot phone wipe + re-enroll after first attempt stuck; PIN set,
awaiting MHS to take over launcher and SDM sign-in prompt
6 new project/feedback memories. Resume point at top of new session log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both servers were already patched (11.110.0.97 and 11.134.0.20) via
daily auto-update. IOC scan found 16 flagged sessions across both
plus 4 uncommented SSH keys on IX.
Critical remediation:
- Forensic evidence preserved before any deletion
- 4 uncommented SSH keys removed from IX (server-side backup retained)
- 16 flagged sessions purged across both servers
- Root passwords rotated via chpasswd
- New WHM API tokens created; 3 stale transfer-* tokens revoked
- Vault entries + 1Password Infrastructure items updated
Forensic deep-dive verdict: patch held. All 7 actual CVE exploit
attempts (botnet IPs hitting /json-api/version) returned HTTP 403.
The "multi-line pass" IOC hits on user sessions were false positives.
Unidentified 76.18.103.222 root session traced to routine SSL
maintenance (zero sensitive endpoints touched).
Skill hardening:
- Added MANDATORY service-token directive to .claude/commands/1password.md
enforcing OP_SERVICE_ACCOUNT_TOKEN from SOPS for all op CLI calls
- Per Mike: memory files alone don't reliably bind agent behavior;
baking governance into skill content loaded at moment of use.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
role_assigned() only checks direct/permanent roleAssignments.
PIM-managed assignments are in roleAssignmentSchedules and won't
be found, producing noisy (non-blocking) output on re-runs against
tenants with PIM-assigned roles (e.g. Cascades).
TODO comment added at the helper — Howard to implement the fix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Day-long session unblocking the Cascades CA reconciliation that was paused on
the Tenant Admin SP directory-role gap. Discovered Microsoft also tightened
the OAuth scope for /identity/conditionalAccess/* reads (Policy.Read.All now
required, Policy.ReadWrite.ConditionalAccess no longer accepted for reads).
Patched Tenant Admin manifest accordingly and re-consented in Cascades.
Phase B Intune state turned out to be far more built than the 4/20 log
suggested -- compliance policy, Wi-Fi, device restrictions, both SDM app
configs (Authenticator + Teams), and 7 of 8 apps were already deployed and
assigned. PATCHed device restrictions to block camera/Bluetooth/roaming
and enabled Managed Home Screen multi-app kiosk (ALIS + Teams visible,
10-min auto-signout). PATCHed Cascades named location to add primary WAN
(184.191.143.62/32). Howard added Outlook from Managed Play; SMB encryption
enabled on \CS-SERVER\homes.
CA bypass design corrected -- original §5 plan in user-account-rollout-plan.md
called for "block off-site + MFA on-site" which doesn't match the actual goal
of bypass when network + device assurance present. Reshaped to three policies
that produce on-site-compliant = password only, anything else = MFA or block.
onboard-tenant.sh patched to:
1. Backfill Policy.Read.All on Tenant Admin SP if missing (idempotent --
for tenants consented before the 2026-04-29 manifest update).
2. Assign Conditional Access Administrator directory role to Tenant Admin
SP at onboard time. Mirrors the Exchange Operator fix Mike landed in
16f95e8.
Validated with --dry-run against Cascades. Customer-facing tenants already
onboarded should be re-run with this script to backfill both items.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Documented two fundamental GuruRMM development principles:
1. Holistic Feature Development (MANDATORY):
- Every feature requires complete stack: backend, API, UI/UX, docs
- Features without management interfaces are incomplete
- Design for scalability and future expansion
- Example workflows included
2. AI-Optional Operation:
- Product must work without AI agents (Claude, autonomous tools)
- AI features are enhancements, not requirements
- Core operations remain deterministic and reliable
Principles documented in guru-rmm/docs/DESIGN.md and now in memory for
cross-session reference.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Tools (remediation-tool, onboard scripts, MSP utilities):
- Howard can modify directly
- Claude can execute with Howard OR Mike approval
- No roadmap process, immediate operational changes
Projects (GuruRMM, ClaudeTools API, etc.):
- Require Mike approval
- Features go to roadmap
- Bugs go to bug list
Established during Cascades CA role gap fix discussion.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
First attempt at Clay's voice profile from 2015-s7e19 produced
Clay-vs-Mike cosine similarity of 0.994 — essentially a Mike clone.
Root cause: 10s WavLM x-vector chunks averaged Mike's frequent
interjections together with Clay's dialogue, and Mike's well-trained
profile dominated the resulting embedding signal.
Mike's call: skip Clay, accept the 2015-s7e19 Q&A as noisy. Clay rarely
appears in other episodes, so the cost of not having his profile is
bounded to this one episode plus any rare future appearances.
Cleanup:
- voice-profiles/clay/ removed
- voice-profiles/profiles.json: Clay entry removed
- Memory updated to record the decision and the failure mode
Kept build_clay_profile.py in-repo as documentation of the attempt and
the Mike-similarity-filter pattern. Useful starting point if a future
attempt provides cleaner pure-Clay timestamps.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>