sync: auto-sync from HOWARD-HOME at 2026-06-30 11:27:16

Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-30 11:27:16
This commit is contained in:
2026-06-30 11:27:47 -07:00
parent 5e92c33b73
commit 51335db124
8 changed files with 140 additions and 5 deletions

View File

@@ -55,6 +55,10 @@ Create, update, close, comment on, and bill tickets in Syncro PSA.
**Always pass `"taxable": false` explicitly on labor line items.** Labor products are configured with `taxable: false` in Syncro, but `add_line_item` via API does not inherit the product's taxable setting — it posts the line item as `taxable: true` regardless. Always include `"taxable": false` in the payload to match the product's configured value.
**`product_category` is a CONTROLLED VOCABULARY — never invent one, never invoice a line blank.** Syncro categories are an admin-defined set; the CATEGORY column on every invoice line drives QuickBooks item mapping and revenue reporting. A blank category = an uncategorized line that breaks both. Two hard rules:
- **Never make up a category string.** Use ONLY a value that already exists in the tenant. To see the live set, enumerate distinct `product_category` across products (do NOT hardcode — it changes): `for p in $(seq 1 N); do curl -s "${BASE}/products?per_page=100&page=$p&api_key=${API_KEY}"; done | jq -r '.products[].product_category' | sort -u`. Known good values include `Labor`, `Software`, `Hardware`, `Product`, `Service`/`Services`, `Subscriptions`, `Contract`, `Discount`, `Exempt Labor`, `Prepay Hours`, `Other`, `Deposit`, `Default`. If none clearly fits, **ASK — do not guess**.
- **Never invoice a line whose product has `product_category: null`.** Before billing, `GET /products/<id>` and check `.product.product_category`. If it is `null`/blank, the product is mis-configured — STOP and flag it (a Windows/OS/software item → `Software`; a physical item → `Hardware`). Do not silently push the line out uncategorized. (Incident 2026-06-30, Cascades #32466/#32474 invoices 67887/67890: "Windows Pro Upgrade" product 23571919 has `product_category: null`, so every billed line showed a blank CATEGORY column. Winter corrected the records; the rule is here so the skill catches it next time.)
**`DELETE /schedules/{id}` destroys the recurring invoice template immediately — no confirmation, no undo.** Past generated invoices are unaffected but future billing stops. The schedule must be recreated manually with all line items if deleted accidentally. NEVER run destructive HTTP method probes against a live customer schedule — use ACG internal account (customer_id 15353550) for any testing. Incident: Russo Law Firm schedule 224454 deleted during API research 2026-05-26; recreated as 509659.
**Test articles — always prefix the subject/name with `[TEST]`.** Any ticket, estimate, appointment, or schedule created for testing or API research MUST have its subject or name prefixed with `[TEST]` (e.g. `[TEST] Schedule API research`, `[TEST] Estimate - hardware pricing`). This applies regardless of which customer account is used (including the ACG internal test account, customer_id 15353550). Test records must be instantly distinguishable from real customer work at a glance. If a test article was created without the prefix, PUT the subject to add it before continuing.
@@ -670,6 +674,8 @@ JSON
- `price_retail` — **must be set explicitly**; Syncro does NOT auto-populate from product rate via API
- `taxable` — **must be set explicitly**; always `false` for labor; `true` for taxable hardware
**Pre-flight every line item's category.** `GET /products/<id>` and confirm `.product.product_category` is non-null and is a real existing category (see the controlled-vocabulary rule above). A `null` category means the line will invoice with a blank CATEGORY column — STOP and flag the product instead of billing it. Never substitute an invented category.
**Do NOT remove line items after invoicing.** Leave them on the ticket.
**Labor product IDs** — always fetch `price_retail` live, never hardcode:

View File

@@ -41,6 +41,7 @@
- [INKY outbound breaks DMARC](reference_inky_outbound_breaks_dmarc.md) — Reverse-resolve DMARC rua failing IPs before blaming a sender: ipw-outbound.inkyphishfence.com / us.cloud-sec-av.com = INKY re-injection breaking DKIM+SPF. INKY is in-M365 (connectors+transport rules) per enrolled tenant, but hosting-level (IX/cPanel website) outbound also routes through it independent of M365 enrollment. Fix is INKY-side (outbound DKIM/SPF/ARC), not cPanel DNS.
- [Syncro prepay: full-GET only](feedback_syncro_prepay_full_get_only.md) — read prepay_hours ONLY from GET /customers/{id}; the customer search/list endpoint returns null/stale prepay. Never assert "no block" in a billing preview from search data.
- [Syncro priority/type format](feedback_syncro_priority_type_format.md) — every ticket create needs a number-prefixed priority ("2 Normal", not bare "Normal" which renders blank) AND a valid problem_type. Winter flagged #32193/#32194. Use the syncro skill's create flow.
- [Syncro line-item category](feedback_syncro_line_item_category.md) — product_category is a controlled vocab: never invent one, never invoice a line whose product has product_category:null (blank CATEGORY breaks QB mapping). Pre-flight GET /products/<id>. Winter fixed Cascades 67887/67890 "Windows Pro Upgrade".
- [RMM drive-map Explorer refresh](reference_rmm_drive_map_explorer_refresh.md) — drive mapped via RMM user_session works but the user's running Explorer won't show it until SHChangeNotify(DRIVEADD); also UNC \\ gets eaten in heredoc+jq, build it from [char]92.
- [Verify live before acting](feedback_verify_live_before_acting.md) — pull LIVE data (OMSA/iDRAC/live API) before acting on a hardware/infra flag; wiki/logs go stale. Cascades CS-SERVER "degraded RAID" was 9-day-stale (mirror self-recovered, SSDs bought needlessly). Windows can't see RAID member health.
- [Windows Pro upgrade billing](feedback_windows_pro_upgrade_billing.md) — ACG MAK key (vault infrastructure/windows-pro-mak, Mike's ACG key) for Home->Pro upgrades; RULE: invoice $99 PER machine activated, name the machine on the line item, bill after success. Each use consumes a MAK count.

View File

@@ -0,0 +1,15 @@
---
name: feedback_syncro_line_item_category
description: Syncro product_category is a controlled vocabulary — never invent one, never invoice a blank-category line
metadata:
type: feedback
---
When billing in Syncro, every invoice/ticket line item carries a CATEGORY (`product_category`) that is a **controlled, admin-defined vocabulary** and drives QuickBooks item mapping + revenue reporting. Two hard rules:
1. **Never make up a category.** Use only values that already exist in the tenant (e.g. `Labor`, `Software`, `Hardware`, `Product`, `Service`/`Services`, `Subscriptions`, `Contract`, `Discount`, `Exempt Labor`, `Prepay Hours`, `Other`, `Deposit`, `Default`). Enumerate the live set from `GET /products` rather than hardcoding. If none fits, ASK — do not guess.
2. **Never invoice a line whose product has `product_category: null`.** Pre-flight with `GET /products/<id>`; a blank category = an uncategorized line. Flag/fix the product (Windows/OS/software → `Software`, physical → `Hardware`) before billing.
**Why:** A blank or invented category silently breaks downstream accounting and makes humans clean up records. Incident 2026-06-30: Cascades "Windows Pro Upgrade" (product 23571919, `product_category: null`) invoiced on #32466/#32474 (invoices 67887/67890) with blank CATEGORY columns; Winter had to correct them. This keeps recurring as a skill-following gap.
**How to apply:** In the `/syncro` flow, before `add_line_item`/invoicing, GET the product and verify `product_category` is a real existing value. Rule lives in `.claude/commands/syncro.md` (taxable-rule block + add_line_item pre-flight). Related: [[feedback_syncro_billing]], [[feedback_syncro_preview_mandatory]], [[feedback_syncro_workflow]].

View File

@@ -28,21 +28,21 @@
### `SG-Management-RW` → `\\CS-SERVER\Management`
**RW:** Meredith Kuhn, Ashley Jensen, Lauren Hasselman, Allison Reibschied, Megan Hiatt,
Crystal Rodriguez, Veronica Feller, Shelby Trozzi, Christina DuPras · ~~Tamra Matthews~~ *(leaving)*
Crystal Rodriguez, Veronica Feller, Shelby Trozzi, Christina DuPras · ~~Tamra Matthews~~ *(OFFBOARDED 2026-06-30)*
**RO (read-only):** Lois Lane, Christine Nyanzunda **[OPEN]**, Susan Hicks **[OPEN]**, John Trozzi, Lupe Sanchez **[OPEN]**
> No `SG-Management-RO` group exists — RO members need either a new RO group or a direct NTFS read ACL. **Decision needed.**
### `SG-Sales-RW` → `\\CS-SERVER\Sales` / `SalesDept`
**RW:** Meredith Kuhn, Ashley Jensen, Lauren Hasselman, Megan Hiatt, Crystal Rodriguez · ~~Tamra Matthews~~ *(leaving)*
**RW:** Meredith Kuhn, Ashley Jensen, Lauren Hasselman, Megan Hiatt, Crystal Rodriguez · ~~Tamra Matthews~~ *(OFFBOARDED 2026-06-30)*
**RO (`SG-Sales-RO`):** Shelby Trozzi
> **Two shares exist — `Sales` and `SalesDept`.** SalesDept holds the real history (20142026 reports, marketing). Confirm which the group maps to (or both), and what `Sales` is for.
### `SG-ALdocs-RW` → `\\CS-SERVER\ALdocs` *(share + group NOT created yet)*
**RW:** Lois Lane, Karen Rossini, Meredith Kuhn, Ashley Jensen, Megan Hiatt, Crystal Rodriguez · ~~Tamra Matthews~~ *(leaving)*
**RW:** Lois Lane, Karen Rossini, Meredith Kuhn, Ashley Jensen, Megan Hiatt, Crystal Rodriguez · ~~Tamra Matthews~~ *(OFFBOARDED 2026-06-30)*
> Must create the share + `SG-ALdocs-RW` group before assigning. Nurses (Lois/Karen) + Exec tier + Sales team.
### `SG-WebDocs-RW` → `\\CS-SERVER\WebDocs` *(share + group NOT created yet)*
**RW:** Megan Hiatt, Crystal Rodriguez, Meredith Kuhn, Ashley Jensen · ~~Tamra Matthews~~ *(leaving)*
**RW:** Megan Hiatt, Crystal Rodriguez, Meredith Kuhn, Ashley Jensen · ~~Tamra Matthews~~ *(OFFBOARDED 2026-06-30)*
> Must create the share + `SG-WebDocs-RW` group. Distinct from the retired DSM `web` station.
### `SG-Server-RW` → `\\CS-SERVER\Server`

View File

@@ -0,0 +1,43 @@
# Cascades — Printer / VLAN 20 Migration Map (GPO planning)
Living reference for the printer migration onto Staff VLAN 20 (10.0.20.0/24) and the
eventual **printer GPO** build. Update as machines/printers migrate. Started 2026-06-30 (Howard).
## How the GPO needs to be built (two layers)
1. **Point-and-Print policy (computer GPO, fleet-wide)** — REQUIRED prerequisite or any
GPO-pushed printer fails (PrintService event 513 / error 0xBCB) for standard users.
Set on `HKLM\SOFTWARE\Policies\Microsoft\Windows NT\Printers`:
`RestrictDriverInstallationToAdministrators=0`; subkey `PointAndPrint`:
`Restricted=1, TrustedServers=1, ServerList=CS-SERVER, InForest=0,`
`NoWarningNoElevationOnInstall=1, UpdatePromptSettings=2` (scopes silent driver install
to CS-SERVER only). Caregiver machines already have this — that's why their printer GPO
works. Set manually 2026-06-30 on DESKTOP-ROK7VNM + DESKTOP-DLTAGOI; needs to be a GPO.
2. **Printer deployment** — GPP Printers / Deployed Printers mapping `\\CS-SERVER\<share>`
to the right users/OU/room. Existing GPO `CSC - Life Enrichment Printers` likely still
points at OLD share names — repoint. `CSC - Printer Deployment` is disabled/empty (do not use).
**Driver trap:** Canon MF741/743 are **UFR II only** — PCL6 produces Error #822 (spools, never
prints). Any GPO/share for those Canons MUST use `Canon Generic Plus UFR II V250` (INF cnlb0ma64.inf).
## Printer / machine map
| Printer (share / name) | Model | IP (VLAN20) | Driver | Machine | User(s) | Domain? | Status / GPO action |
|---|---|---|---|---|---|---|---|
| `\\CS-SERVER\FrontDesk` | Epson ET-5800 | 10.0.20.221 | EPSON ET-5800 Series | RECEPTIONIST-PC (frontdesk box, S/N MJ0KQHNP) | frontdesk | Domain (cascades.local) | DONE — share repointed, mapped, default. Add to GPO. |
| `\\CS-SERVER\LifeEnrichment` | Canon MF741CDW | 10.0.20.94 | Canon Generic Plus UFR II V250 | DESKTOP-DLTAGOI; DESKTOP-ROK7VNM | sharon.edwards; susan.hicks | Domain | DONE — UFR II driver fixed, mapped (not default). **Repoint `CSC - Life Enrichment Printers` GPO from old `1F-132-RecRoom-Canon` to `LifeEnrichment`.** |
| Dining Room Manager - Canon MF743CDW | Canon MF743CDW (MF741C/743C) | 10.0.20.228 | Canon Generic Plus UFR II V250 | DESKTOP-MD6UQI3 | dining manager (Alyssa) | **WORKGROUP — not domain-joined yet** | DONE as direct-IP (local) printer, default. **TODO: when DESKTOP-MD6UQI3 is domain-joined, add this printer to the GPO and map it to Alyssa's domain account.** |
| Chef Office - Brother MFC-9330CDW | Brother MFC-9330CDW | 10.0.20.236 | Brother MFC-9330CDW Printer | CHEF-PC | chef (all users) | **WORKGROUP — not domain-joined** | DONE as direct-IP (machine-wide / all users), default. **TODO: add to GPO + map to chef's domain account once CHEF-PC is domain-joined.** This is the Chef's printer in the Chef's office (distinct from the kitchen printer with the chefs). |
| Memory Care Front Desk - Epson ET-5800 (`\\CS-SERVER\MCReception`) | Epson ET-5800 | 10.0.20.78 | EPSON ET-5800 Series | MEMRECEPT-PC | memfrtdesk (+ other MemCare front-desk staff) | **WORKGROUP — not domain-joined** | Already shared on CS-SERVER as `MCReception`. Machine currently has the Epson via OLD vendor/WSD ports (`EP833571:ET-5800 SERIES` + WSD), NOT the static .78 — needs direct-IP to 10.0.20.78. **Mark for GPO: MemCare front-desk users (mostly the memfrtdesk machine). TODO: add to GPO + map to domain accounts once domain-joined.** |
| Memory Care MedTech - Brother MFC-L8900CDW (`\\CS-SERVER\MCMedTech`) | Brother MFC-L8900CDW | 10.0.20.74 | Brother MFC-L8900CDW series | RECEPTIONIST-PC (memcare box → **rename to MEMCARE-***); DESKTOP-LPOPV30 | memory care; karen rossini | **WORKGROUP** | DONE direct-IP machine-wide on both; old 192.168.2.53 + WSD connections removed; LPOPV30 default = new printer (was the old one); memcare box default unchanged (iR-ADV). MedTech room in Memory Care. **TODO: GPO + domain accounts once joined.** |
| `\\CS-SERVER\Kitchen` | Canon MF743CDW | 192.168.3.232 (pre-migration) | (verify) | (kitchen) | chefs | — | Kitchen printer (with the chefs). Not yet migrated to VLAN20 this round. |
## Machine rename TODO
- **RECEPTIONIST-PC** (the Memory Care box, "memory care" user, S/N MJ0KQH4R, agent 57f19e17) shares its hostname with the front-desk RECEPTIONIST-PC box — too hard to tell apart in the agent list. **Rename to a unique `MEMCARE-*` name** (pending Howard's chosen name + reboot). The OTHER RECEPTIONIST-PC (frontdesk user, S/N MJ0KQHNP) is the actual front desk.
## Notes
- Workgroup machines (DESKTOP-MD6UQI3, CHEF-PC) get **direct-IP local printers** for now
(no domain auth / no point-and-print needed). Once domain-joined, switch them to the
GPO-deployed `\\CS-SERVER\<share>` model and map to the domain account.
- Detailed how-to + pfSense routing fix: `.claude/memory/project_cascades_vlan20_migration_routing.md`
and session log `clients/cascades-tucson/session-logs/2026-06/2026-06-30-howard-vlan20-printer-migration.md`.

View File

@@ -0,0 +1,66 @@
# Offboarding Record — Tamra Matthews
**Date:** 2026-06-30 · **Performed by:** Howard Enos (ClaudeTools session) · **Authorized by:** Howard Enos
**Separation type:** Voluntary (left Cascades, June 2026) · **Role:** Move-In Coordinator (Marketing / Sales)
**Runbook:** `docs/security/termination-procedures.md`
## Identities handled
- **M365 (cloud-only):** `tamra.matthews@cascadestucson.com` — id `2d9cf0d1-2b0b-424e-9cd1-91eaac408837`
(`onPremisesSyncEnabled=null` — cloud-mastered object, NOT Entra-synced)
- **On-prem AD:** `Tamra.Matthews` (was `OU=Marketing,OU=Departments,DC=cascades,DC=local` — separate
object, NOT Entra-synced; renamed from Tamra.Johnson 2026-04-13)
- **ALIS:** Not handled this session — Move-In Coordinator role; confirm/disable ALIS staff profile if
she had clinical/ALIS access (open follow-up below).
## Actions completed (M365)
| # | Action | Result |
|---|---|---|
| 1 | Revoke active sign-in sessions | HTTP 200 |
| 2 | Block sign-in (`accountEnabled=false`) | confirmed false |
| 3 | Reset password (random, vaulted) | OK — no elevation needed (holds no admin role, **no PAA stranding**) |
| 4 | Convert mailbox → **SharedMailbox** | confirmed (`RecipientTypeDetails=SharedMailbox`) |
| 5 | Grant **FullAccess** to Crystal Rodriguez, Megan Hiatt, Meredith Kuhn, Ashley Jensen | all 4 confirmed FullAccess |
| 6 | Hide from GAL (`HiddenFromAddressListsEnabled=true`) | confirmed |
| 7 | Remove **O365 Business Standard** license (`f245ecc8…`) | confirmed 0 licenses — **frees 1 seat** |
| 8 | Remove from groups `Sales`, `All Cascades`, `SG-SSPR-Eligible` | HTTP 204 ×3 |
### AutoMapping caveat (delegate auto-attach)
- **Crystal Rodriguez + Ashley Jensen** — added with `AutoMapping:$true`; the shared mailbox
**auto-attaches** in their Outlook.
- **Megan Hiatt + Meredith Kuhn** — `AutoMapping:$true` would not persist via the ComputerGuru
Exchange Operator app: the cmdlet echoed success but the grant rolled back (a failed
`msExchDelegateListLink` write aborts the whole `Add-MailboxPermission` transaction). Re-added with
`AutoMapping:$false`, which **persisted**. They have full access but the box does **not**
auto-attach — one-time manual add in Outlook (File → Open & Export → Other User's Folder, or add
`tamra.matthews@cascadestucson.com` as an additional mailbox), **or** flip auto-mapping from an
interactive EXO PowerShell session later (`Add-MailboxPermission … -AutoMapping $true`).
## Actions completed (on-prem AD, CS-SERVER)
- `Set-ADAccountPassword -Reset` (random, vaulted)
- `Disable-ADAccount Tamra.Matthews` → Enabled=False
- Group memberships: already 0 (no explicit groups) — nothing to strip
- `Move-ADObject``CN=Tamra Matthews,OU=Excluded-From-Sync,DC=cascades,DC=local`
## Retention / compliance
- **No Litigation Hold applied.** Decision (Howard, 2026-06-30): although Move-In Coordinator is a
resident-intake / PHI-adjacent role, Howard authorized the same posture as the Alma Montt
offboarding — **shared-mailbox conversion + zero-deletion** (no mailbox deleted), license removed to
free the seat. Mailbox is preserved under default MRM retention; revisit if her PHI-access
determination or a legal hold changes. Litigation Hold remains available later (tenant has Business
Premium / Exchange Plan 2) if the determination changes.
- Passwords stored for emergency recovery/audit only: vault `clients/cascades-tucson/tamra-matthews`
(`m365_password`, `ad_password`). **Do NOT re-enable without authorization.**
## Open follow-ups
- [ ] **ALIS staff profile** — confirm whether Tamra had ALIS access; if so, disable the staff record
(audit record stays). Her M365 SSO tie is already severed by the sign-in block.
- [ ] **AutoMapping for Megan Hiatt + Meredith Kuhn** — either they add the shared mailbox manually,
or flip `-AutoMapping $true` from an interactive EXO session (the app-based REST path won't
persist it for these two). Crystal + Ashley already auto-attach.
- [ ] **Reconcile** Tamra out of forward-looking plans/rosters. Share roster
`docs/migration/share-group-roster-proposed-2026-06-25.md` already shows her struck-through
*(leaving)*; `docs/servers/active-directory.md` OU=Marketing row updated to disabled +
Excluded-From-Sync. April/May questionnaires, CSVs, and the staff roster
`reports/cascades-staff-2026-04-22.csv` left as historical record.
- [ ] **Note (separate):** Megan Hiatt's M365 account carries a `CREDENTIAL_STUFFING_ACTIVE` flag in
the April tenant inventory — unrelated to this offboarding, but worth a breach check.

View File

@@ -75,7 +75,7 @@
|---------------|------|----------|-------|
| Megan.Hiatt | Megan Hiatt | Sales Director | M365: Sales@ |
| Crystal.Rodriguez | Crystal Rodriguez | Sales Associate | PC: CRYSTAL-PC. M365: Sales@ |
| Tamra.Matthews | Tamra Matthews | Move-In Coordinator | Renamed from Tamra.Johnson (2026-04-13) |
| ~~Tamra.Matthews~~ | ~~Tamra Matthews~~ | ~~Move-In Coordinator~~ | **OFFBOARDED 2026-06-30** — disabled, moved to `OU=Excluded-From-Sync`. See `docs/security/offboarding-2026-06-30-tamra-matthews.md` |
**OU=Resident Services**
| SamAccountName | Name | Position | Notes |

View File

@@ -17,6 +17,10 @@ Categories (the `[type]` tag): _(none)_ = skill/command execution failure ·
<!-- Append entries below this line -->
2026-06-30 | Howard-Home | remediation-tool/exchange-op | [friction] Add-MailboxPermission -AutoMapping $true silently rolled back the FullAccess grant for 2 of 4 delegates (cmdlet echoed [FullAccess] success but Get-MailboxPermission showed NONE); a failed msExchDelegateListLink write aborts the whole Add transaction. Fix: re-add with -AutoMapping $false (FullAccess then persists); set automapping separately/interactively if auto-attach is required. [ctx: tenant=cascadestucson.com mailbox=tamra.matthews app=ComputerGuru-Exchange-Operator]
2026-06-30 | Howard-Home | /syncro | [correction] invoiced 'Windows Pro Upgrade' line items (Cascades 67887/67890) with blank CATEGORY; product_category was null and I billed it anyway — correct is to pre-flight GET /products/<id>, never invoice a null/blank category, and never invent one (use existing set e.g. Software) [ctx: ref=feedback_syncro_line_item_category invoices=67887,67890 product=23571919]
2026-06-30 | Howard-Home | rmm/printer-map | [friction] Add-Printer -ConnectionName in user_session = HRESULT 0x800702e4 ELEVATION_REQUIRED (Point-and-Print); agent watchdog times out on the interactive UAC prompt. Use WScript.Network.AddWindowsPrinterConnection + have a user at console approve, or pre-stage driver/connection as SYSTEM
2026-06-30 | Howard-Home | rmm/powershell | [friction] literal UNC backslashes (hostshare) in a jq-built PS payload got mangled to a single backslash -> Add-Printer 'invalid name'; fix: build UNC with [char]92 instead of literal backslashes [ctx: ref=feedback_windows_quote_stripping host=RECEPTIONIST-PC]