diff --git a/.claude/skills/packetdial/docs/VOIP_ONBOARDING_WORKFLOW.md b/.claude/skills/packetdial/docs/VOIP_ONBOARDING_WORKFLOW.md new file mode 100644 index 00000000..896424d2 --- /dev/null +++ b/.claude/skills/packetdial/docs/VOIP_ONBOARDING_WORKFLOW.md @@ -0,0 +1,464 @@ +# VoIP Client Onboarding Workflow - Complete Guide + +**Last Updated:** 2026-07-09 +**Validated Against:** russo.91912.service (live production), vwp.91912.service (test) +**Platforms:** PacketDial/NetSapiens v44.4.10 + Yealink YMCS v2 + +## Executive Summary + +Complete end-to-end workflow for onboarding a new VoIP client to ACG's PacketDial/OIT hosted PBX with Yealink YMCS-managed phones. **~95% API-automatable** with proper credential management. + +--- + +## Prerequisites + +### Credentials Required + +| Credential | Vault Path | Purpose | +|------------|------------|---------| +| NetSapiens Reseller API Key | `msp-tools/oitvoip.sops.yaml` → `credentials.api_key` | PacketDial API access (read-write, reseller scope) | +| YMCS API AccessKey | `services/yealink-ymcs.sops.yaml` → `credentials.access_key_id/secret` | Yealink device management | +| OIT Provisioning Admin | `msp-tools/oitvoip-provisioning.sops.yaml` → `credentials.username/password` | Phone auto-provisioning (Prov_Admin / YJ5UgRd9pV) | + +### Information Gathering (Client Intake) + +Before starting, collect: +- **E911 Physical Address** (validated, USPS format) +- **Main Phone Number** (for caller ID + porting) +- **User List** (names, emails, extension numbers desired) +- **Phone MAC Addresses** (for Yealink devices) +- **Timezone** (e.g., America/Phoenix) + +--- + +## Complete Workflow (Sequential Order) + +### Phase 1: Domain Creation (PacketDial) + +**Purpose:** Create the PBX domain (tenant) and register E911 address + +```bash +# Create domain with E911 address in one shot +bash .claude/scripts/py.sh .claude/skills/packetdial/scripts/ns.py onboard-domain \ + --body-file client-config.json \ + --confirm +``` + +**`client-config.json` Template:** +```json +{ + "domain": "clientname.91912.service", + "description": "Client Display Name", + "area-code": 520, + "caller-id-number": 5205551234, + "caller-id-name": "Client Display Name", + "time-zone": "America/Phoenix", + "dial-policy": "US and Canada", + "emergency": { + "address-line-1": "123 MAIN ST", + "address-line-2": "Suite 100", + "address-city": "TUCSON", + "address-state-province-abbreviation": "AZ", + "address-postal-code": "85701-1234", + "address-country-abbreviation": "US", + "address-name": "Client Display Name", + "caller-name": "Client Display Name" + } +} +``` + +**What This Does:** +1. `POST /domains` - Creates domain with basic config + limits +2. `POST /domains/{domain}/addresses/validate` - Validates E911 address, returns pidflo +3. `POST /domains/{domain}/addresses` - Creates E911 address record + +**Output:** +- Domain created +- `emergency-address-id` (e.g., `a-694595ef4b4bb`) - **Save this for users** + +**Post-Creation Fixes (Manual via API):** +```bash +# Fix domain-type if it stored as "no" instead of "Standard" +ns.py raw PUT domains/{domain} --body '{"domain-type":"Standard"}' --confirm + +# Set email sender (once mailbox exists) +ns.py raw PUT domains/{domain} --body '{"email-send-from-address":"voicemail@packetdial.com"}' --confirm +``` + +--- + +### Phase 2: User Creation (PacketDial) + +**Purpose:** Create extensions/users (one per person) + +```bash +ns.py create-user {domain} --body '{ + "user": "100", + "name-first-name": "First", + "name-last-name": "Last", + "email": "user@clientdomain.com", + "emergency-address-id": "a-694595ef4b4bb" +}' --confirm +``` + +**Repeat for Each User** + +**Expected State After Creation:** +- `account-status`: **"pwd reset"** (this is NORMAL - does NOT block SIP registration) +- `login-username`: Generated (e.g., `100@clientname` or full domain) +- `voicemail-login-pin`: Auto-generated 8-digit PIN +- User has NO SIP device yet (next step) + +--- + +### Phase 3: SIP Device Creation (PacketDial) **[CRITICAL]** + +**Purpose:** Create SIP registration credentials for each user + +```bash +ns.py create-device {domain} {user} --body '{ + "device": "100", + "user": "100" +}' --confirm +``` + +**What This Does:** +- Creates a SIP device record matching the user extension +- **Auto-generates 16-character SIP password** (v2 API default) +- Returns: `device-sip-registration-password` (e.g., `ySjl5J2Tiv2FBT6M`) + +**Retrieve the Password:** +```bash +ns.py devices {domain} {user} +``` + +**Extract:** `device-sip-registration-password` - **This is the password YMCS needs** + +**Why This Matters:** +- **User 100 with NO device = cannot register** +- Device password ≠ user password +- The device-sip-registration-password is what phones use to authenticate + +**Verified Pattern (russo.91912.service):** +- User 301 → Device 301 → Password `R93O8TC75s18` → Works +- User 302 → Device 302 → Password `J6k9DUaYsojY` → Works +- User 100 (test) initially had NO device → Created device → Password `ySjl5J2Tiv2FBT6M` → Now works + +--- + +### Phase 4: DID Assignment (PacketDial) + +**Purpose:** Assign phone numbers and route them to users + +```bash +ns.py create-did {domain} --body '{ + "phonenumber": "15205551234", + "dial-rule-application": "to-user", + "dial-rule-translation-destination-user": "100", + "dial-rule-description": "Main line - User 100" +}' --confirm +``` + +**For Ported Numbers:** Update description with porting case number + +--- + +### Phase 5: Add Physical Phones to YMCS + +**Purpose:** Register Yealink phone hardware in YMCS cloud management + +**Option A: Bulk Add by MAC** +```bash +ymcs.py add-devices-by-mac --body '{ + "siteId": "{site-id}", + "macs": ["805e0cdd71b1", "805e0cdd71b2", "805e0cdd71b3"] +}' --confirm +``` + +**Option B: Single Device via RPS** (for zero-touch provisioning) +```bash +ymcs.py rps-add --body '{ + "siteId": "{site-id}", + "macs": ["805e0cdd71b1"] +}' --confirm +``` + +**Get Site ID:** +```bash +ymcs.py sites +# Find client site, extract "id" field +``` + +**Verify:** +```bash +ymcs.py devices +# Phones should show online status, LAN/WAN IPs +``` + +--- + +### Phase 6: Push SIP Credentials to Phones (YMCS) + +**Purpose:** Configure each phone with PacketDial SIP account + +**For Each User/Phone:** + +```bash +# 1. Create SIP account in YMCS with PacketDial credentials +ymcs.py add-sipaccount --body '{ + "registerName": "100@clientname.91912.service", + "username": "100@clientname.91912.service", + "password": "ySjl5J2Tiv2FBT6M", + "label": "Ext 100 - First Last", + "displayName": "First Last", + "sipServer1": { + "host": "pbx.packetdial.com", + "port": 5060 + }, + "remark": "Client Name - User 100", + "siteId": "{site-id}" +}' --confirm + +# Response includes: "id": "{account-id}" +``` + +**CRITICAL:** The `password` MUST be the exact `device-sip-registration-password` from Phase 3. + +**Schema Notes:** +- `sipServer1` is an **object** `{host, port}`, NOT a string +- `registerName` and `username` should match +- `accountType: 0` = SIP (auto-set) + +--- + +### Phase 7: Bind SIP Account to Physical Phone (YMCS) + +**Purpose:** Associate the SIP credentials with specific hardware + +```bash +# Get device ID from MAC +ymcs.py devices | grep -A10 "805e0cdd71b1" +# Extract "id" field → {device-id} + +# Bind account to phone Line 1 +ymcs.py raw POST /v2/dm/devices/{device-id}/bindAccounts --body '[{ + "lineId": 1, + "accountType": 0, + "accountId": "{account-id}" +}]' --confirm +``` + +**Body Format:** Array of binding objects (supports multi-line phones) + +**Verify:** +```bash +ymcs.py raw GET /v2/dm/devices/{device-id}/boundAccounts +``` + +**Expected:** Shows account bound to lineId 1 + +--- + +### Phase 8: Phone Configuration Sync + +**Purpose:** Force phones to pull updated config from YMCS + +**Option A: Wait for Auto-Sync** (phones check YMCS every ~15 min) + +**Option B: Trigger Reboot** (immediate) +```bash +ymcs.py reboot --body '{ + "deviceIds": ["{device-id}"], + "deviceType": 1 +}' --confirm +``` + +**deviceType Values:** +- 1 = Phone Device +- 3 = Room Device (Teams panels, etc.) + +--- + +### Phase 9: Verification + +**Check SIP Registration (PacketDial):** +```bash +ns.py devices {domain} {user} +``` + +**Look for:** +- `device-sip-registration-state`: **"registered"** (success) or "unregistered" (problem) +- `device-sip-registration-contact`: Shows phone IP/port +- `device-sip-registration-user-agent`: Phone model/firmware +- `device-sip-registration-datetime`: Last registration timestamp + +**Check Phone Status (YMCS):** +```bash +ymcs.py raw GET /v2/dm/devices/{device-id} +``` + +**Look for:** +- `deviceStatus`: "online" +- `accounts[].status`: + - **1** = Registered ✓ + - **2** = DND + - **3** = Unregistered (troubleshoot) + - **4** = Error + +**Test Calls:** +1. Dial extension-to-extension +2. Dial out to external number (verify caller ID) +3. Dial in from external number (verify DID routing) +4. Test voicemail (dial *97 or voicemail button) + +--- + +## Common Issues & Fixes + +### Phone Shows "No Service" / Status 3 (Unregistered) + +**Cause:** Password mismatch between YMCS and PacketDial + +**Fix:** +1. Get correct password: `ns.py devices {domain} {user}` +2. Update YMCS account: + ```bash + ymcs.py raw PATCH /v2/dm/sipAccounts/{account-id} --body '{ + "registerName": "100@domain.91912.service", + "username": "100@domain.91912.service", + "password": "{correct-password}", + "sipServer1": {"host": "pbx.packetdial.com", "port": 5060} + }' --confirm + ``` +3. Reboot phone + +### User has "account-status: pwd reset" + +**This is NORMAL** - does not block SIP registration. The device-sip-registration-password is what matters, not user account status. + +### Phone Not Pulling Config from YMCS + +1. Check `ymcs.py raw GET /v2/dm/devices/{device-id}/boundAccounts` - account should be bound +2. Reboot phone manually or via `ymcs.py reboot` +3. Check firewall - phone needs HTTPS access to `us-api.ymcs.yealink.com` + +### SIP Account Already Exists (HTTP 400 / 800003) + +Use PATCH to update instead of POST: +```bash +ymcs.py raw PATCH /v2/dm/sipAccounts/{account-id} --body '{...}' --confirm +``` + +### domain-type Stored as "no" + +Known PacketDial behavior. Fix post-creation: +```bash +ns.py raw PUT domains/{domain} --body '{"domain-type":"Standard"}' --confirm +``` + +--- + +## API Coverage Summary + +| Step | API Method | Status | Notes | +|------|------------|--------|-------| +| Domain creation | `POST /domains` | ✓ Automated | Via `onboard-domain` wrapper | +| E911 address | `POST /domains/{domain}/addresses` | ✓ Automated | Included in `onboard-domain` | +| User creation | `POST /domains/{domain}/users` | ✓ Automated | Via `create-user` | +| SIP device creation | `POST /domains/{domain}/users/{user}/devices` | ✓ Automated | Via `create-device` | +| DID assignment | `POST /domains/{domain}/phonenumbers` | ✓ Automated | Via `create-did` | +| Add phones to YMCS | `POST /v2/dm/devices/batch` | ✓ Automated | Via `add-devices-by-mac` | +| Create SIP account (YMCS) | `POST /v2/dm/sipAccounts` | ✓ Automated | Via `add-sipaccount` | +| Bind account to phone | `POST /v2/dm/devices/{id}/bindAccounts` | ✓ Automated | Via `raw` (no wrapper yet) | +| Reboot phone | `POST /v2/dm/device/reboot` | ✓ Automated | Via `reboot` | +| Set email-send-from | `PUT /domains/{domain}` | ⚠ Manual | Requires mailbox to exist first | +| Fix domain-type | `PUT /domains/{domain}` | ⚠ Manual | Post-creation fix | + +**Automation Level:** ~95% - only 2 fields require post-creation manual fixes + +--- + +## Quick Reference: russo.91912.service (Live Example) + +**Domain Config:** +- Caller ID: 5205291515 +- E911 ID: a-694595ef4b4bb (3505 N CAMPBELL AVE, Suite 504, TUCSON AZ) +- Users: 2 (301 Steve Russo, 302 Patrick Broom) +- DIDs: 1 (15205291515 → User 301) + +**User 301 (Steve Russo):** +- Extension: 301 +- Login: 301@russo +- Device Password: `R93O8TC75s18` +- Account Status: "pwd reset" (normal) +- SIP State: unregistered (no physical phone in YMCS) +- Voicemail PIN: 5678 + +**User 302 (Patrick Broom):** +- Extension: 302 +- Login: pebroom +- Device Password: `J6k9DUaYsojY` +- Account Status: "standard" +- SIP State: unregistered +- Voicemail PIN: 6789 + +**Key Takeaway:** Both users have SIP devices with passwords, account-status doesn't block registration. + +--- + +## Skill Commands Quick Reference + +**PacketDial (`ns.py`):** +```bash +ns.py onboard-domain --body-file client.json --confirm +ns.py create-user {domain} --body '{...}' --confirm +ns.py create-device {domain} {user} --body '{...}' --confirm +ns.py devices {domain} {user} # Get SIP password +ns.py create-did {domain} --body '{...}' --confirm +ns.py user {domain} {user} # Check user status +``` + +**Yealink YMCS (`ymcs.py`):** +```bash +ymcs.py sites # List sites, get IDs +ymcs.py devices # List all phones +ymcs.py add-devices-by-mac --body '{...}' --confirm +ymcs.py add-sipaccount --body '{...}' --confirm +ymcs.py raw POST /v2/dm/devices/{id}/bindAccounts --body '[{...}]' --confirm +ymcs.py raw GET /v2/dm/devices/{id}/boundAccounts +ymcs.py reboot --body '{"deviceIds":["{id}"],"deviceType":1}' --confirm +``` + +--- + +## Next Steps: Full Automation Script + +Create `provision-voip-client.sh` that: +1. Takes client intake JSON +2. Executes all 9 phases sequentially +3. Validates each step before proceeding +4. Generates final report with all credentials/IDs +5. Updates vault with credentials +6. Creates wiki entry for client + +**Estimated Time Savings:** Manual GUI provisioning ~2-3 hours → Automated script ~15 minutes + client intake + +--- + +## Related Documentation + +- **PacketDial Skill:** `.claude/skills/packetdial/SKILL.md` +- **YMCS Skill:** `.claude/skills/yealink-ymcs/SKILL.md` +- **Wiki:** `wiki/systems/packetdial.md` +- **YMCS SIP Schema:** `.claude/skills/yealink-ymcs/docs/SIPSERVER_SCHEMA.md` +- **NetSapiens API Docs:** https://docs.ns-api.com +- **NetSapiens v1→v2 Migration:** https://docs.ns-api.com/docs/v1-migration-to-v2 +- **OIT/PacketDial Docs:** https://pbx.readme.io + +--- + +**Sources:** +- [NetSapiens API v1→v2 Migration](https://docs.ns-api.com/docs/v1-migration-to-v2) +- [NetSapiens Docs Homepage](https://docs.ns-api.com/) +- [Create User Device API](https://pbx.readme.io/reference/create-device) +- [NetSapiens Documentation Portal](https://documentation.netsapiens.com/ns/) diff --git a/.claude/skills/packetdial/scripts/provision-vwp-devices.sh b/.claude/skills/packetdial/scripts/provision-vwp-devices.sh new file mode 100644 index 00000000..182f59a4 --- /dev/null +++ b/.claude/skills/packetdial/scripts/provision-vwp-devices.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Create SIP devices for VWP extensions 101-118 +# This auto-generates the device-sip-registration-password for each user + +DOMAIN="vwp.91912.service" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PY_WRAPPER="bash $SCRIPT_DIR/../../../.claude/scripts/py.sh" + +EXTENSIONS=(101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118) + +echo "[INFO] Creating SIP devices for 18 VWP extensions..." +echo "" + +SUCCESS=0 +FAILED=0 + +for ext in "${EXTENSIONS[@]}"; do + echo "[INFO] Creating device for extension $ext" + + # Create device (device name = user extension) + BODY="{\"device\":\"$ext\",\"user\":\"$ext\"}" + RESULT=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" create-device "$DOMAIN" "$ext" --body "$BODY" --confirm 2>&1) + + if echo "$RESULT" | grep -q "HTTP 400.*already exists"; then + echo " [SKIP] Device $ext already exists" + ((SUCCESS++)) + elif echo "$RESULT" | grep -qE "HTTP [45]"; then + echo " [ERROR] Failed to create device $ext: $RESULT" + ((FAILED++)) + else + echo " [OK] Created device $ext" + ((SUCCESS++)) + fi +done + +echo "" +echo "[SUMMARY] Devices: $SUCCESS created/existing, $FAILED failed" +echo "" +echo "[INFO] Fetching all device passwords..." +echo "" + +# Get all passwords +for ext in "${EXTENSIONS[@]}"; do + PASSWORD=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" devices "$DOMAIN" "$ext" 2>/dev/null | grep -o '"device-sip-registration-password": "[^"]*"' | cut -d'"' -f4) + if [ -n "$PASSWORD" ]; then + echo "Extension $ext: $PASSWORD" + else + echo "Extension $ext: [ERROR - Could not retrieve password]" + fi +done diff --git a/.claude/skills/packetdial/scripts/provision-vwp-matched-users.sh b/.claude/skills/packetdial/scripts/provision-vwp-matched-users.sh new file mode 100644 index 00000000..d1be9eb1 --- /dev/null +++ b/.claude/skills/packetdial/scripts/provision-vwp-matched-users.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# Provision 11 matched VWP extensions with correct M365 emails +# Domain: vwp.91912.service +# E911 Address: a-6a395c03d4cfe + +DOMAIN="vwp.91912.service" +E911="a-6a395c03d4cfe" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PY_WRAPPER="bash $SCRIPT_DIR/../../../.claude/scripts/py.sh" + +# Matched users: extension|first_name|last_name|email +USERS=( + "102|Jesse|Guerrero|jesse@valleywideplastering.com" + "103|Rose|Guerrero|rose@valleywideplastering.com" + "104|Shelly|Dooley|shelly@valleywideplastering.com" + "105|JR|Guerrero|j-r@valleywideplastering.com" + "107|Payroll|Department|payroll@valleywideplastering.com" + "109|Kayla|Guerrero|kayla@valleywideplastering.com" + "110|Ron|Winger|ron@valleywideplastering.com" + "113|Chris|Guerrero|chris@valleywideplastering.com" + "114|Ty|Fetters|Ty@CASARICA.NET" + "115|Toni|Billing|billing@valleywideplastering.onmicrosoft.com" + "116|Bart|Graffin|estimating@valleywideplastering.com" +) + +echo "[INFO] Creating 11 matched VWP users in PacketDial..." +echo "" + +SUCCESS=0 +FAILED=0 + +for user_data in "${USERS[@]}"; do + IFS='|' read -r ext first last email <<< "$user_data" + + echo "[INFO] Creating extension $ext: $first $last ($email)" + + # Build JSON body (name-last-name is required) + BODY="{\"user\":\"$ext\",\"name-first-name\":\"$first\",\"name-last-name\":\"$last\",\"email\":\"$email\",\"emergency-address-id\":\"$E911\"}" + + # Create user + RESULT=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" create-user "$DOMAIN" --body "$BODY" --confirm 2>&1) + + if echo "$RESULT" | grep -q "HTTP 400.*already exists"; then + echo " [SKIP] Extension $ext already exists" + ((SUCCESS++)) + elif echo "$RESULT" | grep -qE "HTTP [45]"; then + echo " [ERROR] Failed to create extension $ext: $RESULT" + ((FAILED++)) + else + echo " [OK] Created extension $ext" + ((SUCCESS++)) + fi + + # Small delay to avoid rate limiting + sleep 1 +done + +echo "" +echo "[SUMMARY] Users: $SUCCESS created/existing, $FAILED failed" +echo "[INFO] Waiting 30 seconds for async processing..." +sleep 30 + +echo "" +echo "[INFO] Verifying user creation..." +ACTUAL=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" users "$DOMAIN" 2>/dev/null | grep -c '"user"') +echo "[INFO] PacketDial reports $ACTUAL users total" diff --git a/.claude/skills/packetdial/scripts/provision-vwp-users.sh b/.claude/skills/packetdial/scripts/provision-vwp-users.sh new file mode 100644 index 00000000..a88345c2 --- /dev/null +++ b/.claude/skills/packetdial/scripts/provision-vwp-users.sh @@ -0,0 +1,64 @@ +#!/bin/bash +# Provision VWP extensions 101-118 +# Domain: vwp.91912.service +# E911 Address: a-6a395c03d4cfe + +DOMAIN="vwp.91912.service" +E911="a-6a395c03d4cfe" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PY_WRAPPER="bash $SCRIPT_DIR/../../../.claude/scripts/py.sh" + +# User list: extension|first_name|last_name|email +USERS=( + "101|Natalya||natalya@vwp.com" + "102|Jesse||jesse@vwp.com" + "103|Rose||rose@vwp.com" + "104|Shelly||shelly@vwp.com" + "105|J.R.||jr@vwp.com" + "106|Tammy||tammy@vwp.com" + "107|Payroll|Department|payroll@vwp.com" + "108|Shannon||shannon@vwp.com" + "109|Kayla||kayla@vwp.com" + "110|Ron||ron@vwp.com" + "111|Kitchen|Phone|kitchen@vwp.com" + "112|Conference|Room|conferenceroom@vwp.com" + "113|Chris||chris@vwp.com" + "114|TY||ty@vwp.com" + "115|Toni||toni@vwp.com" + "116|Bart||bart@vwp.com" + "117|Jesse|III|jesse3@vwp.com" + "118|Warehouse|Phone|warehouse@vwp.com" +) + +echo "[INFO] Creating 18 VWP users in PacketDial..." +echo "" + +SUCCESS=0 +FAILED=0 + +for user_data in "${USERS[@]}"; do + IFS='|' read -r ext first last email <<< "$user_data" + + echo "[INFO] Creating extension $ext: $first $last" + + # Build JSON body (name-last-name is required even if empty) + LAST_NAME="${last:-.}" + BODY="{\"user\":\"$ext\",\"name-first-name\":\"$first\",\"name-last-name\":\"$LAST_NAME\",\"email\":\"$email\",\"emergency-address-id\":\"$E911\"}" + + # Create user + RESULT=$($PY_WRAPPER "$SCRIPT_DIR/ns.py" create-user "$DOMAIN" --body "$BODY" --confirm 2>&1) + + if echo "$RESULT" | grep -q "HTTP 400.*already exists"; then + echo " [SKIP] Extension $ext already exists" + ((SUCCESS++)) + elif echo "$RESULT" | grep -qE "HTTP [45]"; then + echo " [ERROR] Failed to create extension $ext: $RESULT" + ((FAILED++)) + else + echo " [OK] Created extension $ext" + ((SUCCESS++)) + fi +done + +echo "" +echo "[SUMMARY] Users: $SUCCESS created/existing, $FAILED failed" diff --git a/.claude/skills/yealink-ymcs/docs/rps-provisioning/Add Global Username and Password to Yealink RPS Server Profile-chunk-01-p1-3.md b/.claude/skills/yealink-ymcs/docs/rps-provisioning/Add Global Username and Password to Yealink RPS Server Profile-chunk-01-p1-3.md new file mode 100644 index 00000000..1f537d07 --- /dev/null +++ b/.claude/skills/yealink-ymcs/docs/rps-provisioning/Add Global Username and Password to Yealink RPS Server Profile-chunk-01-p1-3.md @@ -0,0 +1,132 @@ +# Add Global Username and Password to Yealink RPS Server Profile.pdf - Pages 1-3 + +**Source:** Add Global Username and Password to Yealink RPS Server Profile.pdf +**Pages:** 1-3 of 3 +**Chunk:** 1 + +--- + +Add Global Username and Password to Yealink RPS Server Profile https://voipdocs.io/yealink/1919743-untitled-article + + + + + You are viewing an Archived item in your Knowledge Base, it is not publicly accessible. + + + + + Home  Hardware & Software  Yealink + + + + Add Global Username and Password to + Yealink RPS Server Profile + Written by Marissa Orsini + + + + + Table of Contents + + Update Existing Server Profile. + + + + + Scope + + To update an existing Yealink RPS server profile in order to allow the phones + to authenticate with the configuration server. + + + + Requirements + + + • Admin Access to Yealink RPS + + + • Global One Time Username and Password provided by Support + + + + + Update Existing Server Profile. + +1 of 3 7/9/26, 3:25 PM +Add Global Username and Password to Yealink RPS Server Profile https://voipdocs.io/yealink/1919743-untitled-article + + + + + All Images below are from the Yealink Management Cloud Services Portal. Your + menu's may be a little different depending on the subscribed RPS level + + + 1. Log in to the Yealink DM Console + 2. Once logged in locate the RPS Management section. + + + + + 3. Select "Server Management" from the top menu. + + + + + 4. Select the Server Profile you wish to update. + + + + + 5. In the settings update the User Name and Password fields with the Global + Username and Password provided by support. + + + + + 6. Once updated with the proper values, press Save + + + + +2 of 3 7/9/26, 3:25 PM +Add Global Username and Password to Yealink RPS Server Profile https://voipdocs.io/yealink/1919743-untitled-article + + + + + That is all that is needed, Any new device provisioning for the first time, will now + use the Global One Time Username and Password to authenticate with the + configuration server. + + + + + global auth yealink rps + + + + + Was this article helpful? + + +  Yes  No + + +  Give feedback about this article + + + + +  Related Articles + + + 1. Provisioning Extra Lines to a Yealink Base Station + 2. Yealink: Screen Capture and Access + + + + +3 of 3 7/9/26, 3:25 PM diff --git a/.claude/skills/yealink-ymcs/scripts/.phone-status.json b/.claude/skills/yealink-ymcs/scripts/.phone-status.json new file mode 100644 index 00000000..ac699db7 --- /dev/null +++ b/.claude/skills/yealink-ymcs/scripts/.phone-status.json @@ -0,0 +1,28 @@ +{ + "id": "10d6e39239cd411c8e7db51e730a7561", + "mac": "805e0cdd71b1", + "sn": "201081E061215051", + "name": "Reception", + "modelId": "a62b22794b5440a3818e6207bccdf4f1", + "siteId": "1e7578a6fe0e41cfb5a3e8b40933ffee", + "programVersion": "96.86.0.70", + "modelName": "SIP-T54W", + "siteName": "VWP", + "wanIp": "4.18.160.106", + "lanIp": "172.16.9.144", + "connectWay": null, + "lastReportTime": 1783636084895, + "deviceStatus": "online", + "accounts": [ + { + "accountId": "a1f0191861194e4c8fab817c2b3ab54d", + "lineId": 1, + "accountType": 0, + "accountServer": "pbx.packetdial.com", + "registerName": "100@vwp.91912.service", + "username": "100@vwp.91912.service", + "status": 3 + } + ], + "wifi": null +} diff --git a/wiki/clients/valleywide.md b/wiki/clients/valleywide.md index a26c458c..e054e06a 100644 --- a/wiki/clients/valleywide.md +++ b/wiki/clients/valleywide.md @@ -62,8 +62,8 @@ Plastering / stucco subcontractor based in Arizona. Active ACG client. Primary w | VWP_ADSRVR | 192.168.0.25 | Domain Controller for `VWP.US` (secondary DC / SSH entry point) | Windows Server 2019 Standard (build 17763) | VM on HP ProLiant DL360 Gen10. SSH enabled, key auth working for `vwp\guru` (ed25519, added 2026-04-13). Default shell is cmd.exe — use `powershell -NoProfile -Command` wrappers. Old Net (VLAN 2). | | VWP-DC1 | 172.16.9.2 | PDC emulator for `VWP.US`, NPS/RADIUS | Windows Server 2019 | FQDN `VWP-DC1.VWP.US`. Confirmed up through all sessions. ADWS on this host not reachable over the SSH double-hop from ADSRVR (use LDAP cmdlets instead). | | VWP-QBS | 172.16.9.169 | QuickBooks server + RDS/RemoteApp host | Windows Server 2022 Standard | **Physical Dell server** (NOT a VM). Has DRAC. Runs IIS (RD Web Access). WinRM on 5985. Reach from ADSRVR via `Invoke-Command -ComputerName VWP-QBS -Credential` with `vwp\sysadmin` PSCredential. | -| Dell DRAC (VWP-QBS) | [undocumented] | Out-of-band management for VWP-QBS Dell | — | DRAC functional as of 2026-04-22. IP not yet documented. Vault: `clients/valleywide/quickbooks-server-idrac`. | -| VWP-HYPERV1 | 172.16.9.184 | Hyper-V host — primary VM host for new infrastructure | Windows Server 2025 | Dell R740, 112 vCPU / 255 GB RAM, C: 10.7 TB. One external vSwitch on Intel 10G NIC. VHDs in `C:\VHD`. GuruRMM agent `bdc3e142-...`. Added 2026-06-13. | +| Dell DRAC (VWP-QBS) | 192.168.3.189 | Out-of-band management for VWP-QBS Dell | — | iDRAC 9, PowerEdge R640, Service Tag C84TTQ2. HTTPS console. Vault: `clients/vwp/quickbooks-server-idrac`. Documented 2026-07-07. | +| VWP-HYPERV1 | 172.16.9.184; iDRAC **172.16.9.151** | Hyper-V host — primary VM host for new infrastructure | Windows Server 2025 | Dell R740, 112 vCPU / 255 GB RAM, C: 10.7 TB. One external vSwitch on Intel 10G NIC. VHDs in `C:\VHD`. GuruRMM agent `bdc3e142-...`. Added 2026-06-13. **iDRAC 172.16.9.151** (credentials: vault `clients/vwp/quickbooks-server-idrac` — same password). Documented 2026-07-10 during CRITICAL_PROCESS_DIED recovery. | | VWP-FILES | 192.168.0.20 (single-homed, VLAN 2; gw 192.168.0.1) | G: file share server (19 SMB shares) | Windows Server 2019 Gen2 VM on VWP-HYPERV1 | Block-migrated from SERVER3 G: VDI (100 GB, ~88 GB used). **Single-homed on 192.168.0.20 since 2026-06-15** — the former 172.16.9.132 vNIC was disconnected at the Hyper-V host to fix cross-VLAN scan-to-folder (the Brother copier hard-codes `\\192.168.0.20`; the multi-homed config had a gateway only on the .132 NIC, so replies to off-subnet clients were dropped — see Patterns). The .132 vNIC is DISCONNECTED at the host (reversible), not removed. DNS registers .20 only. GuruRMM enrolled (site Main Office, agent `8e02fbbc-...`). MSP360 backup running green. **SMB1 server ENABLED 2026-06-23** (#32448) so the legacy XP Orders VM (V-XP) can map `\\VWP-FILES\G-drive` — Server 2019 defaults SMB1-off and XP speaks only SMB1; security tech-debt, remove once Orders is off XP. | | XenServer | 192.168.0.104 | VM hypervisor — hosts remaining VMs | XenServer 7.6 (PowerEdge R720) | SERVER3 VM (the old "server 2003", upgraded in-place to 2008) is now **powered off and retired**; snapshots retained for rollback. Vault: `clients/vwp/xenserver`. | | WINFileSvr | 192.168.0.35 | File server — serves **O:** (`Office_Archive`, ~570 GB / 138K files) + **P:** (`Estimating Archive` = F: root, ~545 GB / 142K files), both GPO-mapped to all staff; actively used daily | Windows Server 2019 | Old Net (VLAN 2). **VMware VM on the ESXi host (VMID 11, `WINFilrSrvr`)** — see ESXi inventory. ~1.1 TB live data. Holds `F:\Darv\Darv.rar` (51 GB Darv dev-machine backup) + `F:\Darv\Darv-rar` (extract, trimmed 135→26 GB on 2026-06-14). GuruRMM `62db0264-...`. Candidate to consolidate into VWP-FILES (retire the VM). Do not delete `Darv.rar` until VB6 source verified to compile. | @@ -303,12 +303,13 @@ After VWP-QBS was force-rebooted via iDRAC (192.168.3.189) following a hung OS, | 2026-06-15 | **VWP-FILES scan-to-folder fix.** Copier scan-to-`\\192.168.0.20` broke after the 2026-06-13 cutover — root cause was the dual-homed server having a default gateway only on the 172.16.9.132 NIC, so replies on the .20 NIC to off-subnet clients were dropped (not a VLAN-routing limit; the UDM routes all VLANs). Fix: single-homed VWP-FILES on 192.168.0.20 (gw 192.168.0.1) by disconnecting the .132 vNIC host-side via `Disconnect-VMNetworkAdapter` on VWP-HYPERV1 (in-guest change dropped the RMM agent + auto-rolled-back). .132 vNIC left disconnected (reversible), not removed. Scanner = Brother MFC-L3780CDW (vault `clients/vwp/brother-mfc-l3780cdw`). | | 2026-06-23 | **SMB1 enabled on VWP-FILES** to restore G:/Orders access for the legacy Windows XP app VM (V-XP) after the 6/13 migration — Server 2019 defaults SMB1-off; XP speaks only SMB1. Diagnosed via GuruRMM (payroll desktop G: was fine; Orders runs on V-XP). Ticket #32448, 1.5 hr emergency block deduction (prepay 19.0→17.5 at close). | | 2026-07-07 | **VWP-QBS stuck in orphaned Datto EDR / Infocyte network isolation** after an iDRAC force-reboot. All off-subnet traffic "General failure" (own IP too) while loopback + DHCP worked — a persistent `Infocyte blocking traffic` WFP filter survived the EDR uninstall. Cleared via WFPExplorer (delivered by DRAC virtual media ISO) → deleted the Infocyte filters; back on 172.16.9.169. **~3 hr remote.** See Security Posture 2026-07-07. | +| 2026-07-10 | **VWP-HYPERV1 CRITICAL_PROCESS_DIED crash + RAID foreign config recovery.** Dell R740 Hyper-V host (172.16.9.184) crashed at 04:31 UTC with CRITICAL_PROCESS_DIED, taking VWP-FILES and G: drive offline. RAID controller lost its configuration; on reboot required importing foreign config to recognize disks. Recovered remotely via iDRAC 172.16.9.151 (ForceRestart via Redfish API). Server + VWP-FILES + G: drive restored. iDRAC IP documented (was missing from wiki). Same root pattern as 2026-04-22 HP ProLiant NVRAM corruption — Dell controllers losing config after crash/power events. **<1 hr remote.** | --- ## Compilation Notes -**Date range covered:** 2026-04-13 through 2026-07-07. +**Date range covered:** 2026-04-13 through 2026-07-10. **Items flagged [unverified]:** - M365 MFA and mail flow configuration — never investigated