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>
This commit is contained in:
2026-06-25 13:28:01 -07:00
parent 5b3dd84fb9
commit 1852f755ad
5 changed files with 43 additions and 40 deletions

View File

@@ -61,7 +61,7 @@ check("companies table", ["companies"], want_rc=0, out_has="Companies:")
check("companies json", ["companies", "--json"], want_rc=0, out_json_ok=True)
check("endpoints (real co)", ["endpoints", "--company", ACG], want_rc=0, out_has="Endpoints:")
check("endpoints json", ["endpoints", "--company", ACG, "--json"], want_rc=0, out_json_ok=True)
check("endpoints bogus parent -> err", ["endpoints", "--company", "bogus"], want_rc=1, err_has="[ERROR]")
check("endpoints bogus parent -> rc2 (client-side id validation)", ["endpoints", "--company", "bogus"], want_rc=2, err_has="[ERROR]")
check("policies", ["policies"], want_rc=0, out_has="Policies:")
check("packages", ["packages"], want_rc=0, out_has="Packages:")
check("quarantine (real co)", ["quarantine", "--company", ACG], want_rc=0, out_has="Quarantine items:")
@@ -84,26 +84,27 @@ check("push-stats (unconfigured -> rc0)", ["push-stats"], want_rc=0, out_has="no
# policy detail must NOT carry the old false 'shallow' warning anymore
check("policy no shallow warning", ["policy", "5c42940b6e16d61a0c8b4568"], want_rc=0, err_has=None)
# --- error handling: a MALFORMED id (not valid hex/ObjectId) makes the API
# error, which must exit non-zero (1). Note: a well-formed but non-existent
# hex id is ACCEPTED by GravityZone and returns a stub (rc 0) -- that is the
# API's behavior, not a skill bug, so we test with a malformed value here. ---
check("endpoint bad id -> rc1", ["endpoint", "bogus"], want_rc=1, err_has="[ERROR]")
check("policy bad id -> rc1", ["policy", "bogus"], want_rc=1, err_has="[ERROR]")
# --- error handling: a MALFORMED id (not 24-char hex ObjectId) is now caught
# CLIENT-SIDE by _require_oid and exits rc2 BEFORE any API call (so it neither
# hits the live tenant nor pollutes errorlog.md). A well-formed but non-existent
# hex id is ACCEPTED by GravityZone and returns a stub (rc 0) -- the API's
# behavior, not a skill bug. ---
check("endpoint bad id -> rc2 (client-side)", ["endpoint", "bogus"], want_rc=2, err_has="not a valid")
check("policy bad id -> rc2 (client-side)", ["policy", "bogus"], want_rc=2, err_has="not a valid")
# --- argparse: missing required arg -> rc2 ---
check("quarantine missing --company -> rc2", ["quarantine"], want_rc=2)
check("endpoint missing positional -> rc2", ["endpoint"], want_rc=2)
# --- gating: destructive without --confirm -> rc3, no API call ---
check("isolate no confirm -> rc3", ["isolate", "--endpoints", "x"], want_rc=3, out_has="Would")
check("isolate no confirm -> rc3", ["isolate", "--endpoints", "x"], want_rc=3, err_has="Would")
check("unisolate no confirm -> rc3", ["unisolate", "--endpoints", "x"], want_rc=3)
check("blocklist-add no confirm -> rc3", ["blocklist-add", "--company", ACG, "--hashes", "abc"], want_rc=3)
check("blocklist-remove no confirm -> rc3", ["blocklist-remove", "--id", "x"], want_rc=3)
check("delete-endpoint no confirm -> rc3", ["delete-endpoint", "x"], want_rc=3)
check("delete-package no confirm -> rc3", ["delete-package", "--id", "x"], want_rc=3)
check("delete-group no confirm -> rc3", ["delete-group", "--group", "x"], want_rc=3)
check("assign-policy no confirm -> rc3", ["assign-policy", "--policy", "p", "--targets", "x"], want_rc=3, out_has="Would")
check("assign-policy no confirm -> rc3", ["assign-policy", "--policy", "p", "--targets", "x"], want_rc=3, err_has="Would")
check("push-set no confirm -> rc3", ["push-set", "--status", "1", "--url", "https://x/y"], want_rc=3)
check("push-set enable no url -> rc2", ["push-set", "--status", "1", "--confirm"], want_rc=2)
check("raw assignPolicy no confirm -> rc3", ["raw", "--module", "network", "--method", "assignPolicy", "--params", "{}"], want_rc=3)
@@ -136,7 +137,7 @@ check("raw setEndpointLabel no confirm -> rc3", ["raw", "--module", "network", "
# --- companies module ---
check("company (own, no id)", ["company"], want_rc=0)
check("company-create no confirm -> rc3", ["company-create", "--type", "1", "--name", "Test Co"], want_rc=3, out_has="Would")
check("company-create no confirm -> rc3", ["company-create", "--type", "1", "--name", "Test Co"], want_rc=3, err_has="Would")
check("company-suspend no confirm -> rc3", ["company-suspend", "--id", "x"], want_rc=3)
check("company-activate no confirm -> rc3", ["company-activate", "--id", "x"], want_rc=3)
check("company-delete no confirm -> rc3", ["company-delete", "--id", "x"], want_rc=3)
@@ -144,7 +145,7 @@ check("raw createCompany no confirm -> rc3", ["raw", "--module", "companies", "-
# --- accounts module ---
check("account (own, no id)", ["account"], want_rc=0)
check("account-create no confirm -> rc3", ["account-create", "--email", "t@x.io"], want_rc=3, out_has="Would")
check("account-create no confirm -> rc3", ["account-create", "--email", "t@x.io"], want_rc=3, err_has="Would")
check("account-update no confirm -> rc3", ["account-update", "--id", "a", "--set-json", "{\"role\":5}"], want_rc=3)
check("account-update bad json -> rc2", ["account-update", "--id", "a", "--set-json", "{bad", "--confirm"], want_rc=2)
check("account-delete no confirm -> rc3", ["account-delete", "--id", "a"], want_rc=3)