Documentation > API Reference > Phase 8 Foundation Features

Phase 8 Foundation Features API

REST endpoints introduced in Phase 8 (v2.0.0.0): access groups, registration keys, scheduled update profiles, package compliance profiles, broadcast messaging, report branding, custom report templates, and dynamic secret leases.

Overview

All endpoints below require JWT bearer authentication and are mounted under /api. Endpoints prefixed /api/v1/reports/... are served by the Pro+ reporting_engine module; OSS deployments expose only the storage / template-CRUD subset.

8.1 Access Groups & Registration Keys

Hierarchical RBAC scoping for hosts and users, plus pre-shared registration keys for unattended agent enrollment.

GET/api/access-groups

List every access group (flat). Each row carries parent_id; tree assembly is the client's job. Returns 200 with an array of {id, name, description, parent_id, created_at, updated_at}.

POST/api/access-groups

Create a new group. Body: {name, description?, parent_id?}. Returns 200 on success, 404 if parent_id doesn't exist, 400 on cycle / depth violation. Tree depth is capped at 10.

GET/api/access-groups/{group_id}

Read one group.

PUT/api/access-groups/{group_id}

Update name / description / parent. Cycle detection re-runs against the new parent.

DELETE/api/access-groups/{group_id}

Delete. Children are reparented to the deleted group's parent (or to root) per the FK ON DELETE SET NULL rule.

GET/api/registration-keys

List every registration key without secrets. The plaintext key is only ever returned at create time.

POST/api/registration-keys

Create. Body: {name, access_group_id?, auto_approve?, max_uses?, expires_at?}. Response includes the plaintext key field exactly once — it is never recoverable.

POST/api/registration-keys/{key_id}/revoke

Mark revoked. Idempotent. Existing host enrollments are not affected.

DELETE/api/registration-keys/{key_id}

Delete the key row. (Use revoke instead if you want to keep the audit trail.)

8.2 Scheduled Update Profiles

POSIX-cron profiles describing recurring fleet updates with security-only and staggered-rollout options.

GET/api/upgrade-profiles

List profiles with their next-run timestamps.

POST/api/upgrade-profiles

Create. Body: {name, description?, cron, enabled?, security_only?, package_managers?, staggered_window_min?, tag_id?}. cron validates against the OSS POSIX cron parser (lists, ranges, step intervals, day/month names, dom/dow OR-semantics). staggered_window_min is clamped to [0, 720] minutes.

GET/api/upgrade-profiles/{profile_id}

Read one.

PUT/api/upgrade-profiles/{profile_id}

Update. Cron changes recompute next_run automatically.

DELETE/api/upgrade-profiles/{profile_id}

Delete.

POST/api/upgrade-profiles/{profile_id}/trigger

Fire a profile NOW. Resolves the target host set, enqueues an apply_updates command per host (with the profile's flags + staggered-window delay), updates last_run / next_run, and returns the dispatched host list.

POST/api/upgrade-profiles/tick

Driver hook for an external scheduler. Selects every enabled profile where next_run <= now, fires it, and returns the fired list. Idempotent within a tick.

8.3 Package Compliance Profiles

REQUIRED / BLOCKED package definitions evaluated against host inventory, optionally with version constraints.

GET/api/package-profiles

List profiles (without constraints).

POST/api/package-profiles

Create. Body: {name, description?, enabled?, constraints[]} where each constraint is {package_name, package_manager?, constraint_type, version_op?, version?}. constraint_type is REQUIRED or BLOCKED; version_op is one of =, ==, >=, <=, >, <, !=, ~=.

GET/api/package-profiles/{profile_id}

Read with constraints.

PUT/api/package-profiles/{profile_id}

Update. Constraint list is replaced atomically — pass the full desired list.

DELETE/api/package-profiles/{profile_id}

Delete.

POST/api/package-profiles/{profile_id}/scan/{host_id}

Evaluate the host's cached software_package inventory against the profile, persist the result in HostPackageComplianceStatus, and return it. Fast but only as fresh as the most recent inventory upload.

POST/api/package-profiles/{profile_id}/dispatch/{host_id}

Ask the agent to evaluate compliance against its live local package state and report back via the WS command-result channel. Slower round-trip but always-current.

GET/api/package-profiles/status/host/{host_id}

Latest compliance status for one host across all profiles. Each row contains {status, violations[], last_scan_at}.

8.5 Broadcast Messaging

Fan out one envelope to every connected agent (or every agent matching a tag / platform filter) in a single round-trip.

POST/api/broadcast

Body: {broadcast_action, message?, parameters?, tag_id?, platform?}. Returns {broadcast_id, broadcast_action, delivered_count, elapsed_ms, target_filter}. SLA: under 5 s for fleets up to 100 hosts.

Common actions: refresh_inventory (re-collect software inventory), banner + message (display a notification on the agent host).

8.7 Report Branding

Singleton org branding (logo + company name + header text) injected into every PDF / HTML report by the Pro+ reporting engine.

GET/api/report-branding

Read current branding. Logo bytes are not included; has_logo indicates whether one is configured.

PUT/api/report-branding

Update company_name and header_text. Empty strings clear the field.

POST/api/report-branding/logo

Upload (or replace) the org logo. multipart/form-data with a file field. Allowed: PNG, JPEG, SVG, WEBP. Max size 1 MB.

GET/api/report-branding/logo

Stream the logo bytes. Used by the frontend preview AND embedded as a data URL by the reporting engine.

DELETE/api/report-branding/logo

Remove the configured logo (text fields untouched).

8.7 Custom Report Templates

Admin-defined column subsets / orderings layered on top of the eight base report types.

GET/api/report-templates

List templates.

POST/api/report-templates

Create. Body: {name, description?, base_report_type, selected_fields[], enabled?}. selected_fields entries must be valid codes for the chosen base_report_type; unknown codes are rejected with 400.

GET/api/report-templates/{template_id}

Read one.

PUT/api/report-templates/{template_id}

Update.

DELETE/api/report-templates/{template_id}

Delete.

GET/api/report-templates/base-types

List the eight base report types (registered-hosts, hosts-with-tags, users-list, firewall-status, antivirus-opensource, antivirus-commercial, user-rbac, audit-log) that templates can be built on.

GET/api/report-templates/fields/{base_report_type}

Catalog of available {code, label} pairs for the base type. The frontend uses this to populate the field-picker UI.

Applying a template at render time: add a ?template_id=<uuid> query param to GET /api/v1/reports/view/{report_type} or GET /api/v1/reports/generate/{report_type}. Unknown / disabled templates fall back to the default column set.

8.7 Dynamic Secret Leases

Short-lived OpenBAO/Vault-backed credentials with automatic expiry. The plaintext value is returned exactly once at issue time and never persisted in the SysManage DB.

POST/api/dynamic-secrets/issue

Issue a new lease. Body: {name, kind, backend_role, ttl_seconds, note?}. kind is token, database, or ssh; ttl_seconds is clamped to [60, 86400]. Response: {lease, secret} — surface secret to the operator once and discard.

GET/api/dynamic-secrets/leases

List leases. Optional filters: ?status=ACTIVE|REVOKED|EXPIRED|FAILED, ?kind=token|database|ssh.

GET/api/dynamic-secrets/leases/{lease_id}

Read one lease (no secret).

POST/api/dynamic-secrets/leases/{lease_id}/revoke

Revoke immediately and delete from OpenBAO. Idempotent.

POST/api/dynamic-secrets/reconcile

Sweeper hook — transitions ACTIVE rows whose expires_at has passed into EXPIRED. Safe to call repeatedly.

GET/api/dynamic-secrets/kinds

Catalog of supported lease kinds and the TTL range.

Audit Logging

Every state-changing endpoint above writes one or more rows to the audit_log table via AuditService.log, including the operator's user ID, the entity touched, and the action result. Use GET /api/audit-log/list to query, or GET /api/audit-log/export?fmt=csv to stream a CSV (Phase 8.4).

i18n / l10n

Every operator-visible response string returned by the endpoints above is wrapped with the server's gettext shim and translated into the 14 supported locales: ar, de, en, es, fr, hi, it, ja, ko, nl, pt, ru, zh_CN, zh_TW.