sync: auto-sync from GURU-5070 at 2026-06-22 08:23:12
Author: Mike Swanson Machine: GURU-5070 Timestamp: 2026-06-22 08:23:12
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
# Session — OITVOIP key vaulted + packetdial skill fully built out; SC admin handoff
|
||||
|
||||
## User
|
||||
- **User:** Mike Swanson (mike)
|
||||
- **Machine:** GURU-5070
|
||||
- **Role:** admin
|
||||
|
||||
## Session Summary
|
||||
|
||||
Picked up Howard's parked Tier-1 item #2 (packetdial non-functional, no creds). Mike pointed at
|
||||
`C:\Users\guru\Downloads\OIT-API.txt`, which held the OITVOIP/PacketDial NetSapiens **reseller**
|
||||
API key. Vaulted it at `msp-tools/oitvoip.sops.yaml` → `credentials.api_key` (the exact path/field
|
||||
the packetdial skill reads), documented it in the entry, and live-verified with `ns.py whoami`:
|
||||
key-id `nsr_hSGUB5Wo`, scope **Reseller** (`91912.service`), `user/domain: *`, read-write. Works
|
||||
against the skill's default host `pbx.packetdial.com/ns-api/v2` (no `api.ucaasnetwork.com` override
|
||||
needed). Published the vault and told Howard his item was unblocked.
|
||||
|
||||
RTFM'd the live NetSapiens API to ground the skill: fetched the OpenAPI spec (v2 **v44.4.10**,
|
||||
**239 paths / 354 operations**), mapped the surface (nearly everything nested under
|
||||
`/domains/{domain}/...`), and live-probed real response shapes. The pre-existing packetdial skill
|
||||
predated the key, so it had unverified guessy paths; I added 6 live-verified read wrappers
|
||||
(callqueues, timeframes, sites, contacts, autoattendants, billing) and rewrote SKILL.md with a
|
||||
capability map + the live credential status, replacing the stale "not yet provisioned" section.
|
||||
|
||||
On Mike's go (ACG domain `arizonacomputerguru` is not in production use — sanctioned test bed),
|
||||
added **gated write wrappers** for call-queue and time-frame edits and verified full
|
||||
create→update→delete lifecycles live. Then finished the wrapping across the rest of the platform:
|
||||
DID update/delete, per-user device CRUD, E911 address CRUD, contact CRUD, site create/update,
|
||||
auto-attendant create, SMS-number CRUD, blocked-number filters, MoH TTS create/delete, plus reads
|
||||
for addresses/smsnumbers/blocked-numbers/moh/dialrules/recording/transcriptions. Verified what was
|
||||
safely reversible on the test domain ([V]); marked the rest [P] (plumbed per spec, not
|
||||
lifecycle-verified — test domain lacks the feature or needs a special body) with the gotchas
|
||||
documented. Every write stays `--confirm`-gated; anything unwrapped remains reachable via `raw`.
|
||||
|
||||
Closed out coordination: confirmed all of Howard's coord messages from the prior day were handled
|
||||
(BUG-018/019/021 merged+deployed, Event Log Watch UI promoted to prod). The one open item was the
|
||||
ScreenConnect RESTful API Manager `GetSessions` ask; Mike granted Howard SC admin, so I handed it
|
||||
back to Howard via coord with the finding that the "Edit Extension Settings" dialog is config-only
|
||||
and the list-all methods live in the extension's code package (re-upload a modified build, or use
|
||||
the native session report API), not a setting.
|
||||
|
||||
## Key Decisions
|
||||
- **Vault path/field:** stored the OITVOIP key at `msp-tools/oitvoip.sops.yaml` `credentials.api_key`
|
||||
specifically because that's what `ns_client.load_credentials()` reads (apikey mode); no skill code
|
||||
change needed.
|
||||
- **Host:** kept the skill on `pbx.packetdial.com` (key works there). Documented that the key's docs
|
||||
reference `api.ucaasnetwork.com` (same NetSapiens platform, white-label) with a
|
||||
`PACKETDIAL_API_BASE_URL` override path if a future endpoint 403s on `pbx.`.
|
||||
- **Wrapper philosophy:** read-first; every write gated behind `--confirm`. Wrapped the practical MSP
|
||||
resource set; left multipart MoH upload, deep dialrule writes, and queue-agent login/logout PATCH
|
||||
on `raw` (awkward shapes, low value).
|
||||
- **Timeframe writes are body-discriminated** — same path, the server picks the op from the body — so
|
||||
one passthrough wrapper per verb (create/update/delete) covers all the spec's PUT/POST/DELETE
|
||||
variants correctly.
|
||||
- **Honest verification status in docs:** marked each wrapper [V] (lifecycle-verified on ACG) or [P]
|
||||
(plumbed per spec, unverified) rather than implying everything was tested, since several resources
|
||||
can't be exercised on the empty test domain.
|
||||
- **ScreenConnect:** handed the GetSessions work to Howard (now SC admin) rather than chasing it —
|
||||
it's his skill, not a blocker, and exposing the method needs an extension-package change, not a UI
|
||||
setting.
|
||||
|
||||
## Problems Encountered
|
||||
- **`/tmp` read failure (documented Windows gotcha):** `curl -o /tmp/x.json` then Windows-python read
|
||||
failed (Git-Bash vs tool path mismatch). Switched to a repo-relative path (`.claude/tmp/`). This is
|
||||
the exact rule promoted to CLAUDE.md CORE the prior session.
|
||||
- **OpenAPI JSON read raised cp1252 UnicodeDecodeError** on Windows python — fixed by opening with
|
||||
`encoding='utf-8'`.
|
||||
- **`raw` syntax:** `raw <path>` failed (argparse expects `raw <METHOD> <path>`); corrected probes to
|
||||
`raw GET <path>`.
|
||||
- **`cargo`-style env trap n/a here**, but a related one: the contact-delete test couldn't parse the
|
||||
new id — the contacts read keys the id as **`unique-id`**, not `contact_id`. Deleted the leftover
|
||||
test contact by its `unique-id`; the wrapper itself is correct (the `{contact_id}` path param takes
|
||||
the `unique-id` value).
|
||||
- **smsnumbers read = HTTP 400** on ACG (`"include domain and dest or number"`) — SMS isn't
|
||||
provisioned on that domain, not a wrapper bug; marked [P].
|
||||
- **number-filters quirk:** `block-numbers` returned 202 but the number didn't persist (empty list
|
||||
after), and `unblock-numbers` (DELETE+body) returned an answering-rule guard error on the empty
|
||||
domain. Wrappers match the spec; behavior inconclusive on the empty test domain → marked [P], no
|
||||
leftover (verified list empty).
|
||||
- **agent ghost rows:** the gururmm host has multiple "gururmm" RMM agent records (re-enroll churn);
|
||||
resolving `[0]` grabbed a stale June-11 ghost (commands stuck `pending`). Selected the live row by
|
||||
recent `last_seen`. (Carried over from the prior session's build-verification work.)
|
||||
|
||||
## Configuration Changes
|
||||
Created:
|
||||
- `msp-tools/oitvoip.sops.yaml` (VAULT repo) — OITVOIP reseller API key + docs.
|
||||
- `session-logs/2026-06/2026-06-22-mike-packetdial-buildout-oitvoip-vault.md` (this file).
|
||||
|
||||
Modified (claudetools, `.claude/skills/packetdial/`):
|
||||
- `scripts/ns_client.py` — added read methods (callqueues, timeframes, sites, contacts,
|
||||
autoattendants, billing, addresses, smsnumbers, blocked_numbers, moh, dialrules, recording,
|
||||
transcriptions) + write methods (callqueue CRUD + agents, timeframe CRUD, DID update/delete, device
|
||||
CRUD, address CRUD, contact CRUD, site create/update, autoattendant create, smsnumber CRUD,
|
||||
block/unblock numbers, moh TTS create/delete).
|
||||
- `scripts/ns.py` — subcommands + dispatch for all of the above (writes `--confirm`-gated).
|
||||
- `SKILL.md` — live credential status, expanded command lists, capability map (RTFM), additional
|
||||
resource-edits section with [V]/[P] legend.
|
||||
- `references/api.md` — history updated (key provisioned, RTFM, wrappers added).
|
||||
|
||||
## Credentials & Secrets
|
||||
- **OITVOIP / PacketDial NetSapiens reseller API key** — vaulted at
|
||||
`msp-tools/oitvoip.sops.yaml` → `credentials.api_key`. key-id `nsr_hSGUB5Wo`, scope Reseller
|
||||
`91912.service`, **read-write**. Retrieve with
|
||||
`bash .claude/scripts/vault.sh get-field msp-tools/oitvoip.sops.yaml credentials.api_key`.
|
||||
(Full `nsr_` secret intentionally NOT written here — it's in the vault. Plaintext source
|
||||
`C:\Users\guru\Downloads\OIT-API.txt` still on disk; Mike to delete.)
|
||||
- No other new secrets.
|
||||
|
||||
## Infrastructure & Servers
|
||||
- NetSapiens API: `https://pbx.packetdial.com/ns-api/v2` (v44.4.10). Token endpoint
|
||||
`…/v2/tokens`. OpenAPI `…/webroot/openapi/openapi.json`. White-label alt host
|
||||
`api.ucaasnetwork.com` (same platform). `voip.packetdial.com` = portal only (no API).
|
||||
- Reseller territory = 3 domains: `arizonacomputerguru` (ACG, **test bed — not in production use**),
|
||||
`0000.91912.service`, `russo.91912.service`.
|
||||
- ScreenConnect: `computerguru.screenconnect.com`; RESTful API Manager extension, API user
|
||||
`acg-sc-api`; Howard now has SC admin.
|
||||
|
||||
## Commands & Outputs
|
||||
- Vault store: `bash .claude/skills/vault/scripts/vault-helper.sh new msp-tools/oitvoip.sops.yaml --kind api-key --set api_key=… --set api_key_id=nsr_hSGUB5Wo …`
|
||||
- Verify key: `ns.py whoami` → `{"user-scope":"Reseller","reseller":"91912.service","readonly":"no",…}`
|
||||
- Read wrappers (verified): `ns.py callqueues|timeframes|sites|contacts|billing|addresses|moh|blocked-numbers <domain>`
|
||||
- Verified write lifecycles on `arizonacomputerguru`: callqueue 8999 create→update→delete; timeframe
|
||||
always create→convert→delete; contact create→delete (id=`unique-id`). All returned 202/clean; no
|
||||
leftovers.
|
||||
- Spec map: 239 paths / 354 ops (GET 139 · POST 87 · PUT 68 · DELETE 50 · PATCH 10).
|
||||
|
||||
## Pending / Incomplete Tasks
|
||||
- **ScreenConnect GetSessions/list-all** — Howard's, he now has SC admin (coord `58ed0b21`). Exposing
|
||||
it needs an extension-package change or the native session report API; not a blocker.
|
||||
- **[P] packetdial wrappers** not lifecycle-verified: DID update/delete, device CRUD, E911 address
|
||||
CRUD (needs `addresses/validate` → pidflo), site/AA writes, smsnumber CRUD (SMS not provisioned on
|
||||
ACG), block/unblock numbers (202 didn't persist on empty domain), moh create/delete. Verify on a
|
||||
real domain when a task needs them.
|
||||
- **`OIT-API.txt`** plaintext in Downloads — Mike to delete.
|
||||
- Optional: AgentDetail-embedded Event Log Watch panel (Howard noted as a follow-up after the dirty
|
||||
AgentDetail branch lands).
|
||||
|
||||
## Reference Information
|
||||
- Vault entry: `msp-tools/oitvoip.sops.yaml` (key-id `nsr_hSGUB5Wo`).
|
||||
- claudetools commits this session: `f8…`/earlier vault push `e705b66` (vault repo); packetdial
|
||||
build-out `d75c367b` (initial), `f42f9c24` (callqueue+timeframe edits), `1062a5ed` (finish wrapping).
|
||||
- coord sent: `7726d9f4` (packetdial unblocked), `58ed0b21` (Howard SC admin handoff).
|
||||
- Skill: `.claude/skills/packetdial/` (SKILL.md, references/api.md, scripts/ns.py, ns_client.py).
|
||||
- Local spec copy: `.claude/tmp/ns-openapi.json` (gitignored; refetch from the OpenAPI URL above).
|
||||
Reference in New Issue
Block a user