feat(bitdefender): doc-verify assignPolicy/push + add full-API build-out tracker

- assign_policy: add inheritFromAbove option; mark VERIFIED via official docs
  (policyId/targetIds/forcePolicyInheritance/inheritFromAbove; not applied to
  ENFORCED-policy targets).
- setPushEventSettings: documented serviceType (splunk/cef/jsonRPC), TLS 1.2+
  receiver requirement, subscribeToEventTypes event-flag map; webhook receiver
  pattern noted.
- api-reference.md: cite GravityZone Support Center as authoritative source.
- add references/BUILDOUT.md — master checklist to implement every API method
  module-by-module; seeded with current done/todo/dead state.
- memory: reference_gravityzone_support (+ index).

selftest 42/42.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 10:14:23 -07:00
parent 5dc5f5f82d
commit 4cf34f5221
6 changed files with 130 additions and 7 deletions

View File

@@ -2,6 +2,7 @@
## Reference
- [ACG resource map](reference_resource_map.md) — **READ THIS FIRST** when a task references a server/service/tenant/API. What we have access to, how to connect from this machine, per-machine exceptions, gotchas. Points at the detail files below.
- [GravityZone support center](reference_gravityzone_support.md) — Authoritative Bitdefender GravityZone product + Public API docs; use to confirm UNVERIFIED `bitdefender` skill methods/param shapes (push setPushEventSettings, assignPolicy, report/account writes, maintenancewindows/integrations names).
- [GURU-5070 Rust toolchain](reference_guru5070_rust_toolchain.md) — GURU-5070 now has cargo + MSVC + protoc; build/clippy/test guru-connect LOCALLY (set PROTOC to the winget path) instead of the build host. CI only clippy-checks the Linux server, not the Windows agent.
- [ACG Office Network Infrastructure](infra_office_network.md) — IPs/hosts/roles for pfSense/Jupiter/VMs/Docker. Check before assuming; .21 (Uranus) is storage.
- [Power Failure Runbook](../POWER_FAILURE_RUNBOOK.md) — Recovery order after a power event: Tailscale routes, libvirt/VMs, Seafile, NPM/DNS.

View File

@@ -0,0 +1,16 @@
---
name: reference_gravityzone_support
description: Authoritative GravityZone product + Public API documentation (Bitdefender Support Center)
metadata:
type: reference
---
GravityZone Support Center — authoritative docs for the Bitdefender product and
its Public JSON-RPC API (methods, params, modules):
https://www.bitdefender.com/business/support/en/77211-79436-welcome-to-gravityzone.html
Use it to confirm UNVERIFIED methods/param shapes before relying on them in the
`bitdefender` skill — e.g. `push.setPushEventSettings` nested shape,
`network.assignPolicy` options, report/account write methods, and the correct
`maintenancewindows`/`integrations` method names. The skill's own verified-vs-
unverified spec lives in `.claude/skills/bitdefender/references/api-reference.md`.

View File

@@ -0,0 +1,87 @@
# Bitdefender skill — full API build-out tracker
Goal: implement EVERY GravityZone Public API method the docs expose (and the
tenant license allows), one module at a time. Source of truth for method/param
shapes: the GravityZone Support Center
(https://www.bitdefender.com/business/support/en/77209-125277-public-api.html).
Legend: `[x]` wrapped + tested · `[ ]` todo · `[~]` partial/unverified ·
`[DEAD]` in key scope but license/feature OFF on this tenant.
Per-module workflow: fetch module doc -> list methods + params -> add to
`gz_client.py` + `gz.py` (gate state-changing behind `--confirm`) -> test
(reads live; writes gated-only, never executed on prod during build) -> update
`api-reference.md` + tick here.
---
## general / authentication
- [x] getApiKeyDetails
## licensing
- [x] getLicenseInfo
- [ ] (enumerate: getMonthlyUsage? / others)
## companies
- [x] getCompanyDetails
- [ ] getCompaniesList / getCompanyDetailsByUser
- [ ] createCompany / updateCompany / deleteCompany / suspend / activate (enumerate; gated)
## network
- [x] getNetworkInventoryItems · getEndpointsList · getManagedEndpointDetails
- [x] getScanTasksList · createScanTask · moveEndpoints
- [x] createCustomGroup · deleteCustomGroup · moveCustomGroup · deleteEndpoint
- [x] assignPolicy
- [ ] createReconfigureClientTask (gated)
- [ ] createUninstallTask (gated)
- [ ] setEndpointLabel
- [ ] (enumerate remaining: getEndpointsCounts, getManagedEndpointDetails opts, etc.)
## packages
- [x] getPackagesList · createPackage · getInstallationLinks · deletePackage
- [ ] getPackageDetails (param: packageId)
- [ ] (enumerate remaining)
## policies
- [x] getPoliciesList · getPolicyDetails (FULL config)
- [x] assignPolicy (lives in /network)
- [ ] (confirm no other policy methods exist)
## reports
- [x] getReportsList
- [ ] createReport (param: name, type, targetIds, ...) (gated-ish)
- [ ] getDownloadLinks · deleteReport (enumerate)
## quarantine
- [x] getQuarantineItemsList (computers)
- [ ] createRemoveQuarantineItemTask (gated)
- [ ] createRestoreQuarantineItemTask (gated)
- [ ] exchange quarantine variants (enumerate)
## incidents / EDR
- [x] getBlocklistItems · addToBlocklist · removeFromBlocklist
- [x] createIsolateEndpointTask · createRestoreEndpointFromIsolationTask
- [DEAD] getIncidentsList (Method not found on this tenant)
- [ ] custom rules / changeIncidentStatus / updateIncidentNote (enumerate; likely EDR-license gated)
## push (event service)
- [x] getPushEventSettings · getPushEventStats · setPushEventSettings
- [ ] sendTestPushEvent (enumerate)
## accounts (fully enumerated from docs)
- [x] getAccountsList
- [x] getNotificationsSettings
- [ ] getAccountDetails
- [ ] createAccount (gated)
- [ ] updateAccount (gated)
- [ ] deleteAccount (gated)
- [ ] configureNotificationsSettings (gated)
## integrations
- [ ] (enumerate; getPSAIntegrationList was a name-miss — find correct names)
## maintenance windows
- [DEAD] getMaintenanceWindows / *List → "not available" on this tenant
## patchmanagement / phasr
- [DEAD] license OFF (managePatchManagement=false; phasr feature off)

View File

@@ -1,5 +1,10 @@
# Bitdefender GravityZone Cloud Public API Reference
> **Authoritative product + API docs:** GravityZone Support Center —
> https://www.bitdefender.com/business/support/en/77211-79436-welcome-to-gravityzone.html
> (everything about the product and the Public API). Use it to confirm any
> UNVERIFIED method/param below before relying on it.
Verified spec for the methods used by this skill. Sourced from Bitdefender's
archived Public API documentation. Methods are flagged **VERIFIED** (signature
confirmed and exposed in the CLI) or **UNVERIFIED** (signature not confirmed —
@@ -110,7 +115,7 @@ In `getNetworkInventoryItems` results, `type == 1` denotes a company node.
|---|---|---|---|
| `getPoliciesList` | `page?, perPage?` | VERIFIED | List policies (id, name). |
| `getPolicyDetails` | `policyId` | VERIFIED | **Full** granular config (not shallow). |
| `assignPolicy` (`/network`) | `policyId, targetIds[], forcePolicyInheritance?` | VERIFIED LIVE (param shape) | Assign existing policy to endpoints/groups. Param shape confirmed via validation probe 2026-06-21. CLI `assign-policy`, gated. STATE-CHANGING. |
| `assignPolicy` (`/network`) | `policyId, targetIds[], forcePolicyInheritance?, inheritFromAbove?` | VERIFIED (official docs + probe) | Assign existing policy to endpoints/containers. NOT applied to targets with an ENFORCED policy. CLI `assign-policy`, gated. STATE-CHANGING. Docs: 77212-924802-assignpolicy.html |
## reports (`/reports`) — VERIFIED LIVE
@@ -139,7 +144,12 @@ In `getNetworkInventoryItems` results, `type == 1` denotes a company node.
|---|---|---|---|
| `getPushEventSettings` | `{}` | VERIFIED LIVE | Current settings. CLI `push-settings`. |
| `getPushEventStats` | `{}` | VERIFIED LIVE | Delivery stats. CLI `push-stats`. |
| `setPushEventSettings` | `status (req), serviceType, serviceSettings{url,requireValidSslCertificate,authorization}, subscribeToEventTypes?` | `status` VERIFIED (probe); nested shape UNVERIFIED | Configure the service. CLI `push-set`, gated. STATE-CHANGING. Needs a receiver URL.
| `setPushEventSettings` | `status (req), serviceType, serviceSettings{url,requireValidSslCertificate,authorization}, subscribeToEventTypes{<event flags>}` | VERIFIED (official docs + probe) | Configure the service. `serviceType``splunk`/`cef`/`jsonRPC`. Receiver MUST support TLS 1.2+. `subscribeToEventTypes` is a map of event flags (av, fw, aph, registration, task-status, modules, network-sandboxing, antiexploit, dp, uc, …) set true to subscribe. Returns bool. CLI `push-set`, gated. STATE-CHANGING. Needs a receiver URL. Docs: 77209-135319-setpusheventsettings.html
> Receiver pattern for the webhook (Phase-2): stand up an HTTPS endpoint (TLS
> 1.2+, valid cert) that accepts GravityZone's event POSTs — a coord-API route
> or an RMM ingest route — then `push-set --status 1 --url <that-endpoint>
> --confirm`. `serviceType jsonRPC` posts JSON-RPC event batches.
## quarantine (`/quarantine`)

View File

@@ -276,7 +276,9 @@ def cmd_assign_policy(client, args):
if not _gated(desc, args.confirm):
return 3
result = client.assign_policy(
args.policy, args.targets, force_inheritance=args.force_inheritance
args.policy, args.targets,
force_inheritance=args.force_inheritance,
inherit_from_above=args.inherit_from_above,
)
_emit({"assignedPolicy": args.policy, "targets": args.targets,
"result": result}, args.json, _print_kv)
@@ -668,6 +670,8 @@ def build_parser() -> argparse.ArgumentParser:
help="One or more endpoint/group ids.")
sp.add_argument("--force-inheritance", action="store_true",
help="Force policy inheritance to sub-items.")
sp.add_argument("--inherit-from-above", action="store_true",
help="Inherit the policy from the parent group.")
sp.add_argument("--confirm", action="store_true")
sp = sub.add_parser("push-set",

View File

@@ -633,17 +633,22 @@ class GravityZoneClient:
policy_id: str,
target_ids: list[str],
force_inheritance: bool = False,
inherit_from_above: bool = False,
) -> Any:
"""Assign an existing policy to endpoints/groups (network.assignPolicy).
Param shape VERIFIED LIVE via validation probe (2026-06-21): requires
`policyId` and `targetIds` (a list of endpoint/group ids).
`forcePolicyInheritance` is optional. STATE-CHANGING — gate at the call
site behind --confirm.
Param shape VERIFIED against the official docs + live validation probe
(2026-06-21): `policyId` and `targetIds` (endpoint/container ids) are
required; `forcePolicyInheritance` and `inheritFromAbove` are optional
bools. NOTE: the policy is NOT applied to targets that already carry an
ENFORCED policy. STATE-CHANGING — gate at the call site behind --confirm.
Docs: bitdefender.com/business/support/en/77212-924802-assignpolicy.html
"""
params: dict = {"policyId": policy_id, "targetIds": target_ids}
if force_inheritance:
params["forcePolicyInheritance"] = True
if inherit_from_above:
params["inheritFromAbove"] = True
return self._jsonrpc_request("network", "assignPolicy", params)
def list_scan_tasks(