Commit Graph

230 Commits

Author SHA1 Message Date
941de499c2 sync: auto-sync from HOWARD-HOME at 2026-07-14 19:13:30
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-14 19:13:30
2026-07-14 19:14:01 -07:00
e78152a706 sync: auto-sync from Mikes-MacBook-Air.local at 2026-07-10 08:30:31
Author: Mike Swanson
Machine: Mikes-MacBook-Air.local
Timestamp: 2026-07-10 08:30:31
2026-07-10 08:30:39 -07:00
033019df18 sync: auto-sync from GURU-5070 at 2026-07-10 06:59:57
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-10 06:59:57
2026-07-10 07:00:29 -07:00
6942827391 sync: auto-sync from Mikes-MacBook-Air.local at 2026-07-09 14:52:07
Author: Mike Swanson
Machine: Mikes-MacBook-Air.local
Timestamp: 2026-07-09 14:52:07
2026-07-09 14:52:17 -07:00
0a438929d0 ask-forum: harden per high-effort review + document capability limits
Fixes from the code-review workflow (7 findings): page the poll cursor past the
100-msg window (no false timeout behind bot/overflow messages); honor 429
retry_after and bail fast on permanent Discord errors (10003/50001/...) instead
of burning the timeout; status-check overflow follow-up chunks (warn, don't
silently truncate); clamp --read limit safely (guard >64-bit overflow); add
--wait --after for precise resumption; DRY the newline-trim; set LC_ALL=C.UTF-8
for codepoint-safe slicing. SKILL.md gains the tested bot capability/limit map
(can: post/read/edit-own/react; cannot without a grant: delete/archive/unlock/pin)
and a robustness section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 20:37:46 -07:00
a2a277ab67 sync: auto-sync from HOWARD-HOME at 2026-07-07 20:31:16
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 20:31:16
2026-07-07 20:31:47 -07:00
9340cdec17 ask-forum: promote to a full skill + wire into skill-first routing
Add .claude/skills/ask-forum/SKILL.md (usage contract, correlation model,
forum-only scope, access/permissions) and route to it from CLAUDE.md
(skill-first covered domains) + SKILL_ROUTING.md, so sessions invoke the
skill instead of hand-rolling the Discord API — the footgun that produced a
broken background wait. Capture that footgun as memory
feedback_background_task_no_ampersand (run_in_background, never a shell &).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 20:12:18 -07:00
a507678254 sync: auto-sync from HOWARD-HOME at 2026-07-07 11:45:40
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 11:45:40
2026-07-07 11:46:46 -07:00
27595d6475 sync: auto-sync from HOWARD-HOME at 2026-07-07 11:01:18
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 11:01:18
2026-07-07 11:01:49 -07:00
ead30520e5 sync: auto-sync from HOWARD-HOME at 2026-07-07 07:23:12
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-07 07:23:12
2026-07-07 07:23:39 -07:00
12c3d83f75 sync: auto-sync from HOWARD-HOME at 2026-07-06 16:41:20
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-06 16:41:20
2026-07-06 16:41:51 -07:00
7dc519827c sync: auto-sync from HOWARD-HOME at 2026-07-06 16:10:24
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-06 16:10:24
2026-07-06 16:10:52 -07:00
d5f7eadf82 sync: auto-sync from HOWARD-HOME at 2026-07-06 08:29:31
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-06 08:29:31
2026-07-06 08:30:01 -07:00
da6567ffe0 owncloud: extend skill from read-only audit to full occ management
Layer gated admin writes onto the read-only GPS-audit skill, driven through
occ over SSH (same paramiko/vault/filecache plumbing):

- user lifecycle (add/delete/enable/disable/reset-password/modify), quota
  get/set/reset, groups (create/delete/members), read-only share listing
  (from oc_share; occ has no share create/list), apps, system config,
  maintenance mode, files scan, ownership transfer, trashbin/versions cleanup.
- All writes gated behind --confirm (refuse -> rc 3); hard-fail guards (rc 2)
  for invalid uid, missing password, and all-users cleanup with no target.
- --all-users trashbin/versions purge now ALSO requires --force-all-users in
  addition to --confirm, so a single stray --confirm cannot trigger an
  irreversible fleet-wide purge.

Built against the verified live occ surface (occ list / occ help), not guessed
flags. Fixes from code-review + security-review: Python-side share filtering
(no MySQL SQL-injection via '' -doubling), occ reads no longer mask a failed
read as healthy (maintenance/quota/config), guarded json.loads, clean --json
output, and '--' end-of-options guards so dash-leading uids can't be parsed as
occ flags. dry_test.sh added as a non-destructive regression harness (43 checks).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 20:52:25 -07:00
a8e76ba215 sync: auto-sync from HOWARD-HOME at 2026-07-05 20:23:39
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-05 20:23:39
2026-07-05 20:24:08 -07:00
976bfe7957 sync: auto-sync from HOWARD-HOME at 2026-07-05 19:59:52
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-05 19:59:52
2026-07-05 20:00:20 -07:00
fa4867580f sync: auto-sync from HOWARD-HOME at 2026-07-05 15:29:59
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-07-05 15:29:59
2026-07-05 15:30:28 -07:00
41c12a934f agy: rewire skill from dead gemini npm CLI to Antigravity 'agy' binary
The old Google gemini CLI stopped working on this account (throwIneligibleOrProjectIdError -
needs a GOOGLE_CLOUD_PROJECT the personal account can't supply). Replace it with the
Antigravity CLI (agy, native Go binary, own auth, no project ID).

- New scripts/ask-agy.sh: plain-text output (no JSON), -p prompt-last, --model friendly
  names (Gemini 3.1 Pro (High) default for verify/review*/vision/search), --add-dir for
  file/vision reads, --dangerously-skip-permissions to avoid print-mode approval hangs.
  All modes smoke-tested (text/verify/review/search).
- scripts/ask-gemini.sh: deprecated shim -> exec ask-agy.sh (back-compat).
- SKILL.md: rewired header/flags/models/auth/availability/reference to agy.
- ask-grok.sh: xsearch fallback now execs ask-agy.sh (was the dead gemini).
- identity.json (local, gitignored): agy block added, gemini marked retired.

Authoritative flags sourced from 'agy --help' (web docs are JS SPAs, unreadable by
fetch tools; grok fetch/search timed out).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 13:19:21 -07:00
8152476ee4 remediation-tool: document the 365 app suite + build consent-audit
Root-caused the recurring '365 suite isn't documented' pain: the apps are fine (tiered by
privilege) but per-tenant consent is NOT uniform and there was no way to see a tenant's
actual grant state. VWP had the Tenant Admin app but no SharePoint app-only role -> silent
401s until this session.

- references/app-suite.md: authoritative, live-verified map of every app, App ID, and
  actually-granted permission per tier; the consent-drift problem + both fix methods
  (adminconsent URL, direct appRoleAssignment grant).
- scripts/consent-audit.sh: audits a tenant (or --all) vs the baseline, grades
  GREEN/AMBER/RED, prints the exact fix per gap. Extends the assign-exchange-role --verify
  pattern to Graph scopes + SharePoint role + EXO role. Verified: BirthBio GREEN, VWP/Cascades
  AMBER (caught real drift - both missing grants).
- SKILL.md: run consent-audit FIRST on any tenant task. Memory + errorlog correction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-02 15:15:08 -07:00
b07613c127 sync: auto-sync from GURU-5070 at 2026-07-01 20:07:01
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-01 20:07:01
2026-07-01 20:07:42 -07:00
2937b00ebf sync: auto-sync from GURU-5070 at 2026-07-01 15:49:56
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-01 15:49:56
2026-07-01 15:50:54 -07:00
c3aeef60fb sync: auto-sync from GURU-5070 at 2026-07-01 15:06:42
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-01 15:06:42
2026-07-01 15:07:39 -07:00
6f7f939a62 sync: auto-sync from GURU-5070 at 2026-07-01 09:32:17
Author: Mike Swanson
Machine: GURU-5070
Timestamp: 2026-07-01 09:32:17
2026-07-01 09:33:09 -07:00
31f2bdb84f sync: auto-sync from HOWARD-HOME at 2026-06-29 16:55:22
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-29 16:55:22
2026-06-29 16:55:55 -07:00
10a90bb213 sync: auto-sync from HOWARD-HOME at 2026-06-26 08:41:22
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-26 08:41:22
2026-06-26 08:42:30 -07:00
04b0d12150 sync: auto-sync from HOWARD-HOME at 2026-06-25 21:48:38
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-25 21:48:38
2026-06-25 21:49:05 -07:00
93bd5379e3 sync: auto-sync from HOWARD-HOME at 2026-06-25 15:21:30
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-25 15:21:30
2026-06-25 15:22:06 -07:00
79bda6fab9 datto-edr: apply code-review fixes (gating + footgun hardening)
- deploy-cmd: require explicit --regkey or --group; never auto-pick an
  arbitrary cross-client registration key (would enroll into wrong org).
- raw: block POST to any */scan endpoint with no non-empty `where`
  (same tenant-wide footgun the scan command guards against).
- main(): catch-all for unexpected exceptions -> [ERROR] + errorlog,
  plus clean KeyboardInterrupt (130).
- isolate: forgiving extension-name match (exact, then substring),
  excludes the paired "Restore" ext; errors on ambiguous match.
- detections: --site -> --target-group; Alert.targetGroupId is a
  scan-target id, not a Location id (distinct from `agents --site`).
- status: relabel "Target groups (sites)" -> "Scan target groups".
- SKILL.md + docstrings updated to match.

Verified: py_compile clean, selftest green (216 agents), guards fire
on no-key/empty-where/no-agent, deploy-cmd --group picks the group's key.
2026-06-25 15:14:18 -07:00
befd2650c8 fix(bitdefender): fifth-pass - companies lists full fleet, drop unused import
Convergence-pass LOW/NIT cleanup:
- cmd_companies uses list_all_companies() so a >100-company tenant isn't truncated
  in the listing (was page-1 only); matches sweep/inventory.
- removed unused 'field' import from dataclasses.
Deliberately NOT changed: id validation on delete-package/report-delete/blocklist-
remove/quarantine-remove/restore - those ids are not pinned 24-hex format, so
validating could reject valid input; they are --confirm-gated and bad ids match
the expected-error markers (no mislog). 81/81 selftest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 14:05:32 -07:00
3d6cb467bf fix(bitdefender): fourth-pass - urllib reset safety, Retry-After clamp, sweep/install-links id validation
From a third review pass (converging - all MEDIUM/LOW):
- urllib fallback: a post-send reset (RemoteDisconnected/ConnectionReset, which
  urllib wraps in URLError) was misclassified as always-safe 'connect' and could
  retry a non-idempotent write after a server commit. Now only ConnectionRefused/
  DNS (socket.gaierror) -> 'connect'; everything else -> 'timeout' (write-gated).
- _retry_delay clamps a negative numeric Retry-After to 0 (was -> time.sleep(-1) ValueError).
- cmd_sweep + cmd_install_links now validate --company; cmd_company_create validates
  --parent (finished _require_oid consistency - these mislogged as errorlog noise).
- cmd_push_test parses --extra-json before gating (validate->gate order, matches siblings).
- selftest: +sweep/install-links bad-company assertions. 81/81. Units: clamp + reset classification.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:59:19 -07:00
1e80fb24db datto-edr: fix scan to verified Agents/scan endpoint + harden
- Scan now uses POST Agents/scan with AND-wrapped where {and:[{id:[...]}]}
  (the Infocyte targets/{id}/scan routes are dead/404; bare {id:{inq}} returns
  HTTP 412 ambiguous-column). Verified live: single-agent scan -> 'Scanning 1 host'.
- scan/isolate REQUIRE explicit --agent ids; empty list refused (tenant-wide footgun).
- isolate rides Agents/scan with the Host Isolation extension in options.extensions;
  resolves --extension-name -> id via /Extensions.
- New subcommands: tasks, task, cancel, create-group, mint-key.
- deploy-cmd emits full -URL (not -InstanceName; cname 'azcomp4587' trips the
  install script's .com regex and leaves --url empty).
- Docs (SKILL.md + api-reference.md) rewritten to the verified endpoints + footguns.

Lifecycle verified end-to-end on RMM-TEST-MACHINE (create-group/mint-key/install/
register/scan/cancel).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:55:22 -07:00
778e12d83e fix(bitdefender): third-pass - companies pagination, connect-retry, Retry-After ceiling, ctx mgr
Remaining LOW/NIT items from the second review pass:
- list_all_companies() paginates the company list; sweep-all + refresh_inventory
  no longer truncate a >100-company tenant.
- Pre-send connection failures (httpx ConnectError/ConnectTimeout; urllib URLError
  not wrapping a timeout) are now retried as 'connect' - always safe (no side
  effect) even for non-idempotent writes; ambiguous read-timeouts stay idempotent-gated.
- Explicit Retry-After honored up to RETRY_AFTER_MAX_SECONDS (120s) instead of the
  30s exponential cap, so a server-mandated cooldown isn't cut short.
- GravityZoneClient is now a context manager (__enter__/__exit__ -> close()).
- incident-status/note reject an empty --set-json (rc2), matching account-update/notif.
- selftest: +connect/Retry-After/ctx-mgr unit coverage, incident empty-json assertion. 79/79.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:52:33 -07:00
a96a15a1d2 sync: auto-sync from HOWARD-HOME at 2026-06-25 13:43:47
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-25 13:43:47
2026-06-25 13:44:18 -07:00
1852f755ad fix(bitdefender): doc LOWs + sweep pagination + selftest alignment
Batched the audit doc/LOW findings plus the two pagination LOWs:
- Pagination (gz_client): security_sweep and refresh_inventory stopped on a
  'total' field some responses omit, truncating after page 1. Now page until a
  short page (< per_page) - the reliable last-page signal.
- isolate/restore docstrings (gz_client): removed the stale 'v1.2 takes an ARRAY
  endpointIds' lines that contradicted the verified single-endpointId code.
- Cache 'no PII' wording corrected (gz_client header + SKILL.md): cache holds infra
  identifiers (hostnames/FQDNs); no secrets. Dead _require_company_for_sweep removed.
- Doc drift fixed: delete-package is '--id <packageId>' not '--package <name>'
  (SKILL.md + api-reference.md, verified live); module docstring + sweep --company
  help corrected (sweep with no --company fans out to ALL companies).
- selftest aligned to the improved behavior: malformed ids now exit rc2 client-side
  (H3) instead of rc1; gate-refusal 'Would' messages now assert on stderr (they
  moved off stdout so --json isn't polluted). 75/75 pass; live sweep verified.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:28:38 -07:00
5b3dd84fb9 synology: fix SSH backend syno* CLI resolution (full pre-test verification)
Found during a full command-surface recheck: every privileged SSH recipe
(shares/users/groups/acl) was broken — sudo secure_path drops /usr/syno/{bin,sbin}
so synoshare/synouser/synogroup/synoacltool were "command not found" (non-sudo
plain recipes worked because the admin login PATH has them).

- Inject SYNO_PATH into priv()/plain(); run priv via `sh -c` so operators work.
- synouser/synogroup use `--enum local` (not the invalid `--list`).
- acl quotes the share path (handles spaces, e.g. "Sandra Fish").
- services repointed to Web API (no synoservice on DSM 7.2; synosystemctl has no list-all).

Verified live: all Web API reads, all SSH reads (acl returns real Windows ACEs),
write path (share create/delete), and every destructive command correctly gated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 13:28:38 -07:00
4d7508382d fix(bitdefender): atomic cache writes + advisory lock on write-through (M3)
Audit fix M3: _write_cache did a non-atomic CACHE_FILE.write_text and the
write-through helpers did unlocked read-modify-write, so a crash mid-write could
truncate inventory.json and two concurrent gz.py runs could lose an update.
- _write_cache now writes a temp file (fsync) then os.replace() - atomic on the
  same filesystem; a reader/crash can never see a partial file, and a failed
  write leaves the prior cache intact and no .tmp residue.
- Added a best-effort cross-platform advisory lock (_cache_lock) around the
  read-modify-write in _cache_add_group/_cache_add_package; steals a stale lock,
  proceeds unlocked on timeout (a lost update is tolerable, a hang is not).
- Dropped the dead cache.setdefault('companies', ...) line in _cache_add_group.
- Verified: compile clean; unit tests for round-trip, lock acquire/release/steal,
  write-through, temp cleanup on failure, and prior-cache survival.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:54:50 -07:00
d4fd71baab sync: auto-sync from HOWARD-HOME at 2026-06-25 12:53:21
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-25 12:53:21
2026-06-25 12:54:04 -07:00
51751e6473 fix(bitdefender): retry 429/5xx/timeout with backoff + reuse one httpx client
Audit fix H2 (+ M2): the live GravityZone tenant is rate-limited and sweeps fan
out one getManagedEndpointDetails per endpoint across every company, which hit a
real HTTP 429 (errorlog 2026-06-21). _post had zero retry and opened a fresh
httpx.Client (new TLS handshake) per request.
- _post now retries 429/500/502/503/504/timeout up to RETRY_MAX_ATTEMPTS with
  bounded exponential backoff + jitter, honoring Retry-After (numeric or HTTP-date).
  Retry notices go to stderr (don't pollute --json). Terminal errors still raise.
- M2: a single httpx.Client is created lazily and reused (connection pooling),
  closed via client.close() in main()'s finally. Makes the docstring's pooling
  claim true and cuts handshake overhead + 429 pressure during sweeps.
- Verified: compile clean; offline unit tests (persistent 429 -> 4 attempts then
  raise, flaky 503 -> recovers, Retry-After honored); live status read OK.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:51:08 -07:00
d8f0974e0f fix(bitdefender): gate move/scan/create-package/make-group + validate object IDs
Audit cluster C1/C2/H1/H3/M1 on the live GravityZone tenant:
- C1/H1/M1: move, scan, create-package, make-group called the live API with
  no --confirm; added _gated() + a --confirm flag to each (move can change an
  endpoint's inherited policy posture).
- C2: extend raw's destructive-method denylist with moveEndpoints/moveCustomGroup/
  createScanTask/createPackage/createCustomGroup so 'raw' can't bypass the gates.
- H3: add _require_oid() 24-char-hex validation to endpoint/policy/endpoints +
  the gated handlers, so malformed ids no longer hit the tenant or get mislogged
  as functional errors (source of the 2026-06-21 errorlog noise).
- Gate refusals now print to stderr (don't pollute --json). SKILL.md gating list
  updated. Verified: compile clean; gates exit 3, bad ids exit 2, raw denylist hits.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:47:45 -07:00
e9ece35c2a sync: auto-sync from HOWARD-HOME at 2026-06-25 12:45:08
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-25 12:45:08
2026-06-25 12:45:43 -07:00
bd1e84d32c skills: add datto-edr (Datto EDR / Infocyte HUNT) + syncro-rmm memory
New /datto-edr skill — standalone CLI for the Datto EDR REST API (azcomp4587,
rebranded Infocyte HUNT, raw-token LoopBack). Live-verified reads across the whole
MSP fleet: orgs/sites/agents/detections/sweep + deploy-cmd. Scan/isolate gated
behind --confirm (shape-verified, not run against prod). Token vaulted at
msp-tools/datto-edr.sops.yaml.

Also: reference_syncro_rmm_api_gui_only memory (Syncro RMM policy mgmt is
GUI-only) and the guru-rmm submodule pointer bump (Feature 6 EDR research).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:39:58 -07:00
b9d4cfde98 sync: auto-sync from HOWARD-HOME at 2026-06-25 12:30:38
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-25 12:30:38
2026-06-25 12:31:14 -07:00
974be13f4c synology: code-review hardening + trim over-budget description
Addresses 5 verified findings from /code-review high:
- SynoError carries DSM code + handled flag; call() no longer logs eagerly.
  Top-level handler logs only genuine unhandled failures, so the handled
  FileStation denial + VPN-down connect errors stop polluting errorlog.md
  (was a CLAUDE.md rule violation: don't log handled conditions).
- FileStation-denial detection is numeric (code in 400/407), not substring.
- SSH hint now also fires on the generic `call` path, not just `ls`.
- `services` falls back get->list on 103 for older DSM builds (multi-device).
- BrokenPipe flush moved inside try so small piped output can't leak a traceback.
- Trim SKILL description 755->515 chars (was the longest of 32 skills; self-check
  registry-budget WARN).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 12:23:43 -07:00
21ef1f2570 synology: fix --confirm arg position + verify write path live
- Fix argparse: --confirm/--vault were only accepted BEFORE the subcommand, so
  every documented gated-write (e.g. `call X set k=v --confirm`) failed. Moved to
  a shared parent parser (SUPPRESS defaults) -> both flags work in either position.
- Verified the CSRF write path live on cascadesDS: Share create -> verify ->
  delete -> verify gone. Both mutating calls succeeded; device left pristine.
- SKILL.md: write/setter path marked VERIFIED; confirmed share-create signature.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:56:32 -07:00
fc36f98450 synology: full read-surface sweep + FileStation ls graceful fallback
Exercised every Web API + SSH read command live against cascadesDS.
- All reads OK; `ls <folder>` (FileStation list) is 407-denied for the admin
  account on this box (confirmed on-box as SYSTEM_ADMIN) -> now catches the
  400/407 and prints an SSH file-browse hint. `ls` share-roots still works.
- SSH backend (info/df/run + privileged synowebapi) verified.
- Documented MSYS path-mangling of bare `ls /path` arg on Windows.
- SKILL.md: per-command results; flagged write/setter path as not-yet-live.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:19:04 -07:00
7173f4dc12 synology: live-verify against cascadesDS, fix services method + pipe handling
First live exercise of the skill against the Cascades DS718+ (DSM 7.2.1, VPN up).
- Fix `services`: SYNO.Core.Service.list 103s on DSM 7.2.1 -> method is `get`.
- Fix `apis | head` BrokenPipeError traceback -> caught, clean exit.
- SKILL.md status PLUMBED -> VERIFIED 2026-06-25 with live device facts.
- wiki/cascades-tucson: add NAS specs, resolve model/RAM/DSM TODO.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:08:28 -07:00
2a1a275511 sync: auto-sync from HOWARD-HOME at 2026-06-24 17:37:00
Author: Howard Enos
Machine: HOWARD-HOME
Timestamp: 2026-06-24 17:37:00
2026-06-24 17:37:35 -07:00
3de8b7fde3 docs(screenconnect skill): clarify end goal — GuruRMM addon, BYO alternative to GuruConnect
Replace the thin "Future: GuruRMM integration" stub with a "Why this skill exists"
section: ScreenConnect surfaces as a per-partner Integrations Center / addons-page
entry, positioned as the bring-your-own alternative to GuruConnect (a partner already
paying for ScreenConnect uses their licensed instance as the remote-access backend).
Points at the mapped plan: SPEC-024, RMM_THOUGHTS Feature 7 + Refinement 7a, the
Integrations Center roadmap item.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 20:51:38 -07:00
850e685d8d feat: yealink-ymcs skill — YMCS v2 device-management API, pairs with packetdial
New skill to manage ACG's Yealink phone fleets via Yealink Management Cloud Service v2
(us-api.ymcs.yealink.com). RTFM'd the API (token auth via POST /v2/token Basic+bearer, NOT the
legacy RPS HMAC; legacy-TLS renegotiation required) + endpoint map from the dszp/n8n-nodes-
yealinkymcs community node. Live-verified: token auth, sites (one ACG AccessKey sees ALL client
sites — VWP/GuruHQ/Ace Pick Up Parks as children of the ACG parent), devices, accounts,
rps-servers (RPS = "WL - ACG" ftp://p.packetdials.net). Gated writes (--confirm): add-devices-by-mac,
add-sipaccount (push a NetSapiens SIP cred onto a phone = the PBX glue), reboot, reset, rps add/del;
+ raw passthrough (auto-recovers the MSYS /v2 path-mangling). Creds vaulted at
services/yealink-ymcs.sops.yaml. Pairs with packetdial onboard-domain for new-client phone
provisioning; VWP is the live pilot. Honest [V]/[P] verification status in SKILL.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:59:52 -07:00
d1d1302d55 packetdial: add onboard-domain wrapper (GUI Add-a-Domain -> 3-call API flow)
onboard-domain runs POST /domains -> addresses/validate (gen E911 pidflo) -> addresses/create
from one JSON body (domain fields + optional `emergency` block), gated --confirm. Reverse-
engineered from the OITVOIP wizard screenshots; live-created the real client domain
vwp.91912.service (Valley Wide Plastering) + E911 address, and proved the wrapper with a
throwaway create->delete (no leftovers, vwp intact). Documented GUI->API mapping + the two
manual gaps (voicemail user-defaults, email-send-from-address pending the packetdial.com mailbox)
+ the domain-type "no"-on-create quirk.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 09:34:48 -07:00