openapi: 3.0.3 info: title: EvoFirewall API version: 0.2.0 description: | Centralized firewall control plane. **HTTP SoT:** this OpenAPI document. **Runtime validation:** Zod schemas in `@evofw/shared` (authoritative for request bodies). servers: - url: http://localhost:8080 description: Local API security: [] paths: /v1/agent/credentials: $ref: './openapi.schemas.json#/paths/~1v1~1agent~1credentials' /v1/agent/token-rotation: $ref: './openapi.schemas.json#/paths/~1v1~1agent~1token-rotation' /api/v1/agents/{id}/token-rotation: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agents~1{id}~1token-rotation' /api/v1/policies/snapshots: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1snapshots' /api/v1/policies/snapshots/{id}: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1snapshots~1{id}' /api/v1/policies/snapshots/{id}/diff: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1snapshots~1{id}~1diff' /api/v1/policies/rollouts: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts' /api/v1/policies/rollouts/{id}: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts~1{id}' /api/v1/policies/rollouts/{id}/confirm: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts~1{id}~1confirm' /api/v1/policies/rollouts/{id}/rollback: $ref: './openapi.schemas.json#/paths/~1api~1v1~1policies~1rollouts~1{id}~1rollback' /api/v1/agents/{id}/policy-pin/release: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agents~1{id}~1policy-pin~1release' /api/v1/agent-labels: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels' /api/v1/agent-labels/{id}: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels~1{id}' /api/v1/agents/{id}/labels: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agents~1{id}~1labels' /api/v1/agent-labels/preview-assignment: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels~1preview-assignment' /api/v1/agent-labels/assign-policy-sets: $ref: './openapi.schemas.json#/paths/~1api~1v1~1agent-labels~1assign-policy-sets' /api/v1/webhooks: get: summary: List webhook endpoints and bounded queue counts (settings admin) tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Endpoint metadata without secrets, configured flag, limits and queue counts '403': description: Settings administrator required post: summary: Create webhook endpoint (at most 20, settings admin) tags: [ops] security: [{ bearerAuth: [] }] requestBody: required: true content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/CreateWebhook' responses: '201': description: Endpoint metadata with secret_configured; secret never returned '503': description: EVOFW_SECRET_KEY missing or shorter than 32 characters /api/v1/webhooks/{id}: parameters: - $ref: '#/components/parameters/Id' patch: summary: Update webhook endpoint; changed destination, signing secret or events cancel pending delivery tags: [ops] security: [{ bearerAuth: [] }] requestBody: required: true content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/PatchWebhook' responses: '200': description: Updated endpoint metadata without secret '503': description: EVOFW_SECRET_KEY unavailable delete: summary: Delete endpoint and cancel queued deliveries (settings admin) tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Deleted /api/v1/webhooks/{id}/deliveries: parameters: - $ref: '#/components/parameters/Id' get: summary: Last 100 pending or terminal deliveries, with sanitized error codes (settings admin) tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Items and total count, excluding payload bytes and signing secrets /health: get: summary: Liveness tags: [system] responses: '200': description: OK /ready: get: summary: SQLite-backed readiness tags: [system] responses: '200': description: Ready '503': description: Database unavailable /api/v1/diagnostics: get: summary: Bounded runtime and delivery queue diagnostics description: Requires fw:settings:admin. Returns DB/WAL sizes, filesystem capacity, audit outbox and limiter counters, RSS/heap and uptime. Memory databases and unavailable filesystem metrics return null; no credentials or queued payloads are returned. tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Runtime diagnostics content: application/json: schema: type: object required: [database, audit_outbox, limiter, process] properties: database: { type: object, additionalProperties: true } audit_outbox: { type: object, additionalProperties: true } limiter: { type: object, additionalProperties: true } process: { type: object, additionalProperties: true } '401': description: Authentication required '403': description: Missing settings administrator permission '429': description: Authenticated user request limit exceeded /api/v1/dashboard: get: summary: Dashboard KPI tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Stats /api/v1/ui/summary: get: summary: Permission-filtered navigation and dashboard summary tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Only sections visible to the authenticated user are included content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/UiSummary' /api/v1/stats/timeseries: get: summary: Coverage-aware fleet or agent packet series tags: [ops] security: [{ bearerAuth: [] }] parameters: - { name: from, in: query, schema: { type: string, format: date-time } } - { name: to, in: query, schema: { type: string, format: date-time } } - { name: resolution, in: query, schema: { type: string, enum: [1m, 1h, 1d] } } - { name: agent_ids, in: query, description: Comma-separated agent IDs (at most 100), schema: { type: string } } responses: '200': description: At most 1440 points and 100 agents; unknown counters are null content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/TimeseriesResponse' /api/v1/install-context: get: summary: Public install base URL + enroll seed hint tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Install context /api/v1/install-links: get: summary: List install links tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Offset' responses: '200': description: Links (items + total) post: summary: Create install link + invited agent tags: [agents] security: [{ bearerAuth: [] }] responses: '201': description: Created /api/v1/install-links/{id}: delete: summary: Revoke install link tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Revoked /api/v1/agents: get: summary: List agents tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Offset' responses: '200': description: Agents (items + total) /api/v1/agents/approve-bulk: post: summary: Approve many pending/invited agents in one request tags: [agents] security: [{ bearerAuth: [] }] requestBody: required: true content: application/json: schema: type: object required: [agent_ids] properties: agent_ids: type: array maxItems: 1000 items: { type: string } responses: '200': description: Approved agents (skips non-pending/invited) /api/v1/agents/{id}: get: summary: Get agent tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Agent patch: summary: Update agent tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Updated delete: summary: Delete agent tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Deleted /api/v1/agents/{id}/approve: post: summary: Approve pending/invited agent tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Approved /api/v1/agents/{id}/revoke: post: summary: Revoke agent tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Revoked /api/v1/agents/{id}/preview: get: summary: Policy preview (truncated CIDRs) tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - name: limit_cidrs in: query schema: { type: integer, default: 50, maximum: 5000 } responses: '200': description: Preview /api/v1/agents/{id}/policy-sets: get: summary: Assigned policy sets tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Sets put: summary: Replace assigned policy sets (order = sort) tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Updated /api/v1/agents/{id}/overrides: get: summary: List IP overrides tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Overrides post: summary: Create override tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Created /api/v1/agents/{id}/overrides/{overrideId}: delete: summary: Delete override tags: [agents] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - name: overrideId in: path required: true schema: { type: string } responses: '200': description: Deleted /api/v1/lists: get: summary: List IP lists tags: [lists] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Offset' - name: view in: query description: Select summary to omit expanded source configuration and entries schema: { type: string, enum: [summary] } responses: '200': description: Lists (items + total) post: summary: Create IP list tags: [lists] security: [{ bearerAuth: [] }] responses: '200': description: Created /api/v1/lists/{id}: get: summary: List detail; use view=page for bounded entries and whole-list filtering tags: [lists] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - { name: view, in: query, schema: { type: string, enum: [page] } } - { name: limit, in: query, description: Requires view=page, schema: { type: integer, minimum: 1, maximum: 200, default: 100 } } - { name: offset, in: query, description: Requires view=page, schema: { type: integer, minimum: 0, maximum: 10000000, default: 0 } } - { name: q, in: query, description: Whole-list text search before pagination; requires view=page, schema: { type: string, maxLength: 256 } } - name: filters in: query description: >- JSON array (at most 10 filters), evaluated over the whole list before paging. Each filter has field value or kind, operator is/is_not/is_any_of/is_not_any_of/ contains/not_contains/starts_with/ends_with/empty/not_empty and values array (at most 20 strings of at most 256 characters). Requires view=page. schema: { type: string } responses: '200': description: >- Default retains full legacy detail. view=page returns metadata plus total, limit, offset, entries and items (at most limit). Each item has kind, value, list_name, resolved_count, resolved_cidrs and resolved_truncated; nested resolved previews are bounded. Invalid page/filter input returns 400. delete: summary: Delete list tags: [lists] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Deleted /api/v1/lists/{id}/refresh: post: summary: Refresh remote/json/evobgp list tags: [lists] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Refreshed /api/v1/lists/{id}/entries: post: summary: Add manual entries tags: [lists] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - name: return in: query schema: { type: string, enum: [summary] } description: Opt in to bounded count/content_hash/changed response instead of expanded detail responses: '200': description: Updated; return=summary uses ListImportSummary from generated contracts delete: summary: Delete entry tags: [lists] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - name: return in: query schema: { type: string, enum: [summary] } description: Opt in to bounded count/content_hash/changed response instead of expanded detail responses: '200': description: Deleted /api/v1/policy-sets: get: summary: List policy sets tags: [policies] security: [{ bearerAuth: [] }] responses: '200': description: Sets post: summary: Create policy set tags: [policies] security: [{ bearerAuth: [] }] responses: '200': description: Created /api/v1/policy-sets/{id}: get: summary: Get policy set tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Set patch: summary: Patch policy set tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Updated delete: summary: Delete policy set tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Deleted /api/v1/policy-sets/{id}/rules: get: summary: Rules in set tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Rules /api/v1/policy-sets/{id}/rules/reorder: put: summary: Reorder rules in a set tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Reordered /api/v1/policy-sets/{id}/agents: put: summary: Replace which agents have this set assigned description: >- Listed agents gain the set (other assignments preserved), unlisted agents lose it. Body — { agent_ids: string[] } (empty array clears). tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: '{ agent_ids, added, removed }' '404': description: Set or agent not found /api/v1/rules: get: summary: List policy rules (optional set filter) tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Offset' responses: '200': description: Rules (items + total) post: summary: Create policy rule tags: [policies] security: [{ bearerAuth: [] }] responses: '200': description: Created /api/v1/rules/{id}: patch: summary: Patch rule tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Updated delete: summary: Delete rule tags: [policies] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Deleted /api/v1/stats/recent: get: summary: Recent apply samples tags: [ops] security: [{ bearerAuth: [] }] responses: '200': description: Samples /api/v1/agents/{id}/stats: get: summary: Apply samples for one agent tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Samples /api/v1/agents/{id}/stats/reset: post: summary: Reset packet totals, samples, and per-IP block stats tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Agent after reset /api/v1/agents/{id}/blocked-ips: get: summary: Per-IP/CIDR drop counters (Linux nft/ipset; MikroTik HITS) tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Top blocked IPs by accumulated packets (+ optional top ports per IP on Linux) content: application/json: schema: type: object properties: items: type: array items: type: object required: [ip, packets, first_seen_at, last_seen_at] properties: ip: { type: string } packets: { type: integer } first_seen_at: { type: string, format: date-time } last_seen_at: { type: string, format: date-time } ports: type: array description: Top destination ports for this IP (Linux nft) items: type: object required: [port, protocol, packets] properties: port: { type: integer, minimum: 1, maximum: 65535 } protocol: { type: string, enum: [tcp, udp] } packets: { type: integer } /api/v1/agents/{id}/blocked-ports: get: summary: Aggregate destination ports hit by denied sources (Linux nft) tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Top ports by accumulated packets across all blocked IPs content: application/json: schema: type: object properties: items: type: array items: type: object required: [port, protocol, packets, last_seen_at] properties: port: { type: integer, minimum: 1, maximum: 65535 } protocol: { type: string, enum: [tcp, udp] } packets: { type: integer } last_seen_at: { type: string, format: date-time } /api/v1/agents/{id}/port-rules: get: summary: Desired Port ACL rules (Linux) tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Port ACL rules content: application/json: schema: type: object properties: items: type: array items: $ref: '#/components/schemas/AgentPortRule' post: summary: Create Port ACL rule tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateAgentPortRule' responses: '200': description: Created rule content: application/json: schema: $ref: '#/components/schemas/AgentPortRule' '400': description: Validation / non-linux /api/v1/agents/{id}/port-rules/import: post: summary: Import Port ACL from IP list or policy set sources tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' requestBody: required: true content: application/json: schema: type: object required: [from, action, ports] properties: from: { type: string, enum: [list, set] } list_id: { type: string } set_id: { type: string } action: { type: string, enum: [open, close] } protocol: { type: string, enum: [tcp, udp, both], default: tcp } ports: type: array minItems: 1 maxItems: 50 items: type: object required: [port_start] properties: port_start: { type: integer, minimum: 1, maximum: 65535 } port_end: { type: integer, minimum: 1, maximum: 65535 } enabled: { type: boolean, default: true } comment: { type: string, maxLength: 500 } responses: '200': description: Created rules content: application/json: schema: type: object properties: items: type: array items: $ref: '#/components/schemas/AgentPortRule' /api/v1/agents/{id}/port-rules/{ruleId}: patch: summary: Update Port ACL rule tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - name: ruleId in: path required: true schema: { type: string } requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateAgentPortRule' responses: '200': description: Updated rule content: application/json: schema: $ref: '#/components/schemas/AgentPortRule' delete: summary: Delete Port ACL rule tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' - name: ruleId in: path required: true schema: { type: string } responses: '200': description: Deleted /api/v1/agents/{id}/host-firewall: get: summary: Last observed host firewall snapshot (Linux) tags: [ops] security: [{ bearerAuth: [] }] parameters: - $ref: '#/components/parameters/Id' responses: '200': description: Snapshot (empty if never reported) content: application/json: schema: type: object properties: collected_at: type: string format: date-time nullable: true raw_digest: type: string nullable: true rules: type: array items: $ref: '#/components/schemas/HostFwRule' listeners: type: array items: $ref: '#/components/schemas/HostListener' /api/v1/integrations/evobgp/communities: get: summary: Proxy EvoBGP communities tags: [integrations] security: [{ bearerAuth: [] }] responses: '200': description: Communities /api/v1/settings: get: summary: Settings map (token masked) tags: [settings] security: [{ bearerAuth: [] }] responses: '200': description: Settings put: summary: Update whitelisted settings keys tags: [settings] security: [{ bearerAuth: [] }] requestBody: required: true content: application/json: schema: type: object additionalProperties: type: string description: Keys — enroll_seed, evobgp_api_url, evobgp_api_token, agent_sync_interval_sec, show_quick_actions responses: '200': description: Saved '400': description: Unknown key / validation /api/v1/audit: get: summary: Local audit log tags: [ops] security: [{ bearerAuth: [] }] parameters: - name: action in: query schema: { type: string } - name: severity in: query schema: { type: string, enum: [info, warning, critical] } - name: limit in: query schema: { type: integer, default: 200 } responses: '200': description: Audit entries /v1/agent/install.sh: get: summary: Agent install script tags: [agent-public] responses: '200': description: Shell script /v1/agent/sync-script: get: summary: Linux sync agent (evofw-firewall.sh) tags: [agent-public] parameters: - name: If-None-Match in: header schema: { type: string } description: ETag from a previous GET (`""`) responses: '200': description: Shell script headers: ETag: schema: { type: string } description: '""' X-Evofw-Script-Sha256: schema: { type: string } description: Hex sha256 of the script body '304': description: Script unchanged /v1/agent/enroll: post: summary: Enroll with single-use install-link credential (legacy global seed refused) tags: [agent-public] parameters: - name: X-EvoFW-Enrollment-Credential in: header required: true schema: { type: string } requestBody: required: true content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/EnrollWithCredential' responses: '200': description: Exact consumed enrollment retry; same client; no-store '201': description: Newly enrolled pending agent; no-store '401': description: Scoped enrollment credential required '409': description: Credential already consumed with different enrollment /v1/agent/policy: get: summary: Evaluated policy for agent tags: [agent] security: [{ agentToken: [] }] responses: '200': description: Policy (includes script_sha256 for Linux self-update; not part of policy.hash) content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/AgentPolicy' /v1/agent/policy.rsc: get: summary: MikroTik RSC policy tags: [agent] security: [{ agentToken: [] }] responses: '200': description: RSC text /v1/agent/heartbeat: post: summary: Agent heartbeat tags: [agent] security: [{ agentToken: [] }] responses: '200': description: OK /v1/agent/apply-report: post: summary: Apply report + packet stats (+ optional ip_hits / port_hits / host_firewall) tags: [agent] security: [{ agentToken: [] }] requestBody: required: true content: application/json: schema: $ref: './openapi.schemas.json#/components/schemas/ApplyReport' responses: '200': description: OK components: parameters: Id: name: id in: path required: true schema: { type: string } Limit: name: limit in: query schema: { type: integer, minimum: 1, maximum: 1000 } description: Page size (without limit/offset the full list is returned) Offset: name: offset in: query schema: { type: integer, minimum: 0 } description: Page offset (response includes total) schemas: AgentPortRule: type: object required: [ id, agent_id, action, protocol, port_start, port_end, src_kind, enabled, priority, created_at, updated_at, ] properties: id: { type: string } agent_id: { type: string } action: { type: string, enum: [open, close] } protocol: { type: string, enum: [tcp, udp, both] } port_start: { type: integer, minimum: 1, maximum: 65535 } port_end: { type: integer, minimum: 1, maximum: 65535 } src_kind: { type: string, enum: [all, cidr, list] } src_cidr: { type: string, nullable: true } list_id: { type: string, nullable: true } list_name: { type: string, nullable: true } enabled: { type: boolean } comment: { type: string, nullable: true } priority: { type: integer } created_at: { type: string, format: date-time } updated_at: { type: string, format: date-time } CreateAgentPortRule: type: object required: [action, port_start] properties: action: { type: string, enum: [open, close] } protocol: { type: string, enum: [tcp, udp, both], default: tcp } port_start: { type: integer, minimum: 1, maximum: 65535 } port_end: { type: integer, minimum: 1, maximum: 65535 } src_kind: { type: string, enum: [all, cidr, list], default: all } src_cidr: { type: string } list_id: { type: string } enabled: { type: boolean, default: true } comment: { type: string, maxLength: 500 } priority: { type: integer, default: 100 } UpdateAgentPortRule: type: object properties: action: { type: string, enum: [open, close] } protocol: { type: string, enum: [tcp, udp, both] } port_start: { type: integer, minimum: 1, maximum: 65535 } port_end: { type: integer, minimum: 1, maximum: 65535 } src_kind: { type: string, enum: [all, cidr, list] } src_cidr: { type: string, nullable: true } list_id: { type: string, nullable: true } enabled: { type: boolean } comment: { type: string, maxLength: 500, nullable: true } priority: { type: integer } HostFwRule: type: object required: [ownership, backend, raw] properties: ownership: { type: string, enum: [evofw, foreign] } backend: type: string enum: [nft, iptables, ufw, firewalld, listener] table: { type: string } chain: { type: string } action: { type: string } protocol: { type: string } dport: { type: string } sport: { type: string } saddr: { type: string } daddr: { type: string } comment: { type: string } raw: { type: string, maxLength: 512 } HostListener: type: object required: [protocol, port, address] properties: protocol: { type: string } port: { type: integer, minimum: 0, maximum: 65535 } address: { type: string } process: { type: string } HostFirewallPayload: type: object properties: rules: type: array maxItems: 500 items: $ref: '#/components/schemas/HostFwRule' listeners: type: array maxItems: 200 items: $ref: '#/components/schemas/HostListener' securitySchemes: bearerAuth: type: http scheme: bearer description: Portal JWT (app id fw) agentToken: type: http scheme: bearer description: Agent enroll token tags: - name: system - name: ops - name: agents - name: lists - name: policies - name: settings - name: integrations - name: agent-public - name: agent