docs(session)+rules: 2026-05-27 — Quantum M365 onboarding, IX autodiscover fix, Syncro emergency/labor/attribution rules
Session logs: root (Michael #32329 hosting offer + IX simplehost.email autodiscover DNS fix + Cascades #32332 emergency correction) + Quantum client log (M365 tenant 2fd0092b onboarding, break-glass GA, CA report-only). Syncro rule overhaul: - Emergency billing: prepaid -> 26184 @ hours x1.5 (was 26118); non-prepaid -> 26184 with channel rate (onsite $262.50 / remote+inshop $225) - Never make up labor items (existing product + real name; QuickBooks sync) - Corrections preserve original tech's user_id (commission); adding notes/labor never changes ticket owner /remediation-tool: Conditional Access may be managed programmatically (report-only first + exclude break-glass + confirm before enforce); fabb3421 deprecated for customer tenants; Quantum tenant onboarded (gotchas table). Memory: 4 new (no-madeup-labor, corrections-preserve-tech, ca-programmatic, quantum-godaddy-tenant) + updates. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,10 +28,11 @@
|
||||
- [D2TESTNAS SSH Access](feedback_d2testnas_ssh.md) - Use root@192.168.0.9 with Paper123!@#, not sysadmin
|
||||
- [Bypass Permissions Setting](feedback_bypass_permissions_setting.md) - Set permissions.defaultMode to bypassPermissions in settings.json on all machines
|
||||
- [No indented code blocks](feedback_no_indented_code_blocks.md) — Never indent code inside fences; Howard copy-pastes directly and leading spaces break PowerShell
|
||||
- [365 Remediation Tool](feedback_365_remediation_tool.md) - Always means Graph API app fabb3421, not CIPP
|
||||
- [365 Remediation Tool](feedback_365_remediation_tool.md) — "remediation tool" = tiered ComputerGuru app suite via /remediation-tool; NOT CIPP, NOT the deprecated fabb3421
|
||||
- [CA managed programmatically (with discipline)](feedback_ca_programmatic_management.md) — Conditional Access CAN be written via Tenant Admin app; ALWAYS report-only first + exclude break-glass + confirm before enforcing. Overrides old "CA manual" rule.
|
||||
- [Ollama Tier-0 Routing](feedback_ollama_tier0_routing.md) - Route drafts/summaries/classifications through Ollama (qwen3:14b). Mike designed ClaudeTools this way — not optional.
|
||||
- [/save writes narrative directly](feedback_save_no_ollama.md) — No Ollama for /save; write all sections inline — too slow
|
||||
- [Syncro Emergency Billing](feedback_syncro_emergency_billing.md) — Emergency = 1.5× multiplier, not additive. Branch by `customer.prepay_hours`: no-prepaid → `26184` at actual hrs; prepaid → `26118` at hrs×1.5. Never stack. Always set `price_retail`.
|
||||
- [Syncro Emergency Billing](feedback_syncro_emergency_billing.md) — Emergency = time-and-a-half (×1.5), applied once, never additive. Branch by `customer.prepay_hours`: no-prepaid → `26184` at actual hrs; prepaid → `26184` at hrs×1.5 (premium in the QUANTITY). One line. Always set `price_retail`. (Updated 2026-05-27: prepaid now uses 26184, not 26118.)
|
||||
- [Identity precedence](feedback_identity_precedence.md) — Trust `.claude/identity.json` over the system-reminder `userEmail` hint when they disagree (shared-login machines).
|
||||
- [1Password — always use service token](feedback_1password_service_token.md) — Source OP_SERVICE_ACCOUNT_TOKEN from SOPS for every `op` call. Desktop-app integration prompts are unacceptable in agent flows.
|
||||
- [Point vault-access teammates at SOPS path](feedback_vault_pointer_for_teammates.md) — When relaying infra/credential info to Howard or other vault-access teammates, hand over the SOPS path + key anchors; don't transcribe the entry's fields into the message.
|
||||
@@ -42,6 +43,8 @@
|
||||
- [Syncro — bill with add_line_item, not timers](feedback_syncro_timer_first.md) — Bill tickets with `POST /tickets/{id}/add_line_item` directly; the timer workflow (`timer_entry → charge_timer_entry`) is NOT used. Set product_id, quantity (decimal hours), price_retail, name, description, taxable:false. Supersedes the old "timers required" rule (Mike confirmed 2026-05-21).
|
||||
- [Syncro — timer_entry response is FLAT (HISTORICAL)](feedback_syncro_timer_response_shape.md) — Reference only: timers are NO LONGER part of the billing workflow (superseded by add_line_item — see feedback_syncro_timer_first.md). Retained for the rare manual-timer case: response is flat (`{"id": N, ...}`), parse `.id` not `.timer.id`. Originally hit on #32253 2026-05-05.
|
||||
- [Syncro — warranty has its own product, never patch dollar amounts](feedback_syncro_warranty_product.md) — Warranty/no-charge work uses product `1049360` (Labor- Warranty work, $0). Don't fake a free line by patching `price_retail` or neutralizing a regular product — pick the correct product and re-run. Hit on #32225 2026-05-06.
|
||||
- [Syncro — never make up labor items](feedback_syncro_no_madeup_labor_items.md) — Labor lines MUST be an existing Syncro product used with its REAL name; never invent/rename a line. Description field is free text. Made-up items break the QuickBooks sync. Incident #32332.
|
||||
- [Syncro — preserve attribution (labor + ticket owner)](feedback_syncro_corrections_preserve_tech.md) — Corrections keep the original tech's labor user_id (commission); update_line_item preserves it, remove+add defaults to the API-key owner. Adding notes/labor never changes the ticket owner. Only reassign labor or ticket ownership when explicitly asked. (#32332)
|
||||
- [SQL instance role — verify by connections, not name](feedback_sql_instance_role_by_connection.md) — Standard installed under default `SQLEXPRESS` instance name is real. Prove role with `sys.dm_exec_sessions` + `Get-NetTCPConnection -OwningProcess` before recommending stop/uninstall. IMC1 2026-05-05/06 near-miss.
|
||||
- [Syncro — confirm appointment owner explicitly](feedback_syncro_appointment_owner.md) — When creating tickets with appointments, always ask "who is the appointment owner?" in the preview. Don't auto-default to ticket's assigned tech. Don't add additional attendees without explicit confirmation. Howard caught on Kittle ticket #32263 2026-05-08.
|
||||
- [Syncro — verify appointment date day-of-week](feedback_syncro_appointment_date_check.md) — Always compute and display the day name (e.g. "Saturday 2026-05-23") in the ticket preview — never just the numeric date. Verify with `py -c "import datetime; ..."` before posting. Wrong-day incident on #32312 2026-05-21 (Sunday booked instead of Saturday). Reported by Winter.
|
||||
@@ -65,6 +68,7 @@
|
||||
- [Mac gururmm setup pending](project_mac_gururmm_setup_pending.md) — ACTION REQUIRED: run `bash scripts/install-hooks.sh` in gururmm repo on Mikes-MacBook-Air before any RMM work
|
||||
|
||||
## Project
|
||||
- [Quantum GoDaddy M365 tenant](project_quantum_godaddy_m365_tenant.md) — quantumwms.com parked in a GoDaddy-provisioned M365 tenant (id ddf3d2c9-b76c-40d9-a216-9f11a1a26f97, netorg18235235.onmicrosoft.com); blocks Pax8 migration until GoDaddy removed. Managed = no DNS takeover; need GoDaddy/GA access.
|
||||
- [Cascades Migration Plan](project-cascades-migration-plan.md) — Active multi-day migration. Plan file: `C:\Users\Howard\.claude\plans\wise-discovering-panda.md`. Syncro ticket: #110680053. Resume: "resume the Cascades migration plan".
|
||||
- [GuruRMM Development Principles](gururmm-development-principles.md) - MANDATORY: every feature needs full stack (backend, API, UI, docs, scalability). Product must work without AI agents (AI features are enhancements). Documented in guru-rmm/docs/DESIGN.md.
|
||||
- [Sync script bug — untracked files (RESOLVED)](project_sync_script_bug.md) — FIXED 2026-05-21: sync.sh now uses `git status --porcelain` for change detection (repo + vault), so untracked-only changes are caught. Added .gitignore for the datto BSOD dumps so the fix doesn't sweep 54MB of binaries.
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
---
|
||||
name: 365 Remediation Tool Reference
|
||||
description: "365 remediation tool" always means the Claude-MSP-Access Graph API app (fabb3421-8b34-484b-bc17-e46de9703418), not CIPP
|
||||
type: feedback
|
||||
---
|
||||
|
||||
When user says "365 remediation tool" or "remediation tool", they ALWAYS mean the Claude-MSP-Access Graph API application (App ID: fabb3421-8b34-484b-bc17-e46de9703418). This is NOT CIPP.
|
||||
|
||||
**Why:** User explicitly clarified this after I incorrectly navigated to CIPP. The remediation tool is direct Graph API access using client credentials flow against customer tenants.
|
||||
|
||||
**How to apply:** Authenticate directly via Graph API using the app's client secret from SOPS vault (`msp-tools/claude-msp-access-graph-api.sops.yaml`), get tenant ID from OpenID discovery for the target domain, and query Graph API endpoints directly. No browser/UI needed.
|
||||
|
||||
**Preferred invocation: use the `/remediation-tool` skill** (`.claude/skills/remediation-tool/`, also surfaces as a `/remediation-tool` command). It wraps tenant resolution, token caching, the 10-point user breach check, and tenant-wide sweep. Remediation actions are gated behind explicit `YES` confirmation. Reference docs at `references/gotchas.md`, `references/graph-endpoints.md`, `references/checklist.md`.
|
||||
|
||||
### Directory Role Requirements (discovered 2026-04-01)
|
||||
|
||||
Graph API permissions alone are NOT sufficient for privileged operations. The service principal also needs Entra directory roles assigned per-tenant:
|
||||
|
||||
| Operation | Required Directory Role |
|
||||
|-----------|----------------------|
|
||||
| Password reset | User Administrator |
|
||||
| Exchange transport rules, mailbox permissions | Exchange Administrator |
|
||||
|
||||
**Roles assigned so far:**
|
||||
- Valleywide Plastering (5c53ae9f...): User Administrator
|
||||
- Dataforth (7dfa3ce8...): User Administrator, Exchange Administrator
|
||||
|
||||
**For new tenants:** After admin consent, manually assign roles via Entra portal > Roles and administrators. The app cannot self-assign directory roles.
|
||||
|
||||
### Exchange Online REST API
|
||||
|
||||
For Exchange cmdlets (Get-TransportRule, Add-MailboxPermission, etc.), use scope `https://outlook.office365.com/.default` and POST to `https://outlook.office365.com/adminapi/beta/$TENANT_ID/InvokeCommand` with `{"CmdletInput":{"CmdletName":"...", "Parameters":{...}}}`.
|
||||
---
|
||||
name: 365 Remediation Tool Reference
|
||||
description: "365 remediation tool" = ACG's tiered ComputerGuru Graph/EXO app suite via the /remediation-tool skill; NOT CIPP, and NOT the deprecated fabb3421 single-app
|
||||
type: feedback
|
||||
---
|
||||
|
||||
When the user says "365 remediation tool" or "remediation tool", they mean ACG's direct Graph/Exchange tooling against customer tenants via the **`/remediation-tool` skill** (`.claude/skills/remediation-tool/`). This is NOT CIPP.
|
||||
|
||||
**App suite (current — tiered):** Security Investigator `bfbc12a4` (Graph read + EXO read), Exchange Operator `b43e7342` (EXO write), User Manager `64fac46b` (user/license/MFA/pw write), Tenant Admin `709e6eed` (high-priv directory), Defender Add-on `dbf8ad1a` (MDE-licensed tenants ONLY). Secrets in `msp-tools/computerguru-*.sops.yaml`. Client-credentials auth; tenant ID via OpenID discovery (or the `*.onmicrosoft.com` domain when the primary domain isn't verified). Use the lowest tier needed. Each app is consented per-tenant (URLs in `references/gotchas.md`); privileged ops also need directory roles assigned to the SP in that tenant (`onboard-tenant.sh`).
|
||||
|
||||
**DEPRECATED — do NOT consent to customer tenants:** `fabb3421` ("AI Remediation" / "Claude-MSP-Access", secret `msp-tools/claude-msp-access-graph-api.sops.yaml`). ~159 perms incl. Defender ATP, so admin consent **breaks with AADSTS650052 on any tenant lacking an MDE license**. It still works where already consented (e.g. ACG's own tenant — the `/mailbox` skill reads our own mailboxes with it), but new onboarding MUST use the tiered suite. (Corrected 2026-05-27 during Quantum onboarding — nearly consented the deprecated app to a no-MDE tenant.)
|
||||
|
||||
**Why (original):** user clarified "remediation tool" != CIPP after a wrong CIPP navigation. **How to apply:** prefer the `/remediation-tool` skill — it wraps tenant resolution, token caching, breach check, sweep, gated remediation, and consent/onboarding URLs (`references/gotchas.md`, `graph-endpoints.md`, `checklist.md`).
|
||||
|
||||
### Directory Role Requirements (discovered 2026-04-01)
|
||||
|
||||
Graph API permissions alone are NOT sufficient for privileged operations. The service principal also needs Entra directory roles assigned per-tenant:
|
||||
|
||||
| Operation | Required Directory Role |
|
||||
|-----------|----------------------|
|
||||
| Password reset | User Administrator |
|
||||
| Exchange transport rules, mailbox permissions | Exchange Administrator |
|
||||
|
||||
**Roles assigned so far:**
|
||||
- Valleywide Plastering (5c53ae9f...): User Administrator
|
||||
- Dataforth (7dfa3ce8...): User Administrator, Exchange Administrator
|
||||
|
||||
**For new tenants:** After admin consent, manually assign roles via Entra portal > Roles and administrators. The app cannot self-assign directory roles.
|
||||
|
||||
### Exchange Online REST API
|
||||
|
||||
For Exchange cmdlets (Get-TransportRule, Add-MailboxPermission, etc.), use scope `https://outlook.office365.com/.default` and POST to `https://outlook.office365.com/adminapi/beta/$TENANT_ID/InvokeCommand` with `{"CmdletInput":{"CmdletName":"...", "Parameters":{...}}}`.
|
||||
|
||||
19
.claude/memory/feedback_ca_programmatic_management.md
Normal file
19
.claude/memory/feedback_ca_programmatic_management.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
name: feedback-ca-programmatic-management
|
||||
description: Conditional Access MAY be managed programmatically via the remediation-tool Tenant Admin app (overrides the old "CA stays manual in portal" boundary); strict report-only-first + break-glass-exclude discipline required
|
||||
metadata:
|
||||
type: feedback
|
||||
---
|
||||
|
||||
Conditional Access policies **may be created/modified programmatically** via the `/remediation-tool` **Tenant Admin tier** (`709e6eed` — carries `Policy.ReadWrite.ConditionalAccess` + the Conditional Access Administrator directory role). This **overrides** the prior scope boundary ("CA stays manual in the portal").
|
||||
|
||||
**Why:** Mike explicitly directed it 2026-05-27 (Quantum onboarding). His rationale: with a **break-glass account excluded** and policies in **report-only**, the blast radius is near zero, and he wants the capability for scale (templated CA baselines across tenants).
|
||||
|
||||
**How to apply — mandatory discipline every time:**
|
||||
1. Create/modify in **report-only first** — `state: "enabledForReportingButNotEnforced"`. Never create a policy directly `enabled`.
|
||||
2. Always **exclude the tenant's break-glass account** in `conditions.users.excludeUsers` (create the break-glass GA first if none exists).
|
||||
3. **Verify impact** in Entra sign-in logs (report-only logs what *would* happen) before enforcing.
|
||||
4. Get **explicit user confirmation before flipping any policy to `enabled`** on a tenant with real users.
|
||||
5. Entra **app registrations** still stay manual — only CA is in scope for programmatic management.
|
||||
|
||||
Endpoint: `POST/PATCH https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies` with the tenant-admin token. Verified working on Quantum tenant 2fd0092b (CA001 MFA-all + CA002 block-legacy, report-only). See [[365-remediation-tool-reference]].
|
||||
18
.claude/memory/feedback_syncro_corrections_preserve_tech.md
Normal file
18
.claude/memory/feedback_syncro_corrections_preserve_tech.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: feedback-syncro-corrections-preserve-tech
|
||||
description: Preserve Syncro attribution — corrections keep the original tech's labor user_id (commission); and adding notes/labor never changes the ticket owner. Only reassign labor or ticket ownership when explicitly asked.
|
||||
metadata:
|
||||
type: feedback
|
||||
---
|
||||
|
||||
When fixing labor line items that were billed incorrectly (wrong product, quantity, name, or bad math — a **debug/correction action**), do NOT let the labor get reassigned to the correcting tech. **Preserve the ORIGINAL tech's attribution (`user_id`)** on each line so their commission isn't lost.
|
||||
|
||||
- **Prefer `update_line_item` in place** — it preserves the line's existing `user_id`. (Verified on #32332: updating Howard's line kept `user_id=1750`; the dollar/product changed but the commission stayed with Howard.)
|
||||
- **If you must REMOVE + re-ADD a line**, the new line defaults to the **API-key owner's** `user_id` (e.g. Mike `1735`) — so explicitly set `user_id` to the original tech on `add_line_item`, or PUT `update_line_item` to fix the new line's `user_id` afterward.
|
||||
- Determine the original tech from the **ticket's `.ticket.user_id`** and the line's `.user_id` before correcting; verify it still matches after.
|
||||
|
||||
**Tech user_ids:** Mike `1735`, Howard `1750`, Winter `1737`, Rob `1760`.
|
||||
|
||||
**Ticket ownership (related rule, Mike 2026-05-27):** Simply adding notes or labor to a ticket does **NOT** change the ticket owner (`.ticket.user_id` / assigned tech). Multiple techs routinely work the same ticket. **Only change ticket ownership when explicitly asked** — never PUT a ticket's `user_id` as a side effect of commenting, billing, or status changes. (Status PUTs should send only `status`; line edits use `update_line_item`; neither should touch `user_id`.)
|
||||
|
||||
**Why:** Mike — a billing correction is a debug action (e.g. Claude or someone billed it wrong); the **original tech still did the work and keeps the commission**. Don't take Howard's commission just because the math was fixed by Mike/Winter. Hit on #32332 (Cascades) 2026-05-27 — Howard's mis-billed labor was corrected via Mike's API key; update-in-place preserved `user_id=1750`, but a remove+add would have stolen the commission. Related: per-user-key attribution in [[365-remediation-tool-reference]] / `/syncro` Attribution rule.
|
||||
@@ -1,23 +1,22 @@
|
||||
---
|
||||
name: Syncro emergency/after-hours billing — check prepay_hours first
|
||||
description: Emergency labor is 1.5× multiplier, not additive. Branch by customer.prepay_hours — wrong branch doubles or undercharges. Applies to every /syncro bill for emergency work.
|
||||
type: feedback
|
||||
description: Emergency labor is time-and-a-half (×1.5), applied once, never additive. Branch by customer.prepay_hours. Prepaid → emergency item 26184 at hours×1.5 (premium in quantity); non-prepaid → 26184 at actual hours (rate has 1.5×).
|
||||
metadata:
|
||||
type: feedback
|
||||
---
|
||||
|
||||
**Rule:** Before adding any Emergency/after-hours labor line item on a Syncro ticket, `GET /customers/<id>` and read `prepay_hours`.
|
||||
**Rule:** Before adding any Emergency/after-hours labor line on a Syncro ticket, `GET /customers/<id>` and read `prepay_hours`. Emergency = **time-and-a-half (×1.5), applied ONCE** — never bill a separate regular line + emergency line for the same hours.
|
||||
|
||||
- If `prepay_hours == 0` (no prepaid block): use product `26184` (Labor - Emergency/After Hours) at quantity = actual hours. The $262.50/hr rate already has the 1.5× multiplier baked in.
|
||||
- If `prepay_hours > 0` (customer has a prepaid block): use product `26118` (Labor - Onsite) at quantity = actual hours × 1.5. Prepaid blocks debit by QUANTITY, not dollars, so we bump qty instead of swapping to the Emergency product.
|
||||
- **No prepaid block (`prepay_hours == 0`):** product `26184` (Labor - Emergency or After Hours) at quantity = **actual hours**, and set `price_retail` by the work's **delivery channel** (the 1.5× lives in the dollars — do NOT also ×1.5 the quantity): **Onsite emergency = $262.50** (175 × 1.5; this is 26184's default rate); **Remote / In-Shop emergency = $225** (150 × 1.5) → override `price_retail` to `225`. Fetch the base rate live and ×1.5 if unsure.
|
||||
- **Prepaid block (`prepay_hours > 0`):** product `26184` at quantity = **actual hours × 1.5** (hours + 50%). Prepaid blocks debit by QUANTITY not dollars, so the 1.5× premium goes in the **quantity**; the invoice nets to $0 and the block debits hours×1.5. e.g. 1.5 emergency hrs → `26184` @ **2.25**. (Delivery channel / dollar rate is **irrelevant** for prepaid — only the quantity hrs×1.5 matters.)
|
||||
|
||||
Never stack `26118` + `26184` for the same hour of work. Pick one path based on the prepaid state.
|
||||
**(Updated 2026-05-27 — Mike):** prepaid emergency now uses the **emergency item `26184`** at ×1.5 quantity — this REPLACES the old "prepaid → onsite `26118` at ×1.5." Using 26184 labels the line correctly as emergency and maps right in QuickBooks; the dollar double-1.5 worry doesn't apply to prepaid since the invoice is $0. Reaffirmed on #32332 (Cascades, prepaid 27h): total 1.5 emergency hrs → `26184` @ 2.25 (Howard had split it into made-up onsite/emergency lines).
|
||||
|
||||
**Why:** Learned on ticket #32203 (Desert Auto Tech) 2026-04-23. Howard asked to bill "1 hour onsite + 1 hour emergency onsite." I posted both as separate additive line items and the invoice came out at $437.50 when the correct bill for 1 actual hour of emergency work was $262.50. Winter caught it and explained the rule: "the goal is to have it bill at time and a half." The Emergency product = time-and-a-half by rate; prepaid accounts = time-and-a-half by quantity. Swapping products AND multiplying quantity double-counts.
|
||||
**Why ×1.5-not-additive:** Learned on #32203 (Desert Auto Tech) 2026-04-23 — billing "1h onsite + 1h emergency" as two additive lines came out $437.50 when 1 actual hour of emergency should bill at time-and-a-half. Emergency IS time-and-a-half; one line.
|
||||
|
||||
**How to apply:**
|
||||
- Every `/syncro bill` for emergency/after-hours work: check `prepay_hours` BEFORE choosing the product. Do not shortcut this.
|
||||
- For a 2-hour emergency job:
|
||||
- Non-prepaid customer → one line, 2.0 hrs × `26184` → $525.00
|
||||
- Prepaid customer → one line, 3.0 hrs × `26118` → 3 hours debit from block
|
||||
- Always set `price_retail` explicitly on `add_line_item`. The old "omit and let Syncro auto-calc" guidance was wrong — the rate does not populate from the product config, and the invoice will post at $0 if `price_retail` is missing. Fetch the current rate with `GET /products/<id>`.
|
||||
- Never let a customer-facing invoice post without verifying `.invoice.total` matches the expected `qty × price_retail`.
|
||||
- Full rules and examples live in `.claude/commands/syncro.md` under the "Labor product IDs" section.
|
||||
- Every emergency/after-hours bill: check `prepay_hours` BEFORE choosing the quantity. One emergency line on `26184`.
|
||||
- Always set `price_retail` explicitly (fetch live via `GET /products/26184`); the rate doesn't auto-populate and the line posts $0 if omitted.
|
||||
- Use the product's REAL name on the line (work detail goes in the description) — see [[feedback-syncro-no-madeup-labor-items]].
|
||||
- Verify after invoicing: `.invoice.total` (non-prepaid) or the prepay-block decrement (prepaid).
|
||||
- Full rules: `.claude/commands/syncro.md`.
|
||||
|
||||
12
.claude/memory/feedback_syncro_no_madeup_labor_items.md
Normal file
12
.claude/memory/feedback_syncro_no_madeup_labor_items.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: feedback-syncro-no-madeup-labor-items
|
||||
description: NEVER invent or rename Syncro labor line items — every labor line must use an existing product with its REAL name (from GET /products/<id>); work detail goes in the description field, not the name
|
||||
metadata:
|
||||
type: feedback
|
||||
---
|
||||
|
||||
Every labor line item on a Syncro ticket/invoice MUST be an **existing Syncro product, billed under its REAL name** (fetched from `GET /products/<id>` → `.product.name`) with the live `price_retail`. **NEVER make up a custom line-item name** — even when the `product_id` is a real product. The line's `name` field = the product's actual name, verbatim. Put any work-specific narrative in the `description` field, never by renaming the line.
|
||||
|
||||
**Why:** Mike flagged ticket #32332 (Cascades — Chris Knight new-user setup), where product `26118` (real name **"Labor - Onsite Business"**) was billed on two lines as **"Emergency Call Setup"** and **"Onsite Computer Setup"** — fabricated names. Invented/renamed labor items break the **Syncro -> QuickBooks sync** — QB maps each labor line to an existing item, so a fabricated name has no QB match and messes up the accounting (Mike's stated reason). The **`description` field is free text and can be whatever the work needs** — only the `name`/product must be an existing Syncro item. Mike: "You CANNOT make up labor items. You MUST use existing items only for all labor items... the labor item must use the ones that already exist in syncro (otherwise it messes things up in Quickbooks)."
|
||||
|
||||
**How to apply:** When adding ANY labor line — `GET /products/<id>`, copy `.product.name` verbatim into `name`, use `.product.price_retail` for `price_retail`, `taxable:false` for labor. Pick the correct EXISTING labor product (remote `1190473` "Labor - Remote Business" $150, onsite `26118` "Labor - Onsite Business" $175, emergency/after-hours `26184` "Labor - Emergency or After Hours Business" $262.50, in-shop `573881`, warranty `1049360`, etc. — full table in `/syncro`). Differentiate the work in `description`, not `name`. If no existing product fits the need, STOP and ask Mike — do not invent one. Related: [[feedback-syncro-live-rates]], [[feedback-syncro-warranty-product]].
|
||||
18
.claude/memory/project_quantum_godaddy_m365_tenant.md
Normal file
18
.claude/memory/project_quantum_godaddy_m365_tenant.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
name: quantum-godaddy-m365-tenant
|
||||
description: Quantum Wealth Management M365 migration uses a NEW fully-onboarded tenant 2fd0092b (quantumwms.com verified+primary); the old GoDaddy tenant ddf3d2c9 was bypassed, not taken over
|
||||
metadata:
|
||||
type: project
|
||||
---
|
||||
|
||||
During the Quantum Wealth Management email migration (Intermedia HEX -> Microsoft 365, Syncro #32323), Pax8 reported `quantumwms.com` was "already attached to a tenant." Unauthenticated discovery (2026-05-27) confirmed:
|
||||
|
||||
- **Existing tenant:** `ddf3d2c9-b76c-40d9-a216-9f11a1a26f97`, default domain `netorg18235235.onmicrosoft.com`, brand name "quantumwms.com", **Managed**, NA region. The `NETORG#######.onmicrosoft.com` pattern = **GoDaddy-provisioned M365 tenant**.
|
||||
- `quantumwms.com` itself returns realm **Unknown** (added but not verified-as-primary in that tenant) — this pending/parked claim is what blocks Pax8.
|
||||
- Mail is on **Intermedia** (`*.exch090.serverdata.net`; SPF `spf.intermedia.net`), with GoDaddy (`secureserver.net`) + Proofpoint Essentials (`ppe-hosted.com`) still in SPF. So the GoDaddy M365 tenant is almost certainly **dormant** (no mailboxes there).
|
||||
|
||||
**Why this matters:** It's a *Managed* tenant, so there is **NO DNS-based admin takeover** (that only works on unmanaged/viral tenants). Access requires the customer's **GoDaddy account login / the tenant Global Admin**, or GoDaddy releasing it.
|
||||
|
||||
**RESOLUTION (2026-05-27):** Mike chose to **spin up a fresh tenant** rather than take over GoDaddy's (only 2 users — cleaner). The operative tenant is now **`2fd0092b-e9b7-474c-ad73-301f34dd6b64`** ("Quantum Wealth Management", `quantumwms.onmicrosoft.com`): `quantumwms.com` is **verified + primary** there, `john@`/`sheila@` are licensed (Pax8 M365), `sysadmin@quantumwms.com` is the ACG admin. Pax8 GDAP approved + the **full ComputerGuru app suite consented & directory-roles assigned via `onboard-tenant.sh`** (Tenant Admin, Security Investigator, Exchange Operator, User Manager, Defender; Exch/User/Auth/CA roles). The GoDaddy tenant `ddf3d2c9` (netorg18235235.onmicrosoft.com) was **bypassed** — it never verified the domain, so the new tenant claimed it; no GoDaddy takeover/defederate needed. Remaining migration steps: PST backups of both mailboxes (Intermedia has no server-side export), DNS cutover (MX/autodiscover/archival+sent-mail-encryption — Jen Curry/IFG meeting Thu 2026-05-28 1PM), then move mail Intermedia -> M365. Tracked on Syncro #32323; tenant row added to remediation-tool gotchas.md table.
|
||||
|
||||
**(Historical) original blocker:** Pax8 reported the domain "attached to a tenant" = the GoDaddy-provisioned `ddf3d2c9` (NETORG onmicrosoft). Managed tenant, so no DNS takeover; would have needed GoDaddy GA access. Superseded by the fresh-tenant decision above.
|
||||
Reference in New Issue
Block a user