{"openapi":"3.1.0","info":{"title":"taranac","description":"Taranac is a web-based **network access control** platform — an open analogue of\nCisco ISE. One control-plane API drives two products:\n\n* **AAA** — device administration over **TACACS+** and **RADIUS**\n  (authentication, command authorization, accounting).\n* **NAC** — port access control over **802.1X** RADIUS (PEAP / EAP-TLS / MAB),\n  endpoint profiling, dynamic VLAN / ACL assignment and guest captive portals.\n\nThe API generates the configuration consumed by the downstream `tac_plus-ng`,\nFreeRADIUS and 802.1X daemons; those daemons never call this API at runtime.\n\n## Conventions\n\n* **Base path** — all management endpoints live under `/api/v1`. Health probes\n  (`/healthz`, `/ready`) and a few public surfaces (captive-portal flows, CA /\n  certificate downloads) are mounted at the root.\n* **Auth** — obtain a token via `POST /api/v1/auth/login`, then send\n  `Authorization: Bearer <token>`. Most endpoints are gated by RBAC permissions\n  (`GET /api/v1/rbac/schema` lists them); admin accounts bypass the gate.\n* **Errors** — failures return a consistent body `{ \"detail\", \"code\", \"field\" }`.\n  Messages are localized from the `Accept-Language` header (`en` / `ru`).\n* **Validation** — request bodies are strict: unknown fields are rejected\n  (`422`), lengths and ranges are bounded, and blank optional text normalizes to\n  `null`.\n* **Timestamps** — stored and returned in **UTC** (ISO-8601); clients localize.\n* **Pagination** — list endpoints accept `page`, `per_page`, `search`,\n  `sort_by`, `sort_order` and return `{ items, total, total_by_filter }`.\n","version":"1.2.2"},"paths":{"/api/v1/aaa/policy/rules":{"get":{"tags":["AAA Policy"],"summary":"List AAA policy rules","description":"List all policy rules in evaluation order.\n\nSupports optional filtering by WHO (user/group), WHERE (device/device_group),\nTACACS+ profile, and RADIUS profile. Filters across dimensions are combined\nwith AND; within a dimension they are combined with OR.\n\nWhen resolve_groups=true, who_user_id also matches rules targeting\ngroups the user belongs to, and where_device_id also matches rules\ntargeting device groups the device belongs to.","operationId":"list_rules_api_v1_aaa_policy_rules_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"who_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by user in WHO","title":"Who User Id"},"description":"Filter by user in WHO"},{"name":"who_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by group in WHO","title":"Who Group Id"},"description":"Filter by group in WHO"},{"name":"where_device_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by device in WHERE","title":"Where Device Id"},"description":"Filter by device in WHERE"},{"name":"where_device_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by device group in WHERE","title":"Where Device Group Id"},"description":"Filter by device group in WHERE"},{"name":"tacacs_profile_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by TACACS+ profile","title":"Tacacs Profile Id"},"description":"Filter by TACACS+ profile"},{"name":"radius_profile_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by RADIUS profile","title":"Radius Profile Id"},"description":"Filter by RADIUS profile"},{"name":"resolve_groups","in":"query","required":false,"schema":{"type":"boolean","description":"When true and who_user_id is set, also match rules targeting any group the user belongs to. Same for where_device_id and device groups.","default":false,"title":"Resolve Groups"},"description":"When true and who_user_id is set, also match rules targeting any group the user belongs to. Same for where_device_id and device groups."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AaaPolicyRuleResponse"},"title":"Response List Rules Api V1 Aaa Policy Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["AAA Policy"],"summary":"Create an AAA policy rule","description":"Create a new policy rule.","operationId":"create_rule_api_v1_aaa_policy_rules_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AaaPolicyRuleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AaaPolicyRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/policy/rules/reorder":{"put":{"tags":["AAA Policy"],"summary":"Reorder AAA policy rules","description":"Atomically reorder all policy rules.","operationId":"reorder_rules_api_v1_aaa_policy_rules_reorder_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AaaPolicyReorderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AaaPolicyRuleResponse"},"type":"array","title":"Response Reorder Rules Api V1 Aaa Policy Rules Reorder Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/aaa/policy/rules/{rule_id}":{"get":{"tags":["AAA Policy"],"summary":"Get an AAA policy rule","description":"Get a single policy rule by ID.","operationId":"get_rule_api_v1_aaa_policy_rules__rule_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AaaPolicyRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["AAA Policy"],"summary":"Update an AAA policy rule","description":"Update a policy rule.","operationId":"update_rule_api_v1_aaa_policy_rules__rule_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AaaPolicyRuleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AaaPolicyRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["AAA Policy"],"summary":"Delete an AAA policy rule","description":"Delete a policy rule. Default rule cannot be deleted.","operationId":"delete_rule_api_v1_aaa_policy_rules__rule_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/policy/rules/{rule_id}/tacacs/preview":{"get":{"tags":["AAA Policy"],"summary":"Preview tac_plus-ng config snippet for a single rule","description":"Preview the tac_plus-ng config snippet that a single rule generates.","operationId":"preview_rule_tacacs_api_v1_aaa_policy_rules__rule_id__tacacs_preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RuleTacacsPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/policy/test":{"post":{"tags":["AAA Policy"],"summary":"Test AAA policy evaluation","description":"Test policy evaluation against simulated request parameters.","operationId":"test_policy_api_v1_aaa_policy_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PolicyTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/command-sets":{"get":{"tags":["Command Sets"],"summary":"List command sets","description":"List command sets with pagination.","operationId":"list_command_sets_api_v1_tacacs_command_sets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, description","title":"Search"},"description":"Search name, description"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CommandSetListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Command Sets"],"summary":"Create a command set","description":"Create a command set with nested commands and argument rules.","operationId":"create_command_set_api_v1_tacacs_command_sets_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandSetCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/command-sets/{command_set_id}":{"get":{"tags":["Command Sets"],"summary":"Get a command set","description":"Get a single command set with all commands and argument rules.","operationId":"get_command_set_api_v1_tacacs_command_sets__command_set_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"command_set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Command Set Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Command Sets"],"summary":"Update a command set","description":"Update a command set. Providing commands replaces the entire list.","operationId":"update_command_set_api_v1_tacacs_command_sets__command_set_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"command_set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Command Set Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandSetUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CommandSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Command Sets"],"summary":"Delete a command set","description":"Delete a command set. Fails if referenced by any profile.","operationId":"delete_command_set_api_v1_tacacs_command_sets__command_set_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"command_set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Command Set Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/command-sets/{command_set_id}/references":{"get":{"tags":["Command Sets"],"summary":"Where this is used (blocking + auto-clearing references)","operationId":"command_set_references_api_v1_tacacs_command_sets__command_set_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"command_set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Command Set Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/command-sets/references/counts":{"post":{"tags":["Command Sets"],"summary":"Batch reference counts (the Ref column)","operationId":"command_set_reference_counts_api_v1_tacacs_command_sets_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Command Set Reference Counts Api V1 Tacacs Command Sets References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/log-exclusions":{"get":{"tags":["Log Exclusions"],"summary":"List log exclusion rules","description":"List log exclusion rules with pagination and filtering.","operationId":"list_exclusions_api_v1_log_exclusions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name, description, or match_value","title":"Search"},"description":"Search by name, description, or match_value"},{"name":"protocol","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by protocol: all, tacacs, radius","title":"Protocol"},"description":"Filter by protocol: all, tacacs, radius"},{"name":"match_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by match_type: username, username_pattern, user_group","title":"Match Type"},"description":"Filter by match_type: username, username_pattern, user_group"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, protocol, match_type, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, protocol, match_type, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_LogExclusionListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Log Exclusions"],"summary":"Create a log exclusion rule","description":"Create a new log exclusion rule.","operationId":"create_exclusion_api_v1_log_exclusions_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogExclusionCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogExclusionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/log-exclusions/{exclusion_id}":{"get":{"tags":["Log Exclusions"],"summary":"Get a log exclusion rule","description":"Get a single log exclusion rule by ID.","operationId":"get_exclusion_api_v1_log_exclusions__exclusion_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"exclusion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Exclusion Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogExclusionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Log Exclusions"],"summary":"Update a log exclusion rule","description":"Update a log exclusion rule.","operationId":"update_exclusion_api_v1_log_exclusions__exclusion_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"exclusion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Exclusion Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogExclusionUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogExclusionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Log Exclusions"],"summary":"Delete a log exclusion rule","description":"Delete a log exclusion rule.","operationId":"delete_exclusion_api_v1_log_exclusions__exclusion_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"exclusion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Exclusion Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/authentication":{"get":{"tags":["AAA Logs"],"summary":"List TACACS+ authentication logs","description":"List TACACS+ authentication log entries.","operationId":"list_tacacs_authn_api_v1_aaa_logs_tacacs_authentication_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: success, failure","title":"Status"},"description":"Filter: success, failure"},{"name":"rule_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched policy rule name, e.g. 'policy_1'","title":"Rule Name"},"description":"Filter by matched policy rule name, e.g. 'policy_1'"},{"name":"profile","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched profile name, e.g. 'profile_rule_1'","title":"Profile"},"description":"Filter by matched profile name, e.g. 'profile_rule_1'"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (timestamp, username, nas_ip, status, rule_name, profile)","title":"Sort By"},"description":"Sort field (timestamp, username, nas_ip, status, rule_name, profile)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TacacsAuthnLogListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/authentication/export":{"get":{"tags":["AAA Logs"],"summary":"Export TACACS+ authentication logs","description":"Export TACACS+ authentication logs as XLSX or CSV.\n\nApplies the same filters as the list endpoint. Export is capped at\n10,000 rows; omit page/per_page to export the full filtered set up\nto that limit.","operationId":"export_tacacs_authn_api_v1_aaa_logs_tacacs_authentication_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number (omit for all records)","title":"Page"},"description":"Page number (omit for all records)"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Items per page (omit for all records)","title":"Per Page"},"description":"Items per page (omit for all records)"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: success, failure","title":"Status"},"description":"Filter: success, failure"},{"name":"rule_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched policy rule name","title":"Rule Name"},"description":"Filter by matched policy rule name"},{"name":"profile","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched profile name","title":"Profile"},"description":"Filter by matched profile name"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/authentication/{log_id}":{"get":{"tags":["AAA Logs"],"summary":"Get a TACACS+ authentication log entry","description":"Get a single TACACS+ authentication log entry.","operationId":"get_tacacs_authn_api_v1_aaa_logs_tacacs_authentication__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsAuthnLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/authorization":{"get":{"tags":["AAA Logs"],"summary":"List TACACS+ authorization logs","description":"List TACACS+ authorization log entries.","operationId":"list_tacacs_authz_api_v1_aaa_logs_tacacs_authorization_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: permit, deny","title":"Action"},"description":"Filter: permit, deny"},{"name":"rule_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched policy rule name, e.g. 'policy_1'","title":"Rule Name"},"description":"Filter by matched policy rule name, e.g. 'policy_1'"},{"name":"profile","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched profile name, e.g. 'profile_rule_1'","title":"Profile"},"description":"Filter by matched profile name, e.g. 'profile_rule_1'"},{"name":"service","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by service name, e.g. 'shell'","title":"Service"},"description":"Filter by service name, e.g. 'shell'"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (timestamp, username, nas_ip, action, rule_name, profile, service)","title":"Sort By"},"description":"Sort field (timestamp, username, nas_ip, action, rule_name, profile, service)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TacacsAuthzLogListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/authorization/export":{"get":{"tags":["AAA Logs"],"summary":"Export TACACS+ authorization logs","description":"Export TACACS+ authorization logs as XLSX or CSV.\n\nApplies the same filters as the list endpoint. Export is capped at\n10,000 rows.","operationId":"export_tacacs_authz_api_v1_aaa_logs_tacacs_authorization_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number (omit for all records)","title":"Page"},"description":"Page number (omit for all records)"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Items per page (omit for all records)","title":"Per Page"},"description":"Items per page (omit for all records)"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: permit, deny","title":"Action"},"description":"Filter: permit, deny"},{"name":"rule_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched policy rule name","title":"Rule Name"},"description":"Filter by matched policy rule name"},{"name":"profile","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by matched profile name","title":"Profile"},"description":"Filter by matched profile name"},{"name":"service","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by service name","title":"Service"},"description":"Filter by service name"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/authorization/{log_id}":{"get":{"tags":["AAA Logs"],"summary":"Get a TACACS+ authorization log entry","description":"Get a single TACACS+ authorization log entry.","operationId":"get_tacacs_authz_api_v1_aaa_logs_tacacs_authorization__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsAuthzLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/accounting":{"get":{"tags":["AAA Logs"],"summary":"List TACACS+ accounting logs","description":"List TACACS+ accounting log entries.","operationId":"list_tacacs_acct_api_v1_aaa_logs_tacacs_accounting_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: start, stop, watchdog","title":"Action"},"description":"Filter: start, stop, watchdog"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (timestamp, username, nas_ip, action)","title":"Sort By"},"description":"Sort field (timestamp, username, nas_ip, action)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TacacsAcctLogListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/accounting/export":{"get":{"tags":["AAA Logs"],"summary":"Export TACACS+ accounting logs","description":"Export TACACS+ accounting logs as XLSX or CSV.\n\nApplies the same filters as the list endpoint. Export is capped at\n10,000 rows.","operationId":"export_tacacs_acct_api_v1_aaa_logs_tacacs_accounting_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number (omit for all records)","title":"Page"},"description":"Page number (omit for all records)"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Items per page (omit for all records)","title":"Per Page"},"description":"Items per page (omit for all records)"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: start, stop, watchdog","title":"Action"},"description":"Filter: start, stop, watchdog"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/tacacs/accounting/{log_id}":{"get":{"tags":["AAA Logs"],"summary":"Get a TACACS+ accounting log entry","description":"Get a single TACACS+ accounting log entry.","operationId":"get_tacacs_acct_api_v1_aaa_logs_tacacs_accounting__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsAcctLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/radius/authentication":{"get":{"tags":["AAA Logs"],"summary":"List RADIUS authentication logs","description":"List RADIUS authentication log entries.","operationId":"list_radius_auth_api_v1_aaa_logs_radius_authentication_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: accept, reject","title":"Status"},"description":"Filter: accept, reject"},{"name":"auth_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by credential transport: PAP, MS-CHAPv2, CHAP","title":"Auth Type"},"description":"Filter by credential transport: PAP, MS-CHAPv2, CHAP"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (timestamp, username, nas_ip, status, rule_name, rule_label)","title":"Sort By"},"description":"Sort field (timestamp, username, nas_ip, status, rule_name, rule_label)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_RadiusAuthLogListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/radius/authentication/export":{"get":{"tags":["AAA Logs"],"summary":"Export RADIUS authentication logs","description":"Export RADIUS authentication logs as XLSX or CSV.\n\nApplies the same filters as the list endpoint. Export is capped at\n10,000 rows.","operationId":"export_radius_auth_api_v1_aaa_logs_radius_authentication_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number (omit for all records)","title":"Page"},"description":"Page number (omit for all records)"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Items per page (omit for all records)","title":"Per Page"},"description":"Items per page (omit for all records)"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: accept, reject","title":"Status"},"description":"Filter: accept, reject"},{"name":"auth_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by credential transport: PAP, MS-CHAPv2, CHAP","title":"Auth Type"},"description":"Filter by credential transport: PAP, MS-CHAPv2, CHAP"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/radius/authentication/{log_id}":{"get":{"tags":["AAA Logs"],"summary":"Get a RADIUS authentication log entry","description":"Get a single RADIUS authentication log entry.","operationId":"get_radius_auth_api_v1_aaa_logs_radius_authentication__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusAuthLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/radius/accounting":{"get":{"tags":["AAA Logs"],"summary":"List RADIUS accounting logs","description":"List RADIUS accounting log entries.","operationId":"list_radius_acct_api_v1_aaa_logs_radius_accounting_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"acct_status_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: Start, Stop, Interim-Update","title":"Acct Status Type"},"description":"Filter: Start, Stop, Interim-Update"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (timestamp, username, nas_ip, acct_status_type)","title":"Sort By"},"description":"Sort field (timestamp, username, nas_ip, acct_status_type)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_RadiusAcctLogListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/radius/accounting/export":{"get":{"tags":["AAA Logs"],"summary":"Export RADIUS accounting logs","description":"Export RADIUS accounting logs as XLSX or CSV.\n\nApplies the same filters as the list endpoint. Export is capped at\n10,000 rows.","operationId":"export_radius_acct_api_v1_aaa_logs_radius_accounting_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number (omit for all records)","title":"Page"},"description":"Page number (omit for all records)"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Items per page (omit for all records)","title":"Per Page"},"description":"Items per page (omit for all records)"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username (exact)","title":"Username"},"description":"Filter by username (exact)"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"acct_status_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: Start, Stop, Interim-Update","title":"Acct Status Type"},"description":"Filter: Start, Stop, Interim-Update"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or after this timestamp (UTC)","title":"Date From"},"description":"Only entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only entries at or before this timestamp (UTC)","title":"Date To"},"description":"Only entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search across log fields","title":"Search"},"description":"Free-text search across log fields"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/aaa/logs/radius/accounting/{log_id}":{"get":{"tags":["AAA Logs"],"summary":"Get a RADIUS accounting log entry","description":"Get a single RADIUS accounting log entry.","operationId":"get_radius_acct_api_v1_aaa_logs_radius_accounting__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusAcctLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/config/preview":{"get":{"tags":["RADIUS Settings"],"summary":"Preview currently deployed FreeRADIUS config","description":"Return the config files currently deployed on disk.","operationId":"preview_radius_config_api_v1_radius_config_preview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusConfigPreviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/config/preview-pending":{"get":{"tags":["RADIUS Settings"],"summary":"Preview pending FreeRADIUS config (rendered from DB)","description":"Render config from current DB state without writing to disk.","operationId":"preview_pending_radius_config_api_v1_radius_config_preview_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusConfigPreviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/config/validate":{"post":{"tags":["RADIUS Settings"],"summary":"Validate generated RADIUS config (dry-run)","description":"Generate and validate the config without writing or reloading.\n\nRuns ``radiusd -XC`` on the generated config. If validation fails,\nthe response includes error details with file name, line number,\nand a code snippet around the error line for UI highlighting.","operationId":"validate_radius_config_api_v1_radius_config_validate_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusConfigValidateResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/config/reload":{"post":{"tags":["RADIUS Settings"],"summary":"Generate, validate, write, and reload FreeRADIUS config","description":"Full config lifecycle: generate → validate → write → signal reload.\n\nIf the config content hasn't changed since the last deploy, returns\n``status=unchanged`` and skips all work — unless ``force=true``.","operationId":"reload_radius_config_api_v1_radius_config_reload_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Force reload even if config hasn't changed","default":false,"title":"Force"},"description":"Force reload even if config hasn't changed"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusConfigReloadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/status":{"get":{"tags":["RADIUS Settings"],"summary":"Get RADIUS service status","description":"Get current RADIUS service status.\n\nReturns:\n- Service connectivity (UDP check to FreeRADIUS ports)\n- Last config deploy info (timestamp, hash, deployed_by)\n- Last validation result (valid/invalid + error details)\n\nStatus data is read from a file on the shared config volume —\nno config re-generation or re-validation happens on this call.","operationId":"get_radius_status_api_v1_radius_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/settings":{"get":{"tags":["RADIUS Settings"],"summary":"Get all RADIUS settings","description":"Return the full RADIUS settings document.\n\nEncrypted values (e.g. ``global_secret``) are masked as ``***``.\nRequires ``radius_settings.view`` permission.","operationId":"get_radius_settings_api_v1_radius_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["RADIUS Settings"],"summary":"Partially update RADIUS settings","description":"Update only the provided RADIUS settings; omitted fields are unchanged.\n\nRequires ``radius_settings.edit`` permission.","operationId":"patch_radius_settings_api_v1_radius_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/settings/global-secret/reveal":{"get":{"tags":["RADIUS Settings"],"summary":"Reveal decrypted RADIUS global shared secret","description":"Reveal the decrypted RADIUS global shared secret.\n\nReturns the plaintext value of radius.global_secret.\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged for security tracking.","operationId":"reveal_global_secret_api_v1_radius_settings_global_secret_reveal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Response Reveal Global Secret Api V1 Radius Settings Global Secret Reveal Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/profiles":{"get":{"tags":["RADIUS Profiles"],"summary":"List RADIUS profiles","description":"List RADIUS profiles with pagination and filtering.","operationId":"list_profiles_api_v1_radius_profiles_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, description","title":"Search"},"description":"Search name, description"},{"name":"template_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by template ID","title":"Template Id"},"description":"Filter by template ID"},{"name":"template_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by template name (partial match)","title":"Template Name"},"description":"Filter by template name (partial match)"},{"name":"is_enabled","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by enabled status","title":"Is Enabled"},"description":"Filter by enabled status"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_RadiusProfileListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["RADIUS Profiles"],"summary":"Create a RADIUS profile","description":"Create a new RADIUS profile.","operationId":"create_profile_api_v1_radius_profiles_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusProfileCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/profiles/{profile_id}":{"get":{"tags":["RADIUS Profiles"],"summary":"Get a RADIUS profile","description":"Get a single RADIUS profile.\n\nEmbeds the linked template detail so the editor opens in a single request (the\nlist endpoint stays lean with a brief only).","operationId":"get_profile_api_v1_radius_profiles__profile_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["RADIUS Profiles"],"summary":"Update a RADIUS profile","description":"Update a RADIUS profile.","operationId":"update_profile_api_v1_radius_profiles__profile_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusProfileUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["RADIUS Profiles"],"summary":"Delete a RADIUS profile","description":"Delete a RADIUS profile.","operationId":"delete_profile_api_v1_radius_profiles__profile_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/profiles/{profile_id}/references":{"get":{"tags":["RADIUS Profiles"],"summary":"Where this is used (blocking + auto-clearing references)","operationId":"radius_profile_references_api_v1_radius_profiles__profile_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/profiles/references/counts":{"post":{"tags":["RADIUS Profiles"],"summary":"Batch reference counts (the Ref column)","operationId":"radius_profile_reference_counts_api_v1_radius_profiles_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Radius Profile Reference Counts Api V1 Radius Profiles References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/templates":{"get":{"tags":["RADIUS Templates"],"summary":"List RADIUS templates","description":"List RADIUS templates with pagination and filtering.","operationId":"list_templates_api_v1_radius_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, slug, vendor, description","title":"Search"},"description":"Search name, slug, vendor, description"},{"name":"vendor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by vendor","title":"Vendor"},"description":"Filter by vendor"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, vendor, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, vendor, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_RadiusTemplateListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["RADIUS Templates"],"summary":"Create a RADIUS template","description":"Create a new RADIUS template.","operationId":"create_template_api_v1_radius_templates_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/templates/{template_id}":{"get":{"tags":["RADIUS Templates"],"summary":"Get a RADIUS template","description":"Get a single RADIUS template.","operationId":"get_template_api_v1_radius_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["RADIUS Templates"],"summary":"Update a RADIUS template","description":"Update a RADIUS template. Slug is immutable.","operationId":"update_template_api_v1_radius_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["RADIUS Templates"],"summary":"Delete a RADIUS template","description":"Delete a RADIUS template. Fails if referenced by profiles.","operationId":"delete_template_api_v1_radius_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/templates/validate":{"post":{"tags":["RADIUS Templates"],"summary":"Validate RADIUS template YAML","description":"Validate YAML content without creating a template.","operationId":"validate_template_yaml_api_v1_radius_templates_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateValidateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RadiusTemplateValidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/radius/templates/{template_id}/references":{"get":{"tags":["RADIUS Templates"],"summary":"Where this is used (blocking + auto-clearing references)","operationId":"radius_template_references_api_v1_radius_templates__template_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/radius/templates/references/counts":{"post":{"tags":["RADIUS Templates"],"summary":"Batch reference counts (the Ref column)","operationId":"radius_template_reference_counts_api_v1_radius_templates_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Radius Template Reference Counts Api V1 Radius Templates References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/syslog/destinations":{"get":{"tags":["Syslog"],"summary":"List syslog destinations","description":"List syslog destinations.","operationId":"list_destinations_api_v1_syslog_destinations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name, description, or host","title":"Search"},"description":"Search by name, description, or host"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, transport, host, port, is_enabled, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, transport, host, port, is_enabled, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_SyslogDestinationListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Syslog"],"summary":"Create a syslog destination","description":"Create a new syslog destination.","operationId":"create_destination_api_v1_syslog_destinations_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogDestinationCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogDestinationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/syslog/destinations/{dest_id}":{"get":{"tags":["Syslog"],"summary":"Get a syslog destination","description":"Get a syslog destination by ID.","operationId":"get_destination_api_v1_syslog_destinations__dest_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dest Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogDestinationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Syslog"],"summary":"Update a syslog destination","description":"Update a syslog destination.","operationId":"update_destination_api_v1_syslog_destinations__dest_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dest Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogDestinationUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogDestinationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Syslog"],"summary":"Delete a syslog destination","description":"Delete a syslog destination. Bindings are cascade-deleted.","operationId":"delete_destination_api_v1_syslog_destinations__dest_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dest Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/syslog/destinations/{dest_id}/test":{"post":{"tags":["Syslog"],"summary":"Test a syslog destination","description":"Send a test syslog message to verify connectivity.","operationId":"test_destination_api_v1_syslog_destinations__dest_id__test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dest_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dest Id"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogTestRequest","default":{"message":"taranac test message"}}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyslogTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/syslog/bindings":{"get":{"tags":["Syslog"],"summary":"List syslog log bindings","description":"List log bindings with optional filters.","operationId":"list_bindings_api_v1_syslog_bindings_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"destination_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by destination","title":"Destination Id"},"description":"Filter by destination"},{"name":"module","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by module: tacacs, radius, nac, system","title":"Module"},"description":"Filter by module: tacacs, radius, nac, system"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LogBindingResponse"},"title":"Response List Bindings Api V1 Syslog Bindings Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Syslog"],"summary":"Create a syslog log binding","description":"Create a new log binding.","operationId":"create_binding_api_v1_syslog_bindings_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogBindingCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogBindingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/syslog/bindings/{binding_id}":{"delete":{"tags":["Syslog"],"summary":"Delete a syslog log binding","description":"Delete a log binding.","operationId":"delete_binding_api_v1_syslog_bindings__binding_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"binding_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Binding Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/config/preview":{"get":{"tags":["TACACS+ Settings"],"summary":"Preview currently deployed tac_plus-ng config","description":"Return the config currently deployed on disk.","operationId":"preview_config_api_v1_tacacs_config_preview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigPreviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/config/preview-pending":{"get":{"tags":["TACACS+ Settings"],"summary":"Preview pending tac_plus-ng config (rendered from DB)","description":"Render config from current DB state without writing to disk.","operationId":"preview_pending_config_api_v1_tacacs_config_preview_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigPreviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/config/validate":{"post":{"tags":["TACACS+ Settings"],"summary":"Validate generated config (dry-run)","description":"Generate and validate the config without writing or reloading.\n\nRuns ``tac_plus-ng -P`` on the generated config. If validation fails,\nthe response includes error details, rule mapping, and a code snippet\naround the error line for UI highlighting.","operationId":"validate_config_api_v1_tacacs_config_validate_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigValidateResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/config/reload":{"post":{"tags":["TACACS+ Settings"],"summary":"Generate, validate, write, and reload tac_plus-ng config","description":"Full config lifecycle: generate → validate → write → signal reload.\n\nIf the config content hasn't changed since the last deploy, returns\n``status=unchanged`` and skips all work — unless ``force=true``.","operationId":"reload_config_api_v1_tacacs_config_reload_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Force reload even if config hasn't changed","default":false,"title":"Force"},"description":"Force reload even if config hasn't changed"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfigReloadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/status":{"get":{"tags":["TACACS+ Settings"],"summary":"Get TACACS+ service status","description":"Get current TACACS+ service status.\n\nReturns:\n- Service connectivity (TCP check to tac_plus-ng port)\n- Last config deploy info (timestamp, hash, deployed_by)\n- Last validation result (valid/invalid + error details)\n\nStatus data is read from a file on the shared config volume —\nno config re-generation or re-validation happens on this call.","operationId":"get_tacacs_status_api_v1_tacacs_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/settings":{"get":{"tags":["TACACS+ Settings"],"summary":"Get all TACACS+ settings","description":"Return the full TACACS+ settings document.\n\nEncrypted values (e.g. ``global_key``) are masked as ``***``.\nRequires ``tacacs_settings.view`` permission.","operationId":"get_tacacs_settings_api_v1_tacacs_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["TACACS+ Settings"],"summary":"Partially update TACACS+ settings","description":"Update only the provided TACACS+ settings; omitted fields are unchanged.\n\nRequires ``tacacs_settings.edit`` permission.","operationId":"patch_tacacs_settings_api_v1_tacacs_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/settings/global-key/reveal":{"get":{"tags":["TACACS+ Settings"],"summary":"Reveal decrypted TACACS+ global shared secret","description":"Reveal the decrypted TACACS+ global shared secret.\n\nReturns the plaintext value of tacacs.global_key.\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged for security tracking.","operationId":"reveal_global_key_api_v1_tacacs_settings_global_key_reveal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Response Reveal Global Key Api V1 Tacacs Settings Global Key Reveal Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/settings/global-enable-password/reveal":{"get":{"tags":["TACACS+ Settings"],"summary":"Reveal decrypted TACACS+ global enable password","description":"Reveal the decrypted TACACS+ global enable password.\n\nOnly meaningful when ``tacacs.global_enable_mode`` is ``custom``.\nReturns the plaintext value of ``tacacs.global_enable_password``.\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged for security tracking.","operationId":"reveal_global_enable_password_api_v1_tacacs_settings_global_enable_password_reveal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Response Reveal Global Enable Password Api V1 Tacacs Settings Global Enable Password Reveal Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/profiles":{"get":{"tags":["TACACS+ Profiles"],"summary":"List TACACS+ profiles","description":"List TACACS+ profiles with pagination and filtering.","operationId":"list_profiles_api_v1_tacacs_profiles_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, description","title":"Search"},"description":"Search name, description"},{"name":"template_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by template ID","title":"Template Id"},"description":"Filter by template ID"},{"name":"template_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by template name (partial match)","title":"Template Name"},"description":"Filter by template name (partial match)"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TacacsProfileListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["TACACS+ Profiles"],"summary":"Create a TACACS+ profile","description":"Create a new TACACS+ profile.","operationId":"create_profile_api_v1_tacacs_profiles_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsProfileCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/profiles/{profile_id}":{"get":{"tags":["TACACS+ Profiles"],"summary":"Get a TACACS+ profile","description":"Get a single TACACS+ profile.\n\nEmbeds the linked template + command-set detail so the editor opens in a single\nrequest (the list endpoint stays lean with briefs only).","operationId":"get_profile_api_v1_tacacs_profiles__profile_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["TACACS+ Profiles"],"summary":"Update a TACACS+ profile","description":"Update a TACACS+ profile. Sentinel logic for enable.password.","operationId":"update_profile_api_v1_tacacs_profiles__profile_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsProfileUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["TACACS+ Profiles"],"summary":"Delete a TACACS+ profile","description":"Delete a TACACS+ profile.","operationId":"delete_profile_api_v1_tacacs_profiles__profile_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/profiles/{profile_id}/enable-secret/reveal":{"get":{"tags":["TACACS+ Profiles"],"summary":"Reveal a TACACS+ profile enable password","description":"Reveal the decrypted enable password for a profile.\n\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets.\nAudit-logged with TACACS_PROFILE_ENABLE_SECRET_REVEALED.\nReturns {\"enable_password\": \"<decrypted>\"} or raises 422 if no password set.","operationId":"reveal_enable_secret_api_v1_tacacs_profiles__profile_id__enable_secret_reveal_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"title":"Response Reveal Enable Secret Api V1 Tacacs Profiles  Profile Id  Enable Secret Reveal Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/profiles/{profile_id}/references":{"get":{"tags":["TACACS+ Profiles"],"summary":"Where this is used (blocking + auto-clearing references)","operationId":"tacacs_profile_references_api_v1_tacacs_profiles__profile_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/profiles/references/counts":{"post":{"tags":["TACACS+ Profiles"],"summary":"Batch reference counts (the Ref column)","operationId":"tacacs_profile_reference_counts_api_v1_tacacs_profiles_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Tacacs Profile Reference Counts Api V1 Tacacs Profiles References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert":{"get":{"tags":["TACACS+ Server Certificate"],"summary":"Get current TACACS+ server certificate","description":"Return the currently active TACACS+ TLS server certificate info.","operationId":"get_current_server_cert_api_v1_tacacs_server_cert_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TacacsServerCertResponse"},{"type":"null"}],"title":"Response Get Current Server Cert Api V1 Tacacs Server Cert Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert/issue":{"post":{"tags":["TACACS+ Server Certificate"],"summary":"Issue TACACS+ server certificate from internal CA","description":"Issue a TACACS+ server certificate signed by an internal CA.","operationId":"issue_from_internal_ca_api_v1_tacacs_server_cert_issue_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsIssueServerCert"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsServerCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert/upload":{"post":{"tags":["TACACS+ Server Certificate"],"summary":"Upload TACACS+ server certificate","description":"Upload a TACACS+ server certificate with private key and optional CA chain.","operationId":"upload_server_cert_api_v1_tacacs_server_cert_upload_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsUploadServerCert"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsServerCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert/self-signed":{"post":{"tags":["TACACS+ Server Certificate"],"summary":"Generate self-signed TACACS+ server certificate","description":"Generate a new self-signed TACACS+ server certificate.","operationId":"generate_self_signed_api_v1_tacacs_server_cert_self_signed_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsGenerateSelfSigned"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsServerCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert/csr":{"post":{"tags":["TACACS+ Server Certificate"],"summary":"Generate CSR for TACACS+ server certificate","description":"Generate a CSR and store the private key for later import.","operationId":"generate_server_csr_api_v1_tacacs_server_cert_csr_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsServerCsrData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsCsrResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert/deploy":{"post":{"tags":["TACACS+ Server Certificate"],"summary":"Deploy TACACS+ server certificate to volume","description":"Deploy the active TACACS+ server certificate to the shared volume.","operationId":"deploy_server_cert_api_v1_tacacs_server_cert_deploy_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Deploy Server Cert Api V1 Tacacs Server Cert Deploy Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/server-cert/expiry":{"get":{"tags":["TACACS+ Server Certificate"],"summary":"Get TACACS+ server certificate expiry info","description":"Return TACACS+ server certificate expiry status.","operationId":"get_server_cert_expiry_api_v1_tacacs_server_cert_expiry_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsServerCertExpiryInfo"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/templates":{"get":{"tags":["TACACS+ Templates"],"summary":"List TACACS+ templates","description":"List TACACS+ templates with pagination and filtering.","operationId":"list_templates_api_v1_tacacs_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, vendor, platform, description","title":"Search"},"description":"Search name, vendor, platform, description"},{"name":"vendor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by vendor","title":"Vendor"},"description":"Filter by vendor"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, vendor, platform, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, vendor, platform, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TacacsTemplateListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["TACACS+ Templates"],"summary":"Create a TACACS+ template","description":"Create a new TACACS+ template from JSON payload.","operationId":"create_template_api_v1_tacacs_templates_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsTemplateCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/templates/{template_id}":{"get":{"tags":["TACACS+ Templates"],"summary":"Get a TACACS+ template","description":"Get a single TACACS+ template.","operationId":"get_template_api_v1_tacacs_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["TACACS+ Templates"],"summary":"Update a TACACS+ template","description":"Update a TACACS+ template.","operationId":"update_template_api_v1_tacacs_templates__template_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsTemplateUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["TACACS+ Templates"],"summary":"Delete a TACACS+ template","description":"Delete a TACACS+ template. Fails if referenced by any profile.","operationId":"delete_template_api_v1_tacacs_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/templates/upload":{"post":{"tags":["TACACS+ Templates"],"summary":"Upload a TACACS+ template (YAML)","description":"Upload a YAML file to create a TACACS+ template.\n\nThe YAML must contain: name, vendor, data (with services[]).\nOptional: platform, description.","operationId":"upload_template_api_v1_tacacs_templates_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_template_api_v1_tacacs_templates_upload_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TacacsTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/tacacs/templates/{template_id}/references":{"get":{"tags":["TACACS+ Templates"],"summary":"Where this is used (blocking + auto-clearing references)","operationId":"tacacs_template_references_api_v1_tacacs_templates__template_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/tacacs/templates/references/counts":{"post":{"tags":["TACACS+ Templates"],"summary":"Batch reference counts (the Ref column)","operationId":"tacacs_template_reference_counts_api_v1_tacacs_templates_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Tacacs Template Reference Counts Api V1 Tacacs Templates References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/alerts":{"get":{"tags":["Alerts"],"summary":"List alerts","description":"List alerts with filters, pagination, and sorting.\n\nDefault ordering (no ``sort_by``) is most-severe-first, then most recent.","operationId":"list_alerts_api_v1_alerts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(firing|resolved)$"},{"type":"null"}],"description":"Lifecycle state","title":"Status"},"description":"Lifecycle state"},{"name":"severity","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(info|warning|error|critical)$"},{"type":"null"}],"description":"Filter by severity","title":"Severity"},"description":"Filter by severity"},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Originating subsystem","title":"Source"},"description":"Originating subsystem"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that observed the alert (HA)","title":"Node Id"},"description":"Filter by cluster node that observed the alert (HA)"},{"name":"acknowledged","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by acknowledgement","title":"Acknowledged"},"description":"Filter by acknowledgement"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Match title/message/source/fingerprint","title":"Search"},"description":"Match title/message/source/fingerprint"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(asc|desc)$"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/stats":{"get":{"tags":["Alerts"],"summary":"Get alert statistics","description":"Aggregate alert counters (firing/resolved/acknowledged + per-severity).","operationId":"alert_stats_api_v1_alerts_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertStatsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/alerts/{alert_id}":{"get":{"tags":["Alerts"],"summary":"Get an alert","description":"Get a single alert by id.","operationId":"get_alert_api_v1_alerts__alert_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Alerts"],"summary":"Acknowledge an alert","description":"Acknowledge an alert — silences repeat notifications without closing it.","operationId":"acknowledge_alert_api_v1_alerts__alert_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alert Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertAcknowledge"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/alerts/acknowledge-all":{"post":{"tags":["Alerts"],"summary":"Acknowledge all firing alerts","description":"Acknowledge all firing, unacknowledged alerts at once.","operationId":"acknowledge_all_alerts_api_v1_alerts_acknowledge_all_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Acknowledge All Alerts Api V1 Alerts Acknowledge All Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/alerts/{alert_id}/resolve":{"post":{"tags":["Alerts"],"summary":"Resolve an alert","description":"Manually resolve a firing alert (operator decides it is handled).","operationId":"resolve_alert_api_v1_alerts__alert_id__resolve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audit-logs":{"get":{"tags":["Audit Log"],"summary":"List audit log entries","description":"List audit log entries with filtering and pagination.","operationId":"list_audit_logs_api_v1_audit_logs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by event type","title":"Event Type"},"description":"Filter by event type"},{"name":"actor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by actor user ID","title":"Actor Id"},"description":"Filter by actor user ID"},{"name":"target_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by target entity ID","title":"Target Id"},"description":"Filter by target entity ID"},{"name":"target_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by target type","title":"Target Type"},"description":"Filter by target type"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that handled the action (HA)","title":"Node Id"},"description":"Filter by cluster node that handled the action (HA)"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Events from this date","title":"Date From"},"description":"Events from this date"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Events up to this date","title":"Date To"},"description":"Events up to this date"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search actor, event type, target type, or IP","title":"Search"},"description":"Search actor, event type, target type, or IP"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (created_at, event_type, actor_username, target_type)","title":"Sort By"},"description":"Sort field (created_at, event_type, actor_username, target_type)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_AuditLogResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audit-logs/export":{"get":{"tags":["Audit Log"],"summary":"Export audit logs (XLSX/CSV)","description":"Export audit log entries as XLSX or CSV file.\n\nWhen ``page`` and ``per_page`` are provided, exports only that page\n(matching exactly what the user sees on screen).\nWhen omitted, exports ALL matching records.","operationId":"export_audit_logs_api_v1_audit_logs_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number (omit for all records)","title":"Page"},"description":"Page number (omit for all records)"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"description":"Items per page (omit for all records)","title":"Per Page"},"description":"Items per page (omit for all records)"},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by event type","title":"Event Type"},"description":"Filter by event type"},{"name":"actor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by actor user ID","title":"Actor Id"},"description":"Filter by actor user ID"},{"name":"target_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by target entity ID","title":"Target Id"},"description":"Filter by target entity ID"},{"name":"target_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by target type","title":"Target Type"},"description":"Filter by target type"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Events from this date","title":"Date From"},"description":"Events from this date"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Events up to this date","title":"Date To"},"description":"Events up to this date"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search actor, event type, target type, or IP","title":"Search"},"description":"Search actor, event type, target type, or IP"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction","title":"Sort Order"},"description":"Sort direction"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/locales":{"get":{"tags":["Authentication"],"summary":"Get Locales","description":"Public: list the UI locales this deployment offers (no auth required).\n\nDrives the frontend language picker so a locale hidden via the\n``SUPPORTED_LOCALES`` env is hidden in the UI as well.","operationId":"get_locales_api_v1_auth_locales_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SupportedLocalesResponse"}}}}}}},"/api/v1/auth/bootstrap":{"get":{"tags":["Authentication"],"summary":"Get Bootstrap","description":"Public: runtime deployment config for the unauthenticated login page.\n\nThe frontend ships as one static build, so it cannot tell at build time\nwhether it is running on a dev, demo, or prod stand. This endpoint is the\nsingle runtime source of truth for that (``APP_ENV``), replacing the old\nbuild-time ``import.meta.env.DEV`` heuristic.\n\n``login_hint`` carries pre-fill credentials only on non-production stands:\nthe admin creds from env in development, the published demo creds in demo.\nIn production it is always ``None`` — we never serve credentials to an\nunauthenticated client. (A guard test pins this.)","operationId":"get_bootstrap_api_v1_auth_bootstrap_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BootstrapResponse"}}}}}}},"/api/v1/auth/login":{"post":{"tags":["Authentication"],"summary":"Authenticate a user","description":"Full authentication flow: credential check, lockout, MFA, JWT issuance.","operationId":"login_api_v1_auth_login_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/altcha/challenge":{"get":{"tags":["Authentication"],"summary":"Issue an ALTCHA proof-of-work challenge","description":"Unauthenticated, rate-limited. The browser solves it client-side and submits the solution as `captcha_token` on login / forgot-password when the server reports `captcha_required`.","operationId":"altcha_challenge_api_v1_auth_altcha_challenge_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Altcha Challenge Api V1 Auth Altcha Challenge Get"}}}}}}},"/api/v1/auth/refresh":{"post":{"tags":["Authentication"],"summary":"Refresh access token","description":"Rotate refresh token and issue a new access + refresh pair.","operationId":"refresh_api_v1_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/me":{"get":{"tags":["Authentication"],"summary":"Get current user profile","description":"Returns profile of the currently authenticated user.","operationId":"get_me_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Me Api V1 Auth Me Get"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["Authentication"],"summary":"Update own profile","description":"Self-service update of the authenticated user's own profile. Not RBAC-gated.","operationId":"update_me_api_v1_auth_me_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfileUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Update Me Api V1 Auth Me Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/me/preferences":{"patch":{"tags":["Authentication"],"summary":"Update own UI preferences","description":"Self-service shallow-merge of the authenticated user's UI preferences (e.g. dashboard widget layout). Not RBAC-gated and not audited.","operationId":"update_my_preferences_api_v1_auth_me_preferences_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreferencesUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Update My Preferences Api V1 Auth Me Preferences Patch"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/logout":{"post":{"tags":["Authentication"],"summary":"Logout / revoke refresh token","description":"Revoke a refresh token.","operationId":"logout_api_v1_auth_logout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/change-password":{"post":{"tags":["Authentication"],"summary":"Change password (authenticated)","description":"Requires current password. Enforces password policy and history.","operationId":"change_password_api_v1_auth_change_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MessageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/forgot-password":{"post":{"tags":["Authentication"],"summary":"Request a password reset link","description":"ALWAYS returns 200 OK. Does not reveal whether the user or email exists.","operationId":"forgot_password_api_v1_auth_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/reset-password/verify":{"get":{"tags":["Authentication"],"summary":"Verify a password reset token","description":"Verify that a password reset token is valid and not expired.","operationId":"verify_reset_token_api_v1_auth_reset_password_verify_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","minLength":1,"title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordVerifyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/reset-password":{"post":{"tags":["Authentication"],"summary":"Reset password using a valid token","description":"Complete password reset using a one-time token.","operationId":"reset_password_api_v1_auth_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/healthz":{"get":{"tags":["Health"],"summary":"Liveness probe","description":"Returns 200 if the application process is running.","operationId":"healthz_healthz_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Healthz Healthz Get"}}}}}}},"/ready":{"get":{"tags":["Health"],"summary":"Readiness probe","description":"Returns 200 with component status if DB and master key are available.","operationId":"ready_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Ready Ready Get"}}}}}}},"/api/v1/admin/crypto/rotate-key":{"post":{"tags":["Crypto"],"summary":"Rotate the master encryption key (KEK) — not available over HTTP","description":"Always answers **501** — KEK rotation is not performed over the API.\n\nThe permission check runs first, so an unauthorized caller still gets 403\nand the endpoint leaks nothing. An authorized caller gets 501 with a\nmessage pointing at the console.\n\nWhy not just do it here: the KEK protects Fernet columns across ~20 tables\n(device/group secrets, the internal CA private keys, NCM credentials, TOTP\nsecrets, the license blob …) plus the ``system_settings`` rows. Rotation\nalso has to rewrite the key file/env on every node and restart the\ntacacs/radius/nac daemons, which read the KEK once at start. A request that\nre-encrypts one table and swaps the in-memory key — which is what this\nendpoint used to do — leaves the installation unbootable and unrecoverable\nwithout a database restore.","operationId":"rotate_key_api_v1_admin_crypto_rotate_key_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateKeyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RotateKeyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ldap/configs/{config_id}/mschapv2":{"get":{"tags":["Domain Membership"],"summary":"Get the MS-CHAPv2 settings of an LDAP configuration","operationId":"get_domain_settings_api_v1_ldap_configs__config_id__mschapv2_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Domain Membership"],"summary":"Update the MS-CHAPv2 settings of an LDAP configuration","description":"Save the settings and deliver the configuration in the same call.\n\nDelivery happens here rather than on the next job tick because an operator\nwho pressed Save expects the sidecar to already have the new realm when they\npress Join a second later.","operationId":"update_domain_settings_api_v1_ldap_configs__config_id__mschapv2_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSettingsUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/mschapv2/status":{"get":{"tags":["Domain Membership"],"summary":"Domain membership status, per node","operationId":"get_domain_status_api_v1_ldap_configs__config_id__mschapv2_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/mschapv2/test":{"post":{"tags":["Domain Membership"],"summary":"Check every precondition domain MS-CHAPv2 depends on","operationId":"test_domain_api_v1_ldap_configs__config_id__mschapv2_test_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/mschapv2/join":{"post":{"tags":["Domain Membership"],"summary":"Join this node to the Active Directory domain","description":"Join with credentials that are used once and never stored.\n\nThe configuration is delivered first: ``net ads join`` reads the realm from\nthe sidecar's ``smb.conf``, so joining before delivering would fail with a\nDNS-shaped error that has nothing to do with DNS.","operationId":"join_domain_api_v1_ldap_configs__config_id__mschapv2_join_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainJoinRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainJoinResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email/smtp":{"get":{"tags":["Email"],"summary":"Get SMTP settings","description":"Get all SMTP settings as a typed document.\n\nPassword field returns sentinel \"••••••••\" when set, empty when not set.\nRequires settings.view permission.","operationId":"get_smtp_settings_api_v1_email_smtp_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmtpSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["Email"],"summary":"Update SMTP settings","description":"Update SMTP settings (partial — only provided fields are saved).\n\nPassword field: sentinel → keep current, empty → clear, other → encrypt+save.\nReturns the full updated document.\nRequires settings.edit permission (admin).","operationId":"update_smtp_settings_api_v1_email_smtp_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmtpSettingsUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmtpSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email/smtp/test-connection":{"post":{"tags":["Email"],"summary":"Test SMTP connection","description":"Test SMTP connection without sending an email.\n\nRequires settings.edit permission (admin).","operationId":"test_smtp_connection_api_v1_email_smtp_test_connection_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTestConnectionResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email/smtp/send-test":{"post":{"tags":["Email"],"summary":"Send a test email","description":"Send a test email to verify SMTP configuration.\n\nRequires settings.edit permission (admin).","operationId":"send_test_email_api_v1_email_smtp_send_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailSendTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email/layout":{"get":{"tags":["Email"],"summary":"Get email layout","description":"Get the current email header, footer, and subject prefix.\n\nReturns defaults if no custom layout has been configured.\nRequires settings.view permission.","operationId":"get_email_layout_api_v1_email_layout_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLayoutResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["Email"],"summary":"Update email layout","description":"Update the email header, footer, and subject prefix.\n\nRequires settings.edit permission (admin).","operationId":"update_email_layout_api_v1_email_layout_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLayoutUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLayoutResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email/layout/preview":{"post":{"tags":["Email"],"summary":"Preview email layout","description":"Render the email layout with sample content for preview.\n\nIf body is provided, uses the provided header/footer.\nOtherwise, uses the currently saved layout.\nRequires settings.view permission.","operationId":"preview_email_layout_api_v1_email_layout_preview_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmailLayoutUpdateRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailLayoutPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email/templates":{"get":{"tags":["Email"],"summary":"List email templates","description":"List all email templates, optionally filtered by language.\n\nRequires settings.view permission.","operationId":"list_templates_api_v1_email_templates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by language code","title":"Lang"},"description":"Filter by language code"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email/templates/{template_type}/{lang}":{"get":{"tags":["Email"],"summary":"Get email template","description":"Get a specific email template by type and language.\n\nRequires settings.view permission.","operationId":"get_template_api_v1_email_templates__template_type___lang__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_type","in":"path","required":true,"schema":{"type":"string","title":"Template Type"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Email"],"summary":"Update email template","description":"Update an email template's content (marks it as custom).\n\nRequires settings.edit permission (admin).","operationId":"update_template_api_v1_email_templates__template_type___lang__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_type","in":"path","required":true,"schema":{"type":"string","title":"Template Type"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email/templates/{template_type}/{lang}/reset":{"post":{"tags":["Email"],"summary":"Reset email template","description":"Reset an email template to its default content.\n\nRequires settings.edit permission (admin).","operationId":"reset_template_api_v1_email_templates__template_type___lang__reset_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_type","in":"path","required":true,"schema":{"type":"string","title":"Template Type"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplateResetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email/templates/{template_type}/{lang}/preview":{"post":{"tags":["Email"],"summary":"Preview email template","description":"Render an email template with sample data for preview.\n\nRequires settings.view permission.","operationId":"preview_template_api_v1_email_templates__template_type___lang__preview_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_type","in":"path","required":true,"schema":{"type":"string","title":"Template Type"}},{"name":"lang","in":"path","required":true,"schema":{"type":"string","title":"Lang"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/EmailTemplatePreviewRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailTemplatePreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups":{"get":{"tags":["Groups"],"summary":"List groups","description":"List groups with pagination.","operationId":"list_groups_api_v1_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search group name","title":"Search"},"description":"Search group name"},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by source (local/ldap)","title":"Source"},"description":"Filter by source (local/ldap)"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, source, is_admins, mfa_required, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, source, is_admins, mfa_required, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_GroupListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Groups"],"summary":"Create a local group","description":"Create a new local group.","operationId":"create_group_api_v1_groups_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_id}":{"get":{"tags":["Groups"],"summary":"Get a group","description":"Get a single group with member list.","operationId":"get_group_api_v1_groups__group_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Groups"],"summary":"Update a group","description":"Update a group.\n\nLDAP groups: only is_admins, mfa_required, rbac_model_id, enable_mode, enable_password editable.","operationId":"update_group_api_v1_groups__group_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Groups"],"summary":"Delete a group","description":"Delete a group. LDAP groups cannot be deleted.","operationId":"delete_group_api_v1_groups__group_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_id}/references":{"get":{"tags":["Groups"],"summary":"Where a group is used (blocking + auto-clearing references)","description":"Itemised references to a group for the delete drawer.","operationId":"group_references_api_v1_groups__group_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/references/counts":{"post":{"tags":["Groups"],"summary":"Batch reference counts for a page of groups (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"group_reference_counts_api_v1_groups_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Group Reference Counts Api V1 Groups References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/groups/{group_id}/members":{"post":{"tags":["Groups"],"summary":"Add users to a group","description":"Add users to a group.","operationId":"add_members_api_v1_groups__group_id__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupMemberAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Groups"],"summary":"Remove users from a group","description":"Remove users from a group.","operationId":"remove_members_api_v1_groups__group_id__members_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupMemberAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/groups/{group_id}/enable-secret/reveal":{"get":{"tags":["Groups"],"summary":"Reveal decrypted enable password for a group","description":"Reveal the decrypted enable password for a group.\n\nOnly returns a value when enable_mode='custom' and a password is set.\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged for security tracking.","operationId":"reveal_enable_password_api_v1_groups__group_id__enable_secret_reveal_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"title":"Response Reveal Enable Password Api V1 Groups  Group Id  Enable Secret Reveal Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs":{"get":{"tags":["LDAP Directory"],"summary":"List LDAP configurations","description":"List all LDAP configurations.","operationId":"list_ldap_configs_api_v1_ldap_configs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/LDAPConfigResponse"},"type":"array","title":"Response List Ldap Configs Api V1 Ldap Configs Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["LDAP Directory"],"summary":"Create an LDAP configuration","description":"Create a new LDAP configuration.","operationId":"create_ldap_config_api_v1_ldap_configs_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPConfigCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ldap/directory-types":{"get":{"tags":["LDAP Directory"],"summary":"Selectable directory types with their capabilities and defaults","description":"The catalog the create flow chooses from.\n\nServed rather than hard-coded in the frontend so the search filters and\nattribute maps that prefill a new configuration have ONE definition. They\nused to exist twice — once as Pydantic field defaults, once as literals in\nthe config form — which is a drift waiting for the first person to fix a\nfilter in only one of them.","operationId":"list_directory_types_api_v1_ldap_directory_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DirectoryTypeResponse"},"type":"array","title":"Response List Directory Types Api V1 Ldap Directory Types Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ldap/adhoc-browse":{"post":{"tags":["LDAP Directory"],"summary":"Browse LDAP directory (ad-hoc connection)","description":"Browse LDAP directory using inline connection parameters (no saved config needed).","operationId":"adhoc_browse_ldap_directory_api_v1_ldap_adhoc_browse_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPAdhocBrowseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ldap/adhoc-search":{"post":{"tags":["LDAP Directory"],"summary":"Search LDAP directory (ad-hoc connection)","description":"Search LDAP directory using inline connection parameters (no saved config needed).","operationId":"adhoc_search_ldap_directory_api_v1_ldap_adhoc_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPAdhocSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ldap/configs/{config_id}":{"get":{"tags":["LDAP Directory"],"summary":"Get an LDAP configuration","description":"Get a single LDAP configuration.","operationId":"get_ldap_config_api_v1_ldap_configs__config_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["LDAP Directory"],"summary":"Update an LDAP configuration","description":"Update an existing LDAP configuration.","operationId":"update_ldap_config_api_v1_ldap_configs__config_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPConfigUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["LDAP Directory"],"summary":"Delete an LDAP configuration (optional cascade)","description":"Delete an LDAP configuration with optional cascade.\n\nThe cascade mode in the request body controls what happens to users and groups\nsynced from this config (e.g. keep or delete them); 'confirm' must be set when the\ncascade would remove dependent records. Destructive — removed data cannot be recovered.","operationId":"delete_ldap_config_api_v1_ldap_configs__config_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/LDAPConfigDeleteRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPConfigDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/{config_id}/test-connection":{"post":{"tags":["LDAP Directory"],"summary":"Test an LDAP connection","description":"Test LDAP connection: check each server, bind, user/group search.","operationId":"test_ldap_connection_api_v1_ldap__config_id__test_connection_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/{config_id}/sync":{"post":{"tags":["LDAP Directory"],"summary":"Trigger an LDAP sync","description":"Trigger a full LDAP synchronization.","operationId":"trigger_ldap_sync_api_v1_ldap__config_id__sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SyncTriggerRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/{config_id}/preview":{"post":{"tags":["LDAP Directory"],"summary":"Preview an LDAP sync (dry run)","description":"Run a dry-run sync and return what would change.","operationId":"preview_ldap_sync_api_v1_ldap__config_id__preview_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/{config_id}/sync-history":{"get":{"tags":["LDAP Directory"],"summary":"Get LDAP sync history","description":"Get paginated sync history for an LDAP configuration.","operationId":"get_sync_history_api_v1_ldap__config_id__sync_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_SyncLogResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/browse":{"post":{"tags":["LDAP Directory"],"summary":"Browse the LDAP directory","description":"Browse the LDAP directory tree with lazy loading.","operationId":"browse_ldap_directory_api_v1_ldap_configs__config_id__browse_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/search-directory":{"post":{"tags":["LDAP Directory"],"summary":"Search the LDAP directory","description":"Search the LDAP directory by name.","operationId":"search_ldap_directory_api_v1_ldap_configs__config_id__search_directory_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPSearchDirectoryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/group-members":{"post":{"tags":["LDAP Directory"],"summary":"Preview members of an LDAP group","description":"Preview members of an LDAP group.","operationId":"get_ldap_group_members_api_v1_ldap_configs__config_id__group_members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPGroupMembersRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPGroupMembersResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/root-dns":{"get":{"tags":["LDAP Directory"],"summary":"Get LDAP root naming contexts","description":"Get root naming contexts from LDAP server.","operationId":"get_ldap_root_dns_api_v1_ldap_configs__config_id__root_dns_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"title":"Response Get Ldap Root Dns Api V1 Ldap Configs  Config Id  Root Dns Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/{config_id}/computer-sync":{"post":{"tags":["LDAP Directory"],"summary":"Trigger an LDAP computer sync","description":"Trigger LDAP computer synchronization for endpoint enrichment.","operationId":"trigger_computer_sync_api_v1_ldap__config_id__computer_sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SyncStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/{config_id}/computer-preview":{"post":{"tags":["LDAP Directory"],"summary":"Preview an LDAP computer sync (dry run)","description":"Run a dry-run computer sync and return what would change.","operationId":"preview_computer_sync_api_v1_ldap__config_id__computer_preview_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComputerSyncPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/computer-browse":{"post":{"tags":["LDAP Directory"],"summary":"Browse LDAP computer objects","description":"Browse OU structure + computer objects for selecting search bases.","operationId":"browse_computers_api_v1_ldap_configs__config_id__computer_browse_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPComputerBrowseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/computer-search":{"post":{"tags":["LDAP Directory"],"summary":"Search LDAP computer objects","description":"Search for computers by name in the LDAP directory.","operationId":"search_computers_api_v1_ldap_configs__config_id__computer_search_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPComputerSearchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LDAPBrowseResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ldap/configs/{config_id}/fetch-crl":{"post":{"tags":["LDAP Directory"],"summary":"Fetch and validate a CRL from a URL","description":"Fetch CRL from URL, validate against CA cert. Returns PEM + info without saving.","operationId":"fetch_crl_from_url_api_v1_ldap_configs__config_id__fetch_crl_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"config_id","in":"path","required":true,"schema":{"type":"string","title":"Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fetch Crl From Url Api V1 Ldap Configs  Config Id  Fetch Crl Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/setup/init":{"post":{"tags":["MFA"],"summary":"Verify setup link and get temporary session","description":"Verify a setup link token and return a temporary access_token.\n\nThe access_token can be used to call /mfa/enroll, /mfa/activate, etc.\nNo authentication required — the setup token itself proves identity.","operationId":"setup_init_api_v1_mfa_setup_init_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Setup Init Api V1 Mfa Setup Init Post"}}}}}}},"/api/v1/mfa/providers":{"get":{"tags":["MFA"],"summary":"List available MFA providers","description":"List all available MFA providers with enabled/health status.","operationId":"list_providers_api_v1_mfa_providers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaProvidersResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/health":{"get":{"tags":["MFA"],"summary":"MFA providers health check (admin)","description":"Run async health checks on all MFA providers. Requires mfa.view permission.","operationId":"mfa_health_api_v1_mfa_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaHealthResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/settings":{"get":{"tags":["MFA"],"summary":"List MFA settings (admin)","description":"Get all global mfa.* settings. Requires mfa.view permission.\n\nEncrypted values are masked as '***'. Internal settings are excluded.\nMirrors GET /settings?prefix=mfa. but gated by the mfa section instead\nof the generic settings section.","operationId":"list_mfa_settings_api_v1_mfa_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SettingResponse"},"type":"array","title":"Response List Mfa Settings Api V1 Mfa Settings Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/settings/{key}":{"put":{"tags":["MFA"],"summary":"Update an MFA setting (admin)","description":"Create or update a global mfa.* setting. Requires mfa.manage permission.\n\nOnly keys with the ``mfa.`` prefix are accepted. Internal settings cannot\nbe modified. Mirrors PUT /settings/{key} but gated by the mfa section.","operationId":"update_mfa_setting_api_v1_mfa_settings__key__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/enroll":{"post":{"tags":["MFA"],"summary":"Start MFA enrollment","description":"Start enrollment for an MFA provider. Returns provider-specific setup data.","operationId":"enroll_api_v1_mfa_enroll_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaEnrollRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaEnrollResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/activate":{"post":{"tags":["MFA"],"summary":"Confirm MFA enrollment","description":"Confirm enrollment by verifying the first code from the authenticator app.","operationId":"activate_api_v1_mfa_activate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaActivateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaActivateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/enroll/resend":{"post":{"tags":["MFA"],"summary":"Resend the Telegram enrollment confirmation push","description":"Re-send the approve/deny enrollment push to the user's linked Telegram chat.","operationId":"resend_enrollment_api_v1_mfa_enroll_resend_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaResendResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/unenroll/{user_mfa_id}":{"delete":{"tags":["MFA"],"summary":"Remove MFA enrollment","description":"Remove an MFA enrollment. Users can remove their own; admins with mfa.edit can remove any.","operationId":"unenroll_api_v1_mfa_unenroll__user_mfa_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_mfa_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Mfa Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaUnenrollResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/status":{"get":{"tags":["MFA"],"summary":"Get own MFA status","description":"Get MFA status and enrolled providers for the current user.","operationId":"get_own_status_api_v1_mfa_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/mfa/challenge":{"post":{"tags":["MFA"],"summary":"Create MFA challenge","description":"Create an MFA challenge during login. No authentication required — mfa_token is proof.","operationId":"create_challenge_api_v1_mfa_challenge_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaChallengeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaChallengeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/verify":{"post":{"tags":["MFA"],"summary":"Verify MFA code during login","description":"Verify an MFA code/push during the login flow. No authentication required.","operationId":"verify_mfa_api_v1_mfa_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaVerifyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/challenge/{challenge_id}/status":{"get":{"tags":["MFA"],"summary":"Get challenge status","description":"Poll the status of a push MFA challenge. No authentication required.","operationId":"get_challenge_status_api_v1_mfa_challenge__challenge_id__status_get","parameters":[{"name":"challenge_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Challenge Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaChallengeStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/push/callback":{"get":{"tags":["MFA"],"summary":"Email push approve/deny callback","description":"Handle approve/deny from an email push link.","operationId":"push_callback_api_v1_mfa_push_callback_get","parameters":[{"name":"secret","in":"query","required":true,"schema":{"type":"string","description":"Challenge secret from the email link","title":"Secret"},"description":"Challenge secret from the email link"},{"name":"action","in":"query","required":true,"schema":{"type":"string","description":"approve or deny","title":"Action"},"description":"approve or deny"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaPushCallbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/push/telegram/callback":{"post":{"tags":["MFA"],"summary":"Telegram webhook callback (embedded mode)","description":"Receive Telegram updates via webhook (embedded webhook mode).\n\nAuthenticates the update against the configured webhook secret and delegates\nto the TelegramEngine for processing.\n\nThe check is driven by the *configuration*, never by what the caller sent:\nan absent ``X-Telegram-Bot-Api-Secret-Token`` header is a rejection, not a\nreason to skip verification. Two more conditions have to hold before an\nupdate is trusted at all:\n\n* the delivery mode must actually be ``webhook`` — ``get_engine()`` returns\n  the singleton whenever the engine runs, polling included, so without this\n  an install that never uses webhooks would still process anything posted\n  here;\n* a webhook secret must be configured — in webhook mode it is mandatory by\n  construction, so \"no secret\" means \"not ready\", not \"open\".","operationId":"telegram_webhook_callback_api_v1_mfa_push_telegram_callback_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Telegram Webhook Callback Api V1 Mfa Push Telegram Callback Post"}}}}}}},"/api/v1/mfa/users/{user_id}/status":{"get":{"tags":["MFA"],"summary":"Get MFA status for a user (admin)","description":"Get MFA status for a user. Requires mfa.view permission.","operationId":"get_user_mfa_status_api_v1_mfa_users__user_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/users/{user_id}/reset":{"delete":{"tags":["MFA"],"summary":"Reset MFA for a user (admin)","description":"Reset all MFA for a user. Requires mfa.edit permission.","operationId":"admin_reset_mfa_api_v1_mfa_users__user_id__reset_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaAdminResetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/users/{user_id}/send-setup-link":{"post":{"tags":["MFA"],"summary":"Send MFA setup link to a user","description":"Send an MFA setup link email to a user. Requires mfa.edit permission.\n\nIf force_reset=true, existing MFA enrollments are removed first.","operationId":"send_setup_link_api_v1_mfa_users__user_id__send_setup_link_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Setup Link Api V1 Mfa Users  User Id  Send Setup Link Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/groups/{group_id}/send-setup-link":{"post":{"tags":["MFA"],"summary":"Send MFA setup links to group members","description":"Send MFA setup link emails to all members of a group. Requires mfa.edit permission.","operationId":"send_group_setup_links_api_v1_mfa_groups__group_id__send_setup_link_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Group Setup Links Api V1 Mfa Groups  Group Id  Send Setup Link Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/users/{user_id}/backup-codes":{"post":{"tags":["MFA"],"summary":"Regenerate backup codes","description":"Regenerate backup codes for a user's TOTP MFA. Requires mfa.edit permission.","operationId":"regenerate_backup_codes_api_v1_mfa_users__user_id__backup_codes_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaBackupCodesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/mfa/internal/challenge":{"post":{"tags":["MFA (Internal)"],"summary":"Create MFA push challenge (internal)","description":"Create a push MFA challenge for a user.\n\nCalled by service containers (TACACS, RADIUS, NAC) after password\nverification. Backend resolves the user's active MFA provider and\nsends a push notification. Returns challenge_id for polling via\nthe existing GET /api/v1/mfa/challenge/{id}/status endpoint.","operationId":"internal_create_challenge_api_v1_mfa_internal_challenge_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaInternalChallengeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaInternalChallengeResponse"}}}},"403":{"description":"Invalid or missing X-Internal-Key"},"404":{"description":"User not found or inactive"},"422":{"description":"MFA not configured for user"},"502":{"description":"MFA provider unavailable"}}}},"/api/v1/mfa/internal/verify":{"post":{"tags":["MFA (Internal)"],"summary":"Verify MFA OTP code (internal)","description":"Verify an OTP code for external MFA providers.\n\nFor providers where OTP verification requires an external service\ncall (Multifactor TOTP via RADIUS, taranac_mfa OTP via REST API).\n\nNOT used for local TOTP (pyotp) — that is handled directly in\nthe service container without network calls.\n\nNOT used for push providers — those use challenge + poll flow.","operationId":"internal_verify_otp_api_v1_mfa_internal_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaInternalVerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MfaInternalVerifyResponse"}}}},"403":{"description":"Invalid or missing X-Internal-Key"},"404":{"description":"User not found or inactive"},"422":{"description":"MFA not configured or provider does not support OTP"},"502":{"description":"MFA provider unavailable"}}}},"/api/v1/monitoring/current":{"get":{"tags":["Monitoring"],"summary":"Get current system metrics","description":"Get the most recent system metrics snapshot.","operationId":"get_current_metrics_api_v1_monitoring_current_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricsSnapshot"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/monitoring/history":{"get":{"tags":["Monitoring"],"summary":"Get metric history","description":"Get metric history for the specified time range.","operationId":"get_metrics_history_api_v1_monitoring_history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"minutes","in":"query","required":false,"schema":{"type":"integer","maximum":1440,"minimum":1,"description":"Number of minutes of history","default":60,"title":"Minutes"},"description":"Number of minutes of history"},{"name":"points","in":"query","required":false,"schema":{"type":"integer","maximum":1440,"minimum":1,"description":"Maximum number of data points","default":60,"title":"Points"},"description":"Maximum number of data points"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/monitoring/process":{"get":{"tags":["Monitoring"],"summary":"Get FastAPI process metrics","description":"Get metrics for the current FastAPI process.","operationId":"get_process_info_api_v1_monitoring_process_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessInfo"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/monitoring/services":{"get":{"tags":["Monitoring"],"summary":"Get AAA service status","description":"Get AAA service status (TACACS+, RADIUS).\n\nChecks service reachability, config file presence,\nand last config validation result.","operationId":"get_service_status_api_v1_monitoring_services_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/rbac/schema":{"get":{"tags":["RBAC"],"summary":"Get the permission schema","description":"Return the full permission schema with all available sections and actions.\n\nUsed by the frontend to render RBAC model editors dynamically.","operationId":"get_permission_schema_api_v1_rbac_schema_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PermissionSchemaResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/rbac/models":{"get":{"tags":["RBAC"],"summary":"List RBAC models","description":"List RBAC models with pagination, search, filtering, and sorting.","operationId":"list_rbac_models_api_v1_rbac_models_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name or description","title":"Search"},"description":"Search name or description"},{"name":"is_system","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by system flag","title":"Is System"},"description":"Filter by system flag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, is_system, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, is_system, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_RBACModelListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["RBAC"],"summary":"Create an RBAC model","description":"Create a new RBAC model.","operationId":"create_rbac_model_api_v1_rbac_models_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RBACModelCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RBACModelResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rbac/models/{model_id}":{"get":{"tags":["RBAC"],"summary":"Get an RBAC model","description":"Get a single RBAC model by ID.","operationId":"get_rbac_model_api_v1_rbac_models__model_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Model Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RBACModelResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["RBAC"],"summary":"Update an RBAC model","description":"Update an existing RBAC model.","operationId":"update_rbac_model_api_v1_rbac_models__model_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Model Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RBACModelUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RBACModelResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["RBAC"],"summary":"Delete an RBAC model","description":"Delete an RBAC model. System models cannot be deleted.","operationId":"delete_rbac_model_api_v1_rbac_models__model_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Model Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rbac/models/{model_id}/references":{"get":{"tags":["RBAC"],"summary":"Where an RBAC model is used (groups it is assigned to)","description":"Itemised references to an RBAC model for the delete drawer.","operationId":"rbac_model_references_api_v1_rbac_models__model_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"model_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Model Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/rbac/models/references/counts":{"post":{"tags":["RBAC"],"summary":"Batch reference counts for a page of RBAC models (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"rbac_model_reference_counts_api_v1_rbac_models_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Rbac Model Reference Counts Api V1 Rbac Models References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/rbac/users/{user_id}/effective":{"get":{"tags":["RBAC"],"summary":"Get a user's effective permissions","description":"Get a user's effective (merged) permissions across all groups.","operationId":"get_effective_permissions_api_v1_rbac_users__user_id__effective_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EffectivePermissionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/settings":{"get":{"tags":["Settings"],"summary":"List global settings","description":"Get all global settings. Encrypted values are masked as '***'.\n\nInternal settings (is_internal=True) are excluded from the response.","operationId":"list_settings_api_v1_settings_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prefix","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by key prefix","title":"Prefix"},"description":"Filter by key prefix"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SettingResponse"},"title":"Response List Settings Api V1 Settings Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/settings/{key}":{"put":{"tags":["Settings"],"summary":"Create or update a global setting","description":"Create or update a global setting.\n\nOnly works for global settings (entity_type=NULL).\nEntity-bound secrets are managed through their respective entity endpoints.\nInternal settings (is_internal=True) cannot be modified via this endpoint.","operationId":"update_setting_api_v1_settings__key__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users":{"get":{"tags":["Users"],"summary":"List users","description":"List users with pagination, search, filtering, and sorting.","operationId":"list_users_api_v1_users_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search username, email, or name","title":"Search"},"description":"Search username, email, or name"},{"name":"is_active","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by active status","title":"Is Active"},"description":"Filter by active status"},{"name":"is_locked","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by locked status","title":"Is Locked"},"description":"Filter by locked status"},{"name":"auth_source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by auth source","title":"Auth Source"},"description":"Filter by auth source"},{"name":"validity_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by account validity: valid, expired, not_yet_valid","title":"Validity Status"},"description":"Filter by account validity: valid, expired, not_yet_valid"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (username, email, first_name, last_name, display_name, is_active, is_locked, auth_source, last_login_at, valid_from, valid_until, created_at, updated_at)","title":"Sort By"},"description":"Sort field (username, email, first_name, last_name, display_name, is_active, is_locked, auth_source, last_login_at, valid_from, valid_until, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_UserListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Users"],"summary":"Create a user","description":"Create a new user.","operationId":"create_user_api_v1_users_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}":{"get":{"tags":["Users"],"summary":"Get a user","description":"Get a single user by ID.","operationId":"get_user_api_v1_users__user_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Users"],"summary":"Update a user","description":"Update an existing user.","operationId":"update_user_api_v1_users__user_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Users"],"summary":"Delete a user","description":"Delete a user. Cannot delete self or LDAP users.","operationId":"delete_user_api_v1_users__user_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}/references":{"get":{"tags":["Users"],"summary":"Where a user is used (blocking + auto-clearing references)","description":"Itemised references to a user for the delete drawer.","operationId":"user_references_api_v1_users__user_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/references/counts":{"post":{"tags":["Users"],"summary":"Batch reference counts for a page of users (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"user_reference_counts_api_v1_users_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response User Reference Counts Api V1 Users References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/{user_id}/lock":{"post":{"tags":["Users"],"summary":"Lock a user account","description":"Lock a user account.","operationId":"lock_user_api_v1_users__user_id__lock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}/unlock":{"post":{"tags":["Users"],"summary":"Unlock a user account","description":"Unlock a user account.","operationId":"unlock_user_api_v1_users__user_id__unlock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}/enable-secret/reveal":{"get":{"tags":["Users"],"summary":"Reveal decrypted enable password for a user","description":"Reveal the decrypted enable password for a user.\n\nOnly returns a value when enable_mode='custom' and a password is set.\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged for security tracking.","operationId":"reveal_enable_password_api_v1_users__user_id__enable_secret_reveal_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"title":"Response Reveal Enable Password Api V1 Users  User Id  Enable Secret Reveal Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/{user_id}/resend-welcome":{"post":{"tags":["Users"],"summary":"Re-send welcome email with a fresh password setup link","description":"Re-send the welcome email with a new password setup link.\n\nUsed when the original email didn't arrive or the invite token expired.\nOnly works for local users with an email address.","operationId":"resend_welcome_email_api_v1_users__user_id__resend_welcome_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Resend Welcome Email Api V1 Users  User Id  Resend Welcome Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/backups/settings":{"get":{"tags":["Backups"],"summary":"Get backup settings","description":"Return the editable backup configuration (schedule, retention, contents).","operationId":"get_backup_settings_api_v1_backups_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["Backups"],"summary":"Update backup settings","description":"Apply a partial update to the backup configuration.","operationId":"update_backup_settings_api_v1_backups_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/backups":{"get":{"tags":["Backups"],"summary":"List backup archives","description":"List configuration archives currently in storage (newest first).","operationId":"list_backups_api_v1_backups_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupListResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Backups"],"summary":"Create a backup now","description":"Create one configuration archive on demand.","operationId":"create_backup_api_v1_backups_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupItem"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/backups/{filename}/download":{"get":{"tags":["Backups"],"summary":"Download a backup archive","description":"Stream the encrypted archive file to the client.","operationId":"download_backup_api_v1_backups__filename__download_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/backups/{filename}":{"delete":{"tags":["Backups"],"summary":"Delete a backup archive","description":"Delete one configuration archive.","operationId":"delete_backup_api_v1_backups__filename__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"filename","in":"path","required":true,"schema":{"type":"string","title":"Filename"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cluster/status":{"get":{"tags":["Cluster"],"summary":"Cluster nodes + replication health","description":"Per-node role + sync state (from the primary's ``pg_stat_replication``) and license fit.","operationId":"get_status_api_v1_cluster_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/cluster/services":{"get":{"tags":["Cluster"],"summary":"Per-node daemon health (tacacs/radius/nac)","description":"Every active node's local daemon health, replicated via heartbeat (§15.5).\n\nFreshness-guarded: a cell is ``stale`` once its heartbeat ages past the cutoff\n(or Patroni reports the node down), so a dead node never renders healthy.","operationId":"get_services_api_v1_cluster_services_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClusterServicesResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/cluster/join-tokens":{"get":{"tags":["Cluster"],"summary":"List pending join tokens","description":"List outstanding (pending) join tokens — the secret is never returned.","operationId":"list_join_tokens_api_v1_cluster_join_tokens_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinTokenListResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Cluster"],"summary":"Issue a license-gated join token","description":"Issue a one-time join token. Refused (4xx) without an HA license, at the\nnode cap, or for a duplicate node name/host.","operationId":"issue_join_token_api_v1_cluster_join_tokens_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinTokenIssueRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedJoinTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/cluster/join-tokens/{token_id}":{"delete":{"tags":["Cluster"],"summary":"Revoke a join token","description":"Cancel a pending join token so it can never be redeemed.","operationId":"revoke_join_token_api_v1_cluster_join_tokens__token_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Token Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cluster/register":{"post":{"tags":["Cluster"],"summary":"Redeem a join token (token-authenticated)","description":"Register the joining node's roster row by redeeming its join token.\n\n**Not** RBAC-gated: the join secret itself is the credential (a new node has\nno user session). Invalid/used/expired tokens are rejected (4xx).","operationId":"register_node_api_v1_cluster_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterNodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cluster/join-config":{"post":{"tags":["Cluster"],"summary":"Fetch cluster-wide config (token-authenticated)","description":"Return the cluster-wide settings a joining node must adopt, so ha-join can\npopulate its ``.env`` instead of the operator hand-copying them.\n\n**Not** RBAC-gated: the join secret is the credential. Does **not** consume the\ntoken (the node redeems it later, via ``/register``). ``MASTER_KEY`` is never\nreturned — it stays strictly out-of-band.","operationId":"join_config_api_v1_cluster_join_config_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinConfigRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JoinConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/cluster/nodes/{node_id}":{"delete":{"tags":["Cluster"],"summary":"Decommission a node","description":"Soft-delete a roster node (its id is retained forever so old logs resolve).","operationId":"decommission_node_api_v1_cluster_nodes__node_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"node_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Node Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecommissionedNodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collectors":{"get":{"tags":["NCM Collectors"],"summary":"List collectors","description":"List collectors with pagination, filtering and sorting.","operationId":"list_collectors_api_v1_ncm_collectors_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by mode (embedded, standalone)","title":"Mode"},"description":"Filter by mode (embedded, standalone)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status (unknown, online, offline)","title":"Status"},"description":"Filter by status (unknown, online, offline)"},{"name":"is_default","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by default flag","title":"Is Default"},"description":"Filter by default flag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CollectorListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Collectors"],"summary":"Create a collector","description":"Create a collector.","operationId":"create_collector_api_v1_ncm_collectors_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectorCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collectors/{collector_id}":{"get":{"tags":["NCM Collectors"],"summary":"Get a collector","description":"Get a single collector by ID.","operationId":"get_collector_api_v1_ncm_collectors__collector_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collector_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Collector Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Collectors"],"summary":"Update a collector","description":"Update a collector.","operationId":"update_collector_api_v1_ncm_collectors__collector_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collector_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Collector Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectorUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectorResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Collectors"],"summary":"Delete a collector","description":"Delete a collector.","operationId":"delete_collector_api_v1_ncm_collectors__collector_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collector_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Collector Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collectors/{collector_id}/references":{"get":{"tags":["NCM Collectors"],"summary":"Where a collector is used (blocking + auto-clearing references)","description":"Itemised references to a collector for the delete drawer.","operationId":"collector_references_api_v1_ncm_collectors__collector_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collector_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Collector Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collectors/references/counts":{"post":{"tags":["NCM Collectors"],"summary":"Batch reference counts for a page of collectors (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"collector_reference_counts_api_v1_ncm_collectors_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Collector Reference Counts Api V1 Ncm Collectors References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/system-info":{"get":{"tags":["Dashboard"],"summary":"Get system info","description":"Get backend runtime metadata: version, server time, timezone, uptime, migration head.\n\nNot cached — all fields are cheap to compute.","operationId":"get_system_info_api_v1_dashboard_system_info_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SystemInfoResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/aaa-activity":{"get":{"tags":["Dashboard"],"summary":"Get AAA activity chart","description":"Get AAA authentication/authorization activity aggregated by time buckets.\n\n- ``period=24h`` → 1-hour buckets (24 data points)\n- ``period=7d``  → 6-hour buckets (28 data points)","operationId":"get_aaa_activity_api_v1_dashboard_aaa_activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d)$","description":"Time period","default":"24h","title":"Period"},"description":"Time period"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__modules__infra__dashboard__schemas__AaaActivityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/top-failed-auth":{"get":{"tags":["Dashboard"],"summary":"Get top failed authentications","description":"Get top-N users/IPs with the most failed authentications.\n\nCombines TACACS+ and RADIUS failure logs for the given period.","operationId":"get_top_failed_auth_api_v1_dashboard_top_failed_auth_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d)$","description":"Time period","default":"24h","title":"Period"},"description":"Time period"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Number of entries","default":5,"title":"Limit"},"description":"Number of entries"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopFailedAuthResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/nac-summary":{"get":{"tags":["Dashboard"],"summary":"Get NAC summary counters","description":"Get live NAC counters: active sessions (by auth method), endpoints (by status), top VLANs.\n\nNot cached — these are live operational counts behind a 30s widget poll.","operationId":"get_nac_summary_api_v1_dashboard_nac_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSummaryResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/nac-activity":{"get":{"tags":["Dashboard"],"summary":"Get NAC activity chart","description":"Get NAC accept/reject activity aggregated by time buckets.\n\n- ``period=24h`` → 1-hour buckets\n- ``period=7d``  → 6-hour buckets\n\nResults are cached server-side for 5 minutes.","operationId":"get_nac_activity_api_v1_dashboard_nac_activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"period","in":"query","required":false,"schema":{"type":"string","pattern":"^(24h|7d)$","description":"Time period","default":"24h","title":"Period"},"description":"Time period"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacActivityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/guest-summary":{"get":{"tags":["Dashboard"],"summary":"Get guest-session summary","description":"Get captive-portal guest-session counters: active, pending approval, expiring within 24h.\n\nReturns zeros (never an error) when no captive portal is configured.","operationId":"get_guest_summary_api_v1_dashboard_guest_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestSummaryResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/cert-expiry":{"get":{"tags":["Dashboard"],"summary":"List expiring certificates","description":"List certificates expiring within ``days`` (or already expired) across the PKI.\n\nSpans internal CAs, issued certs, the server cert, and trusted CAs. Revoked\ncertificates are excluded; entries are sorted most-urgent first. Cached\nserver-side for 5 minutes per ``days`` horizon.","operationId":"get_cert_expiry_api_v1_dashboard_cert_expiry_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"Expiry horizon in days","default":90,"title":"Days"},"description":"Expiry horizon in days"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CertExpiryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/backup-status":{"get":{"tags":["Dashboard"],"summary":"Get backup status","description":"Get last-archive metadata and schedule state, with a ``stale`` overdue flag.\n\nNot cached — reads the backup settings and scans the archive storage.","operationId":"get_backup_status_api_v1_dashboard_backup_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackupStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/dashboard/recent-changes":{"get":{"tags":["Dashboard"],"summary":"Get recent changes","description":"Get the latest audit-log entries (newest first) for the recent-changes widget.\n\nNot cached — a small ``ORDER BY created_at DESC LIMIT`` over the indexed\n``audit_logs.created_at``.","operationId":"get_recent_changes_api_v1_dashboard_recent_changes_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":20,"minimum":1,"description":"Number of entries","default":8,"title":"Limit"},"description":"Number of entries"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecentChangesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/dashboard/entity-counts":{"get":{"tags":["Dashboard"],"summary":"Get entity counts","description":"Get counts of all major entities (users, groups, devices, etc.).\n\nResults are cached server-side for 5 minutes.","operationId":"get_entity_counts_api_v1_dashboard_entity_counts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EntityCountsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/import-export/network-objects/export":{"get":{"tags":["Import / Export"],"summary":"Export network objects","description":"Download network objects as a JSON/XLSX/CSV file attachment.","operationId":"export_network_objects_api_v1_import_export_network_objects_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"Export format","default":"json"},"description":"Export format"},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated UUIDs to export (all if empty)","title":"Ids"},"description":"Comma-separated UUIDs to export (all if empty)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/network-objects/import":{"post":{"tags":["Import / Export"],"summary":"Import network objects","description":"Bulk-import network objects from an uploaded file.\n\nMaster-data write: creates and/or updates rows per ``mode``. Pass\n``dry_run=true`` to validate without persisting. Returns a per-item summary.","operationId":"import_network_objects_api_v1_import_export_network_objects_import_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"File format","default":"json"},"description":"File format"},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ImportMode","description":"Conflict resolution mode","default":"create_only"},"description":"Conflict resolution mode"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Validate only, no DB writes","default":false,"title":"Dry Run"},"description":"Validate only, no DB writes"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_network_objects_api_v1_import_export_network_objects_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/network-objects/template":{"get":{"tags":["Import / Export"],"summary":"Download network-object import template","description":"Download a blank XLSX template for importing network objects.","operationId":"network_objects_template_api_v1_import_export_network_objects_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/import-export/devices/export":{"get":{"tags":["Import / Export"],"summary":"Export devices","description":"Download devices as a JSON/XLSX/CSV file attachment.\n\nSet ``include_secrets=true`` to embed decrypted TACACS+/RADIUS secrets.","operationId":"export_devices_api_v1_import_export_devices_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"Export format","default":"json"},"description":"Export format"},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated UUIDs to export (all if empty)","title":"Ids"},"description":"Comma-separated UUIDs to export (all if empty)"},{"name":"include_secrets","in":"query","required":false,"schema":{"type":"boolean","description":"Include decrypted TACACS+/RADIUS secrets","default":false,"title":"Include Secrets"},"description":"Include decrypted TACACS+/RADIUS secrets"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/devices/import":{"post":{"tags":["Import / Export"],"summary":"Import devices","description":"Bulk-import devices from an uploaded file.\n\nMaster-data write: creates and/or updates rows per ``mode``. Pass\n``dry_run=true`` to validate without persisting. Returns a per-item summary.","operationId":"import_devices_api_v1_import_export_devices_import_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"File format","default":"json"},"description":"File format"},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ImportMode","description":"Conflict resolution mode","default":"create_only"},"description":"Conflict resolution mode"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Validate only, no DB writes","default":false,"title":"Dry Run"},"description":"Validate only, no DB writes"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_devices_api_v1_import_export_devices_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/devices/template":{"get":{"tags":["Import / Export"],"summary":"Download device import template","description":"Download a blank XLSX template for importing devices.","operationId":"devices_template_api_v1_import_export_devices_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/import-export/device-groups/export":{"get":{"tags":["Import / Export"],"summary":"Export device groups","description":"Download device groups as a JSON/XLSX/CSV file attachment.\n\nSet ``include_secrets=true`` to embed decrypted TACACS+/RADIUS secrets.","operationId":"export_device_groups_api_v1_import_export_device_groups_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"Export format","default":"json"},"description":"Export format"},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated UUIDs to export (all if empty)","title":"Ids"},"description":"Comma-separated UUIDs to export (all if empty)"},{"name":"include_secrets","in":"query","required":false,"schema":{"type":"boolean","description":"Include decrypted TACACS+/RADIUS secrets","default":false,"title":"Include Secrets"},"description":"Include decrypted TACACS+/RADIUS secrets"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/device-groups/import":{"post":{"tags":["Import / Export"],"summary":"Import device groups","description":"Bulk-import device groups from an uploaded file.\n\nMaster-data write: creates and/or updates rows per ``mode``. Pass\n``dry_run=true`` to validate without persisting. Returns a per-item summary.","operationId":"import_device_groups_api_v1_import_export_device_groups_import_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"File format","default":"json"},"description":"File format"},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ImportMode","description":"Conflict resolution mode","default":"create_only"},"description":"Conflict resolution mode"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Validate only, no DB writes","default":false,"title":"Dry Run"},"description":"Validate only, no DB writes"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_device_groups_api_v1_import_export_device_groups_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/device-groups/template":{"get":{"tags":["Import / Export"],"summary":"Download device-group import template","description":"Download a blank XLSX template for importing device groups.","operationId":"device_groups_template_api_v1_import_export_device_groups_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/import-export/users/export":{"get":{"tags":["Import / Export"],"summary":"Export users","description":"Download users as a JSON/XLSX/CSV file attachment.","operationId":"export_users_api_v1_import_export_users_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"Export format","default":"json"},"description":"Export format"},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated UUIDs to export (all if empty)","title":"Ids"},"description":"Comma-separated UUIDs to export (all if empty)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/users/import":{"post":{"tags":["Import / Export"],"summary":"Import users","description":"Bulk-import users from an uploaded file.\n\nMaster-data write: creates and/or updates rows per ``mode``. Pass\n``dry_run=true`` to validate without persisting. Returns a per-item summary.","operationId":"import_users_api_v1_import_export_users_import_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"File format","default":"json"},"description":"File format"},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ImportMode","description":"Conflict resolution mode","default":"create_only"},"description":"Conflict resolution mode"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Validate only, no DB writes","default":false,"title":"Dry Run"},"description":"Validate only, no DB writes"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_users_api_v1_import_export_users_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/users/template":{"get":{"tags":["Import / Export"],"summary":"Download user import template","description":"Download a blank XLSX template for importing users.","operationId":"users_template_api_v1_import_export_users_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/import-export/groups/export":{"get":{"tags":["Import / Export"],"summary":"Export user groups","description":"Download user groups as a JSON/XLSX/CSV file attachment.","operationId":"export_groups_api_v1_import_export_groups_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"Export format","default":"json"},"description":"Export format"},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated UUIDs to export (all if empty)","title":"Ids"},"description":"Comma-separated UUIDs to export (all if empty)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/groups/import":{"post":{"tags":["Import / Export"],"summary":"Import user groups","description":"Bulk-import user groups from an uploaded file.\n\nMaster-data write: creates and/or updates rows per ``mode``. Pass\n``dry_run=true`` to validate without persisting. Returns a per-item summary.","operationId":"import_groups_api_v1_import_export_groups_import_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"$ref":"#/components/schemas/app__modules__infra__import_export__schemas__ExportFormat","description":"File format","default":"json"},"description":"File format"},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ImportMode","description":"Conflict resolution mode","default":"create_only"},"description":"Conflict resolution mode"},{"name":"dry_run","in":"query","required":false,"schema":{"type":"boolean","description":"Validate only, no DB writes","default":false,"title":"Dry Run"},"description":"Validate only, no DB writes"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_import_groups_api_v1_import_export_groups_import_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/import-export/groups/template":{"get":{"tags":["Import / Export"],"summary":"Download user-group import template","description":"Download a blank XLSX template for importing user groups.","operationId":"groups_template_api_v1_import_export_groups_template_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/license/installation-id":{"get":{"tags":["License"],"summary":"Get this installation's immutable identifier","description":"Return the ``installation_id`` to bind a Pro license to this install.","operationId":"get_installation_id_api_v1_license_installation_id_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstallationIdResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/license":{"get":{"tags":["License"],"summary":"Get current licensing status","description":"Return edition, entitlements and support state (Community when unlicensed).","operationId":"get_status_api_v1_license_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["License"],"summary":"Upload a license file","description":"Verify and install a ``.lic``.\n\nRejects (4xx) a malformed/tampered/untrusted file or one bound to a different\ninstallation — nothing invalid is stored.","operationId":"upload_license_api_v1_license_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseUploadRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicenseStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/log-rotation/status":{"get":{"tags":["Log Rotation"],"summary":"Get log-rotation status","description":"Return rotation status for every rotated log/session table.","operationId":"get_log_rotation_status_api_v1_log_rotation_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LogRotationStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/log-rotation/daemon-logs":{"get":{"tags":["Log Rotation"],"summary":"Daemon log files + line cap","description":"Return the per-file line cap and the downloadable daemon log inventory.","operationId":"get_daemon_logs_api_v1_log_rotation_daemon_logs_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DaemonLogsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/log-rotation/daemon-logs/max-lines":{"put":{"tags":["Log Rotation"],"summary":"Set daemon log-file line cap","description":"Persist the per-file line cap; pushes the marker to each daemon config volume.","operationId":"set_daemon_max_lines_api_v1_log_rotation_daemon_logs_max_lines_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DaemonMaxLinesUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DaemonMaxLinesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/log-rotation/daemon-logs/forensic/{group}/{year_month}/files":{"get":{"tags":["Log Rotation"],"summary":"List files in a forensic month bucket","description":"Lazy per-month file listing across every ``log_type`` (traversal-guarded).","operationId":"get_forensic_month_files_api_v1_log_rotation_daemon_logs_forensic__group___year_month__files_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group","in":"path","required":true,"schema":{"type":"string","title":"Group"}},{"name":"year_month","in":"path","required":true,"schema":{"type":"string","title":"Year Month"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForensicMonthFilesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/log-rotation/daemon-logs/forensic/{group}/{year_month}":{"delete":{"tags":["Log Rotation"],"summary":"Delete a forensic month bucket","description":"Manually delete one forensic month (past months only; audited, irreversible).","operationId":"delete_forensic_month_api_v1_log_rotation_daemon_logs_forensic__group___year_month__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group","in":"path","required":true,"schema":{"type":"string","title":"Group"}},{"name":"year_month","in":"path","required":true,"schema":{"type":"string","title":"Year Month"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForensicMonthDeleteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/log-rotation/daemon-logs/download":{"get":{"tags":["Log Rotation"],"summary":"Download a daemon log file","description":"Stream a single daemon ``*.log`` file as an attachment (traversal-guarded).","operationId":"download_daemon_log_api_v1_log_rotation_daemon_logs_download_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group","in":"query","required":true,"schema":{"type":"string","description":"Daemon group: tacacs | radius | nac","title":"Group"},"description":"Daemon group: tacacs | radius | nac"},{"name":"path","in":"query","required":true,"schema":{"type":"string","description":"Log file path relative to the group root","title":"Path"},"description":"Log file path relative to the group root"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sms/settings":{"get":{"tags":["SMS"],"summary":"Get all SMS settings","description":"Return the full SMS settings document.\n\nEncrypted values (``http_api_key``, ``http_api_secret``) are masked.\nRequires ``settings.view`` permission.","operationId":"get_sms_settings_api_v1_sms_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["SMS"],"summary":"Partially update SMS settings","description":"Update only the provided SMS settings; omitted fields are unchanged.\n\nRequires ``settings.edit`` permission.","operationId":"patch_sms_settings_api_v1_sms_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sms/settings/test":{"post":{"tags":["SMS"],"summary":"Send a test SMS","description":"Send a test SMS to verify provider configuration.\n\nReturns the full provider response for debugging.\nRequires ``settings.edit`` permission.","operationId":"test_sms_api_v1_sms_settings_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sms/settings/api-key/reveal":{"get":{"tags":["SMS"],"summary":"Reveal decrypted SMS API key","description":"Reveal the decrypted SMS API key.\n\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged.","operationId":"reveal_api_key_api_v1_sms_settings_api_key_reveal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Response Reveal Api Key Api V1 Sms Settings Api Key Reveal Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sms/settings/api-secret/reveal":{"get":{"tags":["SMS"],"summary":"Reveal decrypted SMS API secret","description":"Reveal the decrypted SMS API secret.\n\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged.","operationId":"reveal_api_secret_api_v1_sms_settings_api_secret_reveal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Response Reveal Api Secret Api V1 Sms Settings Api Secret Reveal Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/update-feed/status":{"get":{"tags":["Update Feed"],"summary":"Get the current update-feed status","description":"Return the persisted last-check state + current version. Never hits the network.","operationId":"get_status_api_v1_update_feed_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFeedStatus"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/update-feed/check":{"post":{"tags":["Update Feed"],"summary":"Check taranac.pro for a newer release now","description":"Force one fetch + verify + persist and return fresh status.\n\nAn explicit per-click pull: runs regardless of the ``update_feed.enabled``\ntoggle (which only governs the *periodic* check), so an operator can check on\ndemand without turning on background polling. A feed that cannot be reached\nyields ``reachable=false`` with a machine ``problem`` code, never an error.","operationId":"check_now_api_v1_update_feed_check_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateFeedStatus"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/workers":{"get":{"tags":["Workers"],"summary":"List background jobs","description":"List all background jobs (live + disabled) with their status.","operationId":"list_workers_api_v1_workers_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/workers/{job_id}/run":{"post":{"tags":["Workers"],"summary":"Run a job now","description":"Manually trigger a job for immediate execution.\n\nOperational action: runs the job's work now, outside its normal schedule.","operationId":"run_worker_api_v1_workers__job_id__run_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","description":"Job identifier","title":"Job Id"},"description":"Job identifier"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workers/{job_id}/pause":{"post":{"tags":["Workers"],"summary":"Pause a job","description":"Pause a scheduled job.","operationId":"pause_worker_api_v1_workers__job_id__pause_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","description":"Job identifier","title":"Job Id"},"description":"Job identifier"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workers/{job_id}/resume":{"post":{"tags":["Workers"],"summary":"Resume a job","description":"Resume a paused job.","operationId":"resume_worker_api_v1_workers__job_id__resume_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","description":"Job identifier","title":"Job Id"},"description":"Job identifier"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workers/{job_id}/interval":{"put":{"tags":["Workers"],"summary":"Change a job's interval","description":"Change the interval for an interval-based job.\n\nProvide exactly one of: seconds, minutes, or hours.","operationId":"update_interval_api_v1_workers__job_id__interval_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntervalUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/workers/{job_id}/enabled":{"patch":{"tags":["Workers"],"summary":"Enable or disable a job","description":"Persistently enable or disable a job (survives restart).","operationId":"set_worker_enabled_api_v1_workers__job_id__enabled_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnabledUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkerJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portal/{slug}":{"get":{"tags":["Captive Portal"],"summary":"Get public portal config (public, no auth)","description":"Get public portal configuration for the guest-facing page.\n\nUnauthenticated — returns only appearance and enabled flows.","operationId":"get_portal_public_api_v1_captive_portal_portal__slug__get","parameters":[{"name":"slug","in":"path","required":true,"schema":{"type":"string","title":"Slug"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortalPublicResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/heartbeat":{"post":{"tags":["Captive Portal"],"summary":"Receive standalone portal heartbeat (token auth)","description":"Receive a heartbeat from a standalone portal container.\n\nAuthenticated via X-Portal-Token header (not JWT).","operationId":"heartbeat_api_v1_captive_portal_heartbeat_post","parameters":[{"name":"x-portal-token","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Portal-Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeartbeatRequest"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portals":{"get":{"tags":["Captive Portal"],"summary":"List captive portals","description":"List captive portals with pagination and filtering.","operationId":"list_portals_api_v1_captive_portal_portals_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search over name and slug","title":"Search"},"description":"Free-text search over name and slug"},{"name":"deployment_mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by deployment mode (embedded, standalone)","title":"Deployment Mode"},"description":"Filter by deployment mode (embedded, standalone)"},{"name":"enabled","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by enabled state","title":"Enabled"},"description":"Filter by enabled state"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by (whitelist-checked)","title":"Sort By"},"description":"Field to sort by (whitelist-checked)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CaptivePortalConfigListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Captive Portal"],"summary":"Create a captive portal","description":"Create a new captive portal with optional inline flows.","operationId":"create_portal_api_v1_captive_portal_portals_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptivePortalConfigCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptivePortalConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portals/{portal_id}":{"get":{"tags":["Captive Portal"],"summary":"Get a captive portal","description":"Get a single portal with flows and health status.","operationId":"get_portal_api_v1_captive_portal_portals__portal_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptivePortalConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Captive Portal"],"summary":"Update a captive portal","description":"Update a portal. Flows use replace-set semantics if provided.","operationId":"update_portal_api_v1_captive_portal_portals__portal_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptivePortalConfigUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaptivePortalConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Captive Portal"],"summary":"Delete a captive portal","description":"Delete a portal. Fails if active guest sessions exist.","operationId":"delete_portal_api_v1_captive_portal_portals__portal_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portals/{portal_id}/generate-token":{"post":{"tags":["Captive Portal"],"summary":"Generate a standalone portal API token","description":"Generate a new API token for a standalone portal.\n\nThe token is shown once in the response and never stored in plaintext.","operationId":"generate_token_api_v1_captive_portal_portals__portal_id__generate_token_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portals/{portal_id}/generate-bundle":{"post":{"tags":["Captive Portal"],"summary":"Download standalone deployment bundle (.tar.gz)","description":"Generate a .tar.gz archive for standalone portal deployment.\n\nContains docker-compose.yml, .env, portal.conf, and README.md\nwith pre-filled settings from the portal configuration.","operationId":"generate_bundle_api_v1_captive_portal_portals__portal_id__generate_bundle_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}},"application/gzip":{}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portals/{portal_id}/instances":{"get":{"tags":["Captive Portal"],"summary":"List portal instances","description":"List all instances of a portal with health status.","operationId":"list_instances_api_v1_captive_portal_portals__portal_id__instances_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CaptivePortalInstanceResponse"},"title":"Response List Instances Api V1 Captive Portal Portals  Portal Id  Instances Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/portals/{portal_id}/instances/{instance_id}":{"delete":{"tags":["Captive Portal"],"summary":"Delete a stale portal instance","description":"Delete a stale portal instance record.","operationId":"delete_instance_api_v1_captive_portal_portals__portal_id__instances__instance_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"portal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Portal Id"}},{"name":"instance_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Instance Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/nginx/preview":{"get":{"tags":["Captive Portal"],"summary":"Preview currently deployed captive portal nginx config","description":"Return the nginx config currently deployed on disk.","operationId":"nginx_preview_api_v1_captive_portal_nginx_preview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Nginx Preview Api V1 Captive Portal Nginx Preview Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/captive-portal/nginx/preview-pending":{"get":{"tags":["Captive Portal"],"summary":"Preview pending captive portal nginx config (rendered from DB)","description":"Render nginx config from current DB state without writing to disk.","operationId":"nginx_preview_pending_api_v1_captive_portal_nginx_preview_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Nginx Preview Pending Api V1 Captive Portal Nginx Preview Pending Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/captive-portal/nginx/apply":{"post":{"tags":["Captive Portal"],"summary":"Generate, write, and reload captive portal nginx config","description":"Full config lifecycle: render → compare → write → signal nginx reload.\n\nRenders the embedded captive-portal nginx config from DB state, writes it\nto the shared volume, and signals the portal nginx to reload. If the config\nhasn't changed since the last deploy, returns ``status=unchanged`` — unless\n``force=true``.","operationId":"nginx_apply_api_v1_captive_portal_nginx_apply_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Force apply even if config hasn't changed","default":false,"title":"Force"},"description":"Force apply even if config hasn't changed"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Nginx Apply Api V1 Captive Portal Nginx Apply Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/nginx/status":{"get":{"tags":["Captive Portal"],"summary":"Get captive portal nginx config deploy status","description":"Return last deploy info plus a desired-vs-applied diff.\n\n``pending=true`` means portal config changed since the last deploy and\nnginx must be re-applied. Reflects the embedded deployment (shared\nvolume); standalone instances report their own state via heartbeat.","operationId":"nginx_status_api_v1_captive_portal_nginx_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Nginx Status Api V1 Captive Portal Nginx Status Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/captive-portal/register":{"post":{"tags":["Captive Portal (Public)"],"summary":"Register a guest session (public, no auth)","description":"Register a guest or self-registration session.\n\nUnauthenticated — rate limited per IP.","operationId":"register_api_v1_captive_portal_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestRegisterRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestRegisterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/altcha/challenge":{"get":{"tags":["Captive Portal (Public)"],"summary":"Issue an ALTCHA challenge (public, no auth)","description":"Issue an ALTCHA proof-of-work challenge for the public forms.\n\nUnauthenticated — rate limited per IP. The widget solves it client-side\nand submits the solution as ``captcha_token`` on register / byod-register.","operationId":"altcha_challenge_api_v1_captive_portal_altcha_challenge_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Altcha Challenge Api V1 Captive Portal Altcha Challenge Get"}}}}}}},"/api/v1/captive-portal/status/{token}":{"get":{"tags":["Captive Portal (Public)"],"summary":"Poll guest session status (public, no auth)","description":"Check the status of a guest session (polling for sponsor wait).\n\nUnauthenticated — rate limited per IP.","operationId":"check_status_api_v1_captive_portal_status__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/verify/{token}":{"post":{"tags":["Captive Portal (Public)"],"summary":"Submit a verification code (public, no auth)","description":"Submit a verification code.\n\nUnauthenticated — attempt-limited per token (max 5).","operationId":"verify_code_api_v1_captive_portal_verify__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyCodeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyCodeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/resend/{token}":{"post":{"tags":["Captive Portal (Public)"],"summary":"Resend a verification code (public, no auth)","description":"Resend verification code. Rate limited to 1 per minute per token.\n\nUnauthenticated.","operationId":"resend_code_api_v1_captive_portal_resend__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/cancel/{token}":{"post":{"tags":["Captive Portal (Public)"],"summary":"Cancel a pending session (public, no auth)","description":"Cancel a pending verification session so the guest can re-register.\n\nUnauthenticated — session token serves as authentication.","operationId":"cancel_session_api_v1_captive_portal_cancel__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Session Api V1 Captive Portal Cancel  Token  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/byod-register":{"post":{"tags":["Captive Portal (Public)"],"summary":"Register a BYOD device (public, no auth)","description":"BYOD device registration — authenticate existing user and bind device.\n\nUnauthenticated (credentials in body) — rate limited per IP.","operationId":"byod_register_api_v1_captive_portal_byod_register_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ByodRegisterRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ByodRegisterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/byod-mfa-verify":{"post":{"tags":["Captive Portal (Public)"],"summary":"Verify BYOD second factor (public, no auth)","description":"Verify the BYOD second factor and finalize device registration.\n\nUnauthenticated — the byod_mfa token (issued by /byod-register) is proof of\nthe password step. Rate limited per IP.","operationId":"byod_mfa_verify_api_v1_captive_portal_byod_mfa_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ByodMfaVerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ByodRegisterResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/byod-mfa-status/{challenge_id}":{"get":{"tags":["Captive Portal (Public)"],"summary":"Poll BYOD push MFA status (public, no auth)","description":"Poll a BYOD push MFA challenge status.\n\nUnauthenticated — rate limited per IP (mirrors the guest status polling).","operationId":"byod_mfa_status_api_v1_captive_portal_byod_mfa_status__challenge_id__get","parameters":[{"name":"challenge_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Challenge Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ByodMfaStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/aup-accept":{"post":{"tags":["Captive Portal (Public)"],"summary":"Accept the Acceptable Use Policy (public, no auth)","description":"Accept the Acceptable Use Policy.\n\nUnauthenticated — rate limited per IP.","operationId":"aup_accept_api_v1_captive_portal_aup_accept_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AupAcceptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AupAcceptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sponsor/pending":{"get":{"tags":["Captive Portal (Public)"],"summary":"List the sponsor's pending guest requests","description":"List pending sponsor requests for the current user.\n\nAuthenticated — returns sessions where sponsor_email matches\nthe current user's email.","operationId":"sponsor_pending_api_v1_captive_portal_sponsor_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/GuestSessionResponse"},"type":"array","title":"Response Sponsor Pending Api V1 Captive Portal Sponsor Pending Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/captive-portal/sponsor/approve/{token}":{"post":{"tags":["Captive Portal (Public)"],"summary":"Approve a guest session (sponsor)","description":"Approve a pending guest session.\n\nAuthenticated — sponsor must be the user referenced in sponsor_email.","operationId":"sponsor_approve_api_v1_captive_portal_sponsor_approve__token__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sponsor Approve Api V1 Captive Portal Sponsor Approve  Token  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sponsor/reject/{token}":{"post":{"tags":["Captive Portal (Public)"],"summary":"Reject a guest session (sponsor)","description":"Reject a pending guest session.\n\nAuthenticated — sponsor must be the user referenced in sponsor_email.","operationId":"sponsor_reject_api_v1_captive_portal_sponsor_reject__token__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sponsor Reject Api V1 Captive Portal Sponsor Reject  Token  Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sponsor/callback":{"get":{"tags":["Captive Portal (Public)"],"summary":"Sponsor approve/reject via email link (public, no auth)","description":"Process sponsor approve/reject from email callback link.\n\nUnauthenticated — session token (256-bit random) serves as\nauthentication. Rate limited per IP.","operationId":"sponsor_callback_api_v1_captive_portal_sponsor_callback_get","parameters":[{"name":"token","in":"query","required":true,"schema":{"type":"string","description":"Session token from the sponsor email link","title":"Token"},"description":"Session token from the sponsor email link"},{"name":"action","in":"query","required":true,"schema":{"type":"string","pattern":"^(approve|reject)$","description":"Action to take: approve or reject","title":"Action"},"description":"Action to take: approve or reject"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sponsor Callback Api V1 Captive Portal Sponsor Callback Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sessions":{"get":{"tags":["Captive Portal (Public)"],"summary":"List guest sessions","description":"List guest sessions with filtering.\n\nAuthenticated — requires captive_portal_sessions.view permission.","operationId":"list_sessions_api_v1_captive_portal_sessions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Per Page"},"description":"Items per page"},{"name":"portal_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by portal","title":"Portal Id"},"description":"Filter by portal"},{"name":"flow_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by flow type (guest, self_registration, byod, aup)","title":"Flow Type"},"description":"Filter by flow type (guest, self_registration, byod, aup)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by session status","title":"Status"},"description":"Filter by session status"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search over guest identifiers","title":"Search"},"description":"Free-text search over guest identifiers"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_GuestSessionResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sessions/{session_id}":{"get":{"tags":["Captive Portal (Public)"],"summary":"Get a guest session","description":"Get a single guest session detail.\n\nAuthenticated — requires captive_portal_sessions.view permission.","operationId":"get_session_detail_api_v1_captive_portal_sessions__session_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Captive Portal (Public)"],"summary":"Revoke a guest session","description":"Revoke an active guest session.\n\nAuthenticated — requires captive_portal_sessions.manage permission.","operationId":"revoke_session_api_v1_captive_portal_sessions__session_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Body"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sessions/{session_id}/extend":{"post":{"tags":["Captive Portal (Public)"],"summary":"Extend a guest session","description":"Extend an active guest session by N hours.\n\nAuthenticated — requires captive_portal_sessions.manage permission.","operationId":"extend_session_api_v1_captive_portal_sessions__session_id__extend_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sessions/{session_id}/approve":{"post":{"tags":["Captive Portal (Public)"],"summary":"Admin-approve a guest session","description":"Admin approves a pending or pending_verification session.\n\nBypasses verification and sponsor flow — activates the session\nimmediately.  Uses deferred CoA (fires on guest's next poll).\n\nAuthenticated — any logged-in admin user.","operationId":"approve_session_api_v1_captive_portal_sessions__session_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/captive-portal/sessions/{session_id}/reject":{"post":{"tags":["Captive Portal (Public)"],"summary":"Admin-reject a guest session","description":"Admin rejects a pending or pending_verification session.\n\nAuthenticated — any logged-in admin user.","operationId":"reject_session_api_v1_captive_portal_sessions__session_id__reject_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"type":"object","additionalProperties":true},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuestSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups":{"get":{"tags":["Endpoint Groups"],"summary":"List endpoint groups","description":"List endpoint groups with pagination.","operationId":"list_endpoint_groups_api_v1_nac_endpoint_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Per Page"},"description":"Items per page (max 100)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name or description","title":"Search"},"description":"Search name or description"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_EndpointGroupListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Endpoint Groups"],"summary":"Create an endpoint group","description":"Create a new endpoint group.","operationId":"create_endpoint_group_api_v1_nac_endpoint_groups_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/{group_id}":{"get":{"tags":["Endpoint Groups"],"summary":"Get an endpoint group","description":"Get a single endpoint group with classification rules and members preview.\n\nReturns the full group payload including:\n- classification_rules: full list, ordered by created_at asc\n- members_preview: up to 10 most recently assigned members (by assigned_at desc)\n- members_total: total member count\n\nFor the full paginated member list use GET /{group_id}/members.","operationId":"get_endpoint_group_api_v1_nac_endpoint_groups__group_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Endpoint Groups"],"summary":"Update an endpoint group","description":"Update an endpoint group.","operationId":"update_endpoint_group_api_v1_nac_endpoint_groups__group_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Endpoint Groups"],"summary":"Delete an endpoint group","description":"Delete an endpoint group.","operationId":"delete_endpoint_group_api_v1_nac_endpoint_groups__group_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/{group_id}/members":{"get":{"tags":["Endpoint Groups"],"summary":"List endpoint group members","description":"List endpoints in a group (paginated, searchable).","operationId":"get_group_members_api_v1_nac_endpoint_groups__group_id__members_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Per Page"},"description":"Items per page (max 100)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search mac, name, vendor, hostname","title":"Search"},"description":"Search mac, name, vendor, hostname"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_EndpointListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Endpoint Groups"],"summary":"Add members to a group","description":"Add endpoints to a group.","operationId":"add_members_api_v1_nac_endpoint_groups__group_id__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupMemberAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/{group_id}/members/{endpoint_id}":{"delete":{"tags":["Endpoint Groups"],"summary":"Remove a member from a group","description":"Remove an endpoint from a group.","operationId":"remove_member_api_v1_nac_endpoint_groups__group_id__members__endpoint_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/{group_id}/rules":{"get":{"tags":["Endpoint Groups"],"summary":"List classification rules","description":"List classification rules for a group.","operationId":"list_classification_rules_api_v1_nac_endpoint_groups__group_id__rules_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClassificationRuleResponse"},"title":"Response List Classification Rules Api V1 Nac Endpoint Groups  Group Id  Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Endpoint Groups"],"summary":"Create a classification rule","description":"Create a classification rule for a group.","operationId":"create_classification_rule_api_v1_nac_endpoint_groups__group_id__rules_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationRuleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/{group_id}/rules/{rule_id}":{"put":{"tags":["Endpoint Groups"],"summary":"Update a classification rule","description":"Update a classification rule.","operationId":"update_classification_rule_api_v1_nac_endpoint_groups__group_id__rules__rule_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationRuleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Endpoint Groups"],"summary":"Delete a classification rule","description":"Delete a classification rule.","operationId":"delete_classification_rule_api_v1_nac_endpoint_groups__group_id__rules__rule_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}},{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/rules/test":{"post":{"tags":["Endpoint Groups"],"summary":"Test classification rules against a MAC","description":"Test classification: which groups would a MAC be assigned to?\n\nReturns matches grouped by target group (one entry per group, with\nevery rule of that group that fired listed inside). All-matches\nsemantics. Does not update hit_count.","operationId":"test_classification_api_v1_nac_endpoint_groups_rules_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationRuleTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClassificationRuleTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/endpoint-groups/{group_id}/references":{"get":{"tags":["Endpoint Groups"],"summary":"Where an endpoint group is used (blocking + auto-clearing references)","description":"Itemised references to an endpoint group for the delete drawer.","operationId":"endpoint_group_references_api_v1_nac_endpoint_groups__group_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoint-groups/references/counts":{"post":{"tags":["Endpoint Groups"],"summary":"Batch reference counts for a page of endpoint groups (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"endpoint_group_reference_counts_api_v1_nac_endpoint_groups_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Endpoint Group Reference Counts Api V1 Nac Endpoint Groups References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/endpoints":{"get":{"tags":["Endpoints"],"summary":"List endpoints","description":"List endpoints with pagination, filtering, and sorting.","operationId":"list_endpoints_api_v1_nac_endpoints_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Per Page"},"description":"Items per page (max 100)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search MAC, name, vendor, hostname, IP","title":"Search"},"description":"Search MAC, name, vendor, hostname, IP"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status (comma-separated)","title":"Status"},"description":"Filter by status (comma-separated)"},{"name":"persistence_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by persistence type","title":"Persistence Type"},"description":"Filter by persistence type"},{"name":"endpoint_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by group","title":"Endpoint Group Id"},"description":"Filter by group"},{"name":"vendor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by vendor (partial match)","title":"Vendor"},"description":"Filter by vendor (partial match)"},{"name":"discovery_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by discovery type","title":"Discovery Type"},"description":"Filter by discovery type"},{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","description":"Include inactive endpoints","default":false,"title":"Include Inactive"},"description":"Include inactive endpoints"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_EndpointListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Endpoints"],"summary":"Create an endpoint","description":"Create a new endpoint manually.","operationId":"create_endpoint_api_v1_nac_endpoints_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/{endpoint_id}":{"get":{"tags":["Endpoints"],"summary":"Get an endpoint","description":"Get a single endpoint by ID.","operationId":"get_endpoint_api_v1_nac_endpoints__endpoint_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Endpoints"],"summary":"Update an endpoint","description":"Update an endpoint.","operationId":"update_endpoint_api_v1_nac_endpoints__endpoint_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Endpoints"],"summary":"Delete an endpoint","description":"Delete an endpoint.","operationId":"delete_endpoint_api_v1_nac_endpoints__endpoint_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/{endpoint_id}/actions/block":{"post":{"tags":["Endpoints"],"summary":"Block an endpoint","description":"Block an endpoint (status → blocked).","operationId":"block_endpoint_api_v1_nac_endpoints__endpoint_id__actions_block_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/{endpoint_id}/actions/unblock":{"post":{"tags":["Endpoints"],"summary":"Unblock an endpoint","description":"Unblock an endpoint (status → known).","operationId":"unblock_endpoint_api_v1_nac_endpoints__endpoint_id__actions_unblock_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/{endpoint_id}/actions/pin":{"post":{"tags":["Endpoints"],"summary":"Pin an endpoint (make static)","description":"Pin an endpoint (persistence_type → static).","operationId":"pin_endpoint_api_v1_nac_endpoints__endpoint_id__actions_pin_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/{endpoint_id}/actions/unpin":{"post":{"tags":["Endpoints"],"summary":"Unpin an endpoint (make dynamic)","description":"Unpin an endpoint (persistence_type → dynamic).","operationId":"unpin_endpoint_api_v1_nac_endpoints__endpoint_id__actions_unpin_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/{endpoint_id}/actions/reassign":{"post":{"tags":["Endpoints"],"summary":"Reassign an endpoint to groups","description":"Replace an endpoint's group memberships with the given set.","operationId":"reassign_endpoint_api_v1_nac_endpoints__endpoint_id__actions_reassign_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointReassign"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/bulk/delete":{"post":{"tags":["Endpoints"],"summary":"Bulk-delete endpoints","description":"Delete multiple endpoints.","operationId":"bulk_delete_api_v1_nac_endpoints_bulk_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointBulkAction"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Bulk Delete Api V1 Nac Endpoints Bulk Delete Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/endpoints/bulk/block":{"post":{"tags":["Endpoints"],"summary":"Bulk-block endpoints","description":"Block multiple endpoints.","operationId":"bulk_block_api_v1_nac_endpoints_bulk_block_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointBulkAction"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Bulk Block Api V1 Nac Endpoints Bulk Block Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/endpoints/bulk/reassign":{"post":{"tags":["Endpoints"],"summary":"Bulk-reassign endpoints to groups","description":"Replace each selected endpoint's memberships with the given set.","operationId":"bulk_reassign_api_v1_nac_endpoints_bulk_reassign_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointBulkReassign"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Bulk Reassign Api V1 Nac Endpoints Bulk Reassign Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/endpoints/bulk/pin":{"post":{"tags":["Endpoints"],"summary":"Bulk-pin endpoints (make static)","description":"Pin multiple endpoints.","operationId":"bulk_pin_api_v1_nac_endpoints_bulk_pin_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EndpointBulkAction"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"integer"},"type":"object","title":"Response Bulk Pin Api V1 Nac Endpoints Bulk Pin Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/endpoints/{endpoint_id}/references":{"get":{"tags":["Endpoints"],"summary":"Where an endpoint is used (blocking + auto-clearing references)","description":"Itemised references to an endpoint for the delete drawer.","operationId":"endpoint_references_api_v1_nac_endpoints__endpoint_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"endpoint_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Endpoint Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/endpoints/references/counts":{"post":{"tags":["Endpoints"],"summary":"Batch reference counts for a page of endpoints (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"endpoint_reference_counts_api_v1_nac_endpoints_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Endpoint Reference Counts Api V1 Nac Endpoints References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pending-computers":{"get":{"tags":["Pending Computers"],"summary":"List pending AD computers","description":"List pending AD computers with pagination and filters.","operationId":"list_pending_computers_api_v1_nac_pending_computers_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Per Page"},"description":"Items per page (max 100)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search hostname or name","title":"Search"},"description":"Search hostname or name"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: pending, matched, all (default: all)","title":"Status"},"description":"Filter: pending, matched, all (default: all)"},{"name":"ldap_config_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by LDAP config","title":"Ldap Config Id"},"description":"Filter by LDAP config"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_PendingComputerListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/logs/authentication":{"get":{"tags":["NAC Logs"],"summary":"List NAC authentication logs","description":"List NAC authentication log entries.","operationId":"list_nac_auth_api_v1_nac_logs_authentication_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page (max 200)","default":50,"title":"Per Page"},"description":"Items per page (max 200)"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username","title":"Username"},"description":"Filter by username"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: accept, reject, session_stop","title":"Status"},"description":"Filter: accept, reject, session_stop"},{"name":"auth_method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: peap, eap_tls, mab, accounting, unknown","title":"Auth Method"},"description":"Filter: peap, eap_tls, mab, accounting, unknown"},{"name":"endpoint_mac","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exact MAC match (case-insensitive, normalized to upper)","title":"Endpoint Mac"},"description":"Exact MAC match (case-insensitive, normalized to upper)"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Include entries at or after this timestamp (UTC)","title":"Date From"},"description":"Include entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Include entries at or before this timestamp (UTC)","title":"Date To"},"description":"Include entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Partial match across username, nas_ip, endpoint_mac, calling_station_id, device_name","title":"Search"},"description":"Partial match across username, nas_ip, endpoint_mac, calling_station_id, device_name"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (timestamp, username, nas_ip, status, auth_method, endpoint_mac, device_name, rule_order, rule_name, profile_name, reject_reason, vlan_id)","title":"Sort By"},"description":"Sort field (timestamp, username, nas_ip, status, auth_method, endpoint_mac, device_name, rule_order, rule_name, profile_name, reject_reason, vlan_id)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc). Default: desc","title":"Sort Order"},"description":"Sort direction (asc, desc). Default: desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_NacAuthLogListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/logs/authentication/export":{"get":{"tags":["NAC Logs"],"summary":"Export NAC authentication logs","description":"Export NAC authentication logs as XLSX or CSV.\n\n- With ``page`` + ``per_page``: export exactly that page (current view).\n- Without them: export all matching records up to ``_MAX_EXPORT_ROWS``.","operationId":"export_nac_auth_api_v1_nac_logs_authentication_export_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Export format: xlsx or csv","default":"xlsx","title":"Format"},"description":"Export format: xlsx or csv"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Page number; with per_page exports just that page","title":"Page"},"description":"Page number; with per_page exports just that page"},{"name":"per_page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200,"minimum":1},{"type":"null"}],"description":"Items per page; with page exports just that page","title":"Per Page"},"description":"Items per page; with page exports just that page"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username","title":"Username"},"description":"Filter by username"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that processed the entry (HA)","title":"Node Id"},"description":"Filter by cluster node that processed the entry (HA)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: accept, reject, session_stop","title":"Status"},"description":"Filter: accept, reject, session_stop"},{"name":"auth_method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: peap, eap_tls, mab, accounting, unknown","title":"Auth Method"},"description":"Filter: peap, eap_tls, mab, accounting, unknown"},{"name":"endpoint_mac","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exact MAC match (case-insensitive)","title":"Endpoint Mac"},"description":"Exact MAC match (case-insensitive)"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Include entries at or after this timestamp (UTC)","title":"Date From"},"description":"Include entries at or after this timestamp (UTC)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Include entries at or before this timestamp (UTC)","title":"Date To"},"description":"Include entries at or before this timestamp (UTC)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Partial match across username, nas_ip, endpoint_mac, device_name","title":"Search"},"description":"Partial match across username, nas_ip, endpoint_mac, device_name"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/logs/authentication/{log_id}":{"get":{"tags":["NAC Logs"],"summary":"Get a NAC authentication log entry","description":"Get a single NAC authentication log entry.","operationId":"get_nac_auth_api_v1_nac_logs_authentication__log_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"log_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Log Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthLogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/authorization-profiles/vendor-dictionary":{"get":{"tags":["Authorization Profiles"],"summary":"List vendor capabilities","description":"List all vendors from the NAC Vendor Dictionary with capabilities.","operationId":"list_vendors_api_v1_nac_authorization_profiles_vendor_dictionary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VendorDictionaryResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/authorization-profiles":{"get":{"tags":["Authorization Profiles"],"summary":"List authorization profiles","description":"List all authorization profiles with pagination.","operationId":"list_profiles_api_v1_nac_authorization_profiles_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":50,"title":"Per Page"},"description":"Items per page (max 100)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"description":"Search by profile name","title":"Search"},"description":"Search by profile name"},{"name":"vlan_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by assigned VLAN ID (exact match)","title":"Vlan Id"},"description":"Filter by assigned VLAN ID (exact match)"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_NacAuthorizationProfileResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Authorization Profiles"],"summary":"Create an authorization profile","description":"Create a new authorization profile.","operationId":"create_profile_api_v1_nac_authorization_profiles_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthorizationProfileCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthorizationProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/authorization-profiles/{profile_id}":{"get":{"tags":["Authorization Profiles"],"summary":"Get an authorization profile","description":"Get a single authorization profile by ID.","operationId":"get_profile_api_v1_nac_authorization_profiles__profile_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthorizationProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["Authorization Profiles"],"summary":"Update an authorization profile","description":"Update an authorization profile.","operationId":"update_profile_api_v1_nac_authorization_profiles__profile_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthorizationProfileUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthorizationProfileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Authorization Profiles"],"summary":"Delete an authorization profile","description":"Delete an authorization profile. Profiles in use cannot be deleted.","operationId":"delete_profile_api_v1_nac_authorization_profiles__profile_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/authorization-profiles/{profile_id}/preview":{"get":{"tags":["Authorization Profiles"],"summary":"Preview RADIUS attributes per vendor","description":"Preview RADIUS attributes for all vendors in the dictionary.","operationId":"preview_profile_api_v1_nac_authorization_profiles__profile_id__preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacAuthorizationProfilePreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/authorization-profiles/{profile_id}/references":{"get":{"tags":["Authorization Profiles"],"summary":"Where an authorization profile is used (blocking + auto-clearing references)","description":"Itemised references to an authorization profile for the delete drawer.","operationId":"nac_auth_profile_references_api_v1_nac_authorization_profiles__profile_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/authorization-profiles/references/counts":{"post":{"tags":["Authorization Profiles"],"summary":"Batch reference counts for a page of authorization profiles (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"nac_auth_profile_reference_counts_api_v1_nac_authorization_profiles_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Nac Auth Profile Reference Counts Api V1 Nac Authorization Profiles References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/config/preview":{"get":{"tags":["NAC Config"],"summary":"Preview currently deployed NAC FreeRADIUS config","description":"Return the config files currently deployed on disk.","operationId":"preview_nac_config_api_v1_nac_config_preview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacConfigPreviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/config/preview-pending":{"get":{"tags":["NAC Config"],"summary":"Preview pending NAC FreeRADIUS config (rendered from DB)","description":"Render config from current DB state without writing to disk.","operationId":"preview_pending_nac_config_api_v1_nac_config_preview_pending_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacConfigPreviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/config/validate":{"post":{"tags":["NAC Config"],"summary":"Validate generated NAC config (dry-run)","description":"Generate and validate the config without writing or reloading.\n\nRuns ``radiusd -XC`` on the generated config inside the NAC container.\nIf validation fails, the response includes error details with file name,\nline number, and a code snippet around the error line.","operationId":"validate_nac_config_api_v1_nac_config_validate_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacConfigValidateResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/config/reload":{"post":{"tags":["NAC Config"],"summary":"Generate, validate, write, and reload NAC FreeRADIUS config","description":"Full config lifecycle: generate → validate → write → signal reload.\n\nIf the config content hasn't changed since the last deploy, returns\n``status=unchanged`` — unless ``force=true``.","operationId":"reload_nac_config_api_v1_nac_config_reload_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Force reload even if config hasn't changed","default":false,"title":"Force"},"description":"Force reload even if config hasn't changed"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacConfigReloadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/status":{"get":{"tags":["NAC Config"],"summary":"Get NAC FreeRADIUS service status","description":"Get current NAC FreeRADIUS service status.\n\nReturns:\n- Service connectivity (UDP Status-Server check to NAC container)\n- Last config deploy info (timestamp, hash, deployed_by)\n- Last validation result","operationId":"get_nac_status_api_v1_nac_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/policy/rules":{"get":{"tags":["NAC Policy"],"summary":"List NAC policy rules","description":"List all NAC policy rules in evaluation order.\n\nSupports optional filtering by WHO (user group), WHAT (endpoint group),\nWHERE (device group), authorization profile, and auth method. Filters\nacross dimensions are combined with AND; within a dimension rules with\n*_any=True always match. auth_method filter also matches rules with\nauth_method='any'.","operationId":"list_rules_api_v1_nac_policy_rules_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"who_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by user group in WHO","title":"Who Group Id"},"description":"Filter by user group in WHO"},{"name":"what_endpoint_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by endpoint group in WHAT","title":"What Endpoint Group Id"},"description":"Filter by endpoint group in WHAT"},{"name":"where_device_group_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by device group in WHERE","title":"Where Device Group Id"},"description":"Filter by device group in WHERE"},{"name":"authorization_profile_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by authorization profile","title":"Authorization Profile Id"},"description":"Filter by authorization profile"},{"name":"auth_method","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by auth method (peap, eap_tls, mab, etc.)","title":"Auth Method"},"description":"Filter by auth method (peap, eap_tls, mab, etc.)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NacPolicyRuleResponse"},"title":"Response List Rules Api V1 Nac Policy Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NAC Policy"],"summary":"Create a NAC policy rule","description":"Create a new NAC policy rule.","operationId":"create_rule_api_v1_nac_policy_rules_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyRuleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/policy/rules/reorder":{"put":{"tags":["NAC Policy"],"summary":"Reorder NAC policy rules","description":"Atomically reorder all NAC policy rules.","operationId":"reorder_rules_api_v1_nac_policy_rules_reorder_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyReorderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/NacPolicyRuleResponse"},"type":"array","title":"Response Reorder Rules Api V1 Nac Policy Rules Reorder Put"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/policy/rules/{rule_id}":{"get":{"tags":["NAC Policy"],"summary":"Get a NAC policy rule","description":"Get a single NAC policy rule by ID.","operationId":"get_rule_api_v1_nac_policy_rules__rule_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NAC Policy"],"summary":"Update a NAC policy rule","description":"Update a NAC policy rule.","operationId":"update_rule_api_v1_nac_policy_rules__rule_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyRuleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyRuleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NAC Policy"],"summary":"Delete a NAC policy rule","description":"Delete a NAC policy rule. Default rule cannot be deleted.","operationId":"delete_rule_api_v1_nac_policy_rules__rule_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"rule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Rule Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/policy/test":{"post":{"tags":["NAC Policy"],"summary":"Test NAC policy evaluation","description":"Test NAC policy evaluation against simulated request parameters.","operationId":"test_policy_api_v1_nac_policy_test_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPolicyTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/settings":{"get":{"tags":["NAC Settings"],"summary":"Get all NAC settings","description":"Return the full NAC settings document.\n\nEncrypted values (e.g. ``coa_secret``) are masked as ``***``.\nRequires ``nac_settings.view`` permission.","operationId":"get_nac_settings_api_v1_nac_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["NAC Settings"],"summary":"Partially update NAC settings","description":"Update only the provided NAC settings; omitted fields are unchanged.\n\nRequires ``nac_settings.edit`` permission.","operationId":"patch_nac_settings_api_v1_nac_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/settings/coa-secret/reveal":{"get":{"tags":["NAC Settings"],"summary":"Reveal decrypted NAC CoA shared secret","description":"Reveal the decrypted NAC CoA shared secret.\n\nReturns the plaintext value of nac.coa_secret.\nRevealing a real plaintext secret requires `edit` (not just `view`), so a\nview-only viewer — e.g. the public demo — can open the form but never\ndecrypt secrets. Access is audit-logged for security tracking.","operationId":"reveal_coa_secret_api_v1_nac_settings_coa_secret_reveal_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Response Reveal Coa Secret Api V1 Nac Settings Coa Secret Reveal Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/oui/lookup/{mac}":{"get":{"tags":["OUI Database"],"summary":"Look up a MAC vendor","description":"Look up the manufacturer for a MAC address using the OUI database.","operationId":"lookup_vendor_api_v1_nac_oui_lookup__mac__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"mac","in":"path","required":true,"schema":{"type":"string","description":"MAC address to look up the manufacturer for","title":"Mac"},"description":"MAC address to look up the manufacturer for"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuiLookupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/oui/search":{"get":{"tags":["OUI Database"],"summary":"Search OUI records by vendor","description":"Search OUI records by vendor name (legacy paginated list).","operationId":"search_vendors_api_v1_nac_oui_search_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"vendor","in":"query","required":true,"schema":{"type":"string","minLength":2,"description":"Vendor name to search","title":"Vendor"},"description":"Vendor name to search"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Per Page"},"description":"Items per page (max 100)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuiSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/oui/match-preview":{"get":{"tags":["OUI Database"],"summary":"Preview OUI data for rule matching","description":"Paginated OUI data for classification rule match preview.\n\nShape of items depends on match_type:\n  - match_type=vendor_name → rows are unique vendors (grouped, with prefix_count)\n  - match_type=oui_prefix → rows are individual OUI records (bidirectional search)\n\nSame pagination contract as every other table in the app: items, total,\ntotal_by_filter, page, per_page, pages.","operationId":"match_preview_api_v1_nac_oui_match_preview_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"match_type","in":"query","required":true,"schema":{"enum":["vendor_name","oui_prefix"],"type":"string","description":"Classification rule match type","title":"Match Type"},"description":"Classification rule match type"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Optional filter; empty = full list","title":"Search"},"description":"Optional filter; empty = full list"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field. For vendor_name: 'vendor_name' | 'prefix_count'. For oui_prefix: 'oui_prefix' | 'vendor_name'.","title":"Sort By"},"description":"Sort field. For vendor_name: 'vendor_name' | 'prefix_count'. For oui_prefix: 'oui_prefix' | 'vendor_name'."},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"asc | desc","title":"Sort Order"},"description":"asc | desc"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuiMatchPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/oui/stats":{"get":{"tags":["OUI Database"],"summary":"Get OUI database stats","description":"Get OUI database statistics (total vendors, last update time).","operationId":"oui_stats_api_v1_nac_oui_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuiStatsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/oui/update":{"post":{"tags":["OUI Database"],"summary":"Sync the OUI database from IEEE","description":"Manually trigger OUI database update from IEEE.","operationId":"update_oui_database_api_v1_nac_oui_update_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OuiUpdateResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/cas":{"get":{"tags":["NAC PKI"],"summary":"List all internal CAs","description":"Return all internal CAs with hierarchy.","operationId":"list_cas_api_v1_nac_pki_cas_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Cas Api V1 Nac Pki Cas Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["NAC PKI"],"summary":"Create root CA","description":"Create a new root CA (generates key + self-signed certificate).","operationId":"create_root_ca_api_v1_nac_pki_cas_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RootCaCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/cas/{ca_id}/cert":{"get":{"tags":["NAC PKI"],"summary":"Download CA certificate","description":"Download the CA public certificate in PEM format, optionally with full chain.","operationId":"download_ca_cert_api_v1_nac_pki_cas__ca_id__cert_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}},{"name":"include_chain","in":"query","required":false,"schema":{"type":"boolean","description":"Include full chain up to root","default":false,"title":"Include Chain"},"description":"Include full chain up to root"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/cas/intermediate":{"post":{"tags":["NAC PKI"],"summary":"Create intermediate CA","description":"Create a new intermediate CA signed by a parent CA.","operationId":"create_intermediate_ca_api_v1_nac_pki_cas_intermediate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntermediateCaCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/cas/import":{"post":{"tags":["NAC PKI"],"summary":"Import existing CA","description":"Import an existing CA certificate and private key.","operationId":"import_ca_api_v1_nac_pki_cas_import_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ImportCaData"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/cas/{ca_id}":{"get":{"tags":["NAC PKI"],"summary":"Get CA details","description":"Return a single internal CA with computed counts.","operationId":"get_ca_api_v1_nac_pki_cas__ca_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["NAC PKI"],"summary":"Update CA metadata","description":"Update CA metadata (name, description, enabled, CRL/OCSP URLs).","operationId":"update_ca_api_v1_nac_pki_cas__ca_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NAC PKI"],"summary":"Delete CA","description":"Delete a CA, including its key material.\n\nPermitted only if the CA has no active certificates and no child CAs.\nDestructive and irreversible — the stored private key is removed.","operationId":"delete_ca_api_v1_nac_pki_cas__ca_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/cas/{ca_id}/disable":{"post":{"tags":["NAC PKI"],"summary":"Disable CA","description":"Disable a CA (removes from bundle, stops issuance).","operationId":"disable_ca_api_v1_nac_pki_cas__ca_id__disable_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/cas/{ca_id}/crl":{"get":{"tags":["NAC PKI"],"summary":"Download CRL","description":"Download the CRL for a CA in PEM format.","operationId":"get_crl_api_v1_nac_pki_cas__ca_id__crl_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/cas/{ca_id}/crl/regenerate":{"post":{"tags":["NAC PKI"],"summary":"Force CRL regeneration","description":"Force CRL regeneration for a CA.","operationId":"regenerate_crl_api_v1_nac_pki_cas__ca_id__crl_regenerate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Regenerate Crl Api V1 Nac Pki Cas  Ca Id  Crl Regenerate Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates":{"get":{"tags":["NAC PKI"],"summary":"List issued certificates","description":"List issued certificates with filters, search and pagination.","operationId":"list_certificates_api_v1_nac_pki_certificates_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by issuing internal CA","title":"Ca Id"},"description":"Filter by issuing internal CA"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by certificate status (active, revoked, expired)","title":"Status"},"description":"Filter by certificate status (active, revoked, expired)"},{"name":"cert_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by certificate type (e.g. user, device, server)","title":"Cert Type"},"description":"Filter by certificate type (e.g. user, device, server)"},{"name":"linked_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by linked user","title":"Linked User Id"},"description":"Filter by linked user"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Free-text search over name and subject DN","title":"Search"},"description":"Free-text search over name and subject DN"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by (whitelist-checked)","title":"Sort By"},"description":"Field to sort by (whitelist-checked)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Certificates Api V1 Nac Pki Certificates Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NAC PKI"],"summary":"Issue new certificate","description":"Issue a new certificate (generates key + signed cert).","operationId":"issue_certificate_api_v1_nac_pki_certificates_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCertData"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/from-csr":{"post":{"tags":["NAC PKI"],"summary":"Issue certificate from CSR","description":"Issue a certificate from an externally generated CSR.","operationId":"issue_from_csr_api_v1_nac_pki_certificates_from_csr_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCsrData"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/certificates/csr/parse":{"post":{"tags":["NAC PKI"],"summary":"Parse a CSR for preview before signing","description":"Decode a CSR (subject, key, SANs) without issuing anything.","operationId":"parse_csr_api_v1_nac_pki_certificates_csr_parse_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsrParseData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsrParseResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/certificates/{cert_id}":{"get":{"tags":["NAC PKI"],"summary":"Get certificate details","description":"Return a single issued certificate.","operationId":"get_certificate_api_v1_nac_pki_certificates__cert_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NAC PKI"],"summary":"Delete certificate","description":"Delete a revoked or expired certificate. Active certificates must be revoked first.","operationId":"delete_certificate_api_v1_nac_pki_certificates__cert_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/{cert_id}/revoke":{"post":{"tags":["NAC PKI"],"summary":"Revoke certificate","description":"Revoke an issued certificate and regenerate the CRL.\n\nIrreversible: the certificate is permanently marked revoked and added\nto the CA's CRL, which is then regenerated and redeployed.","operationId":"revoke_certificate_api_v1_nac_pki_certificates__cert_id__revoke_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeCertData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/{cert_id}/reassign":{"post":{"tags":["NAC PKI"],"summary":"Reassign device certificate to a user","description":"Reassign a device certificate to a different user, or unlink (set linked_user_id to null).","operationId":"reassign_certificate_api_v1_nac_pki_certificates__cert_id__reassign_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReassignCertData"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/{cert_id}/download":{"get":{"tags":["NAC PKI"],"summary":"Download certificate","description":"Download certificate as P12 or PEM bundle.\n\nBoth formats embed the certificate's decrypted PRIVATE KEY, so this requires\n`edit` (not just `view`): a view-only viewer — e.g. the public demo — can see\ncert metadata but never download real private key material. (The CA cert and\nCRL downloads stay `view`: they are public, key-free.)","operationId":"download_certificate_api_v1_nac_pki_certificates__cert_id__download_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(p12|pem)$","description":"Output format: PKCS#12 (p12) or PEM bundle","default":"p12","title":"Format"},"description":"Output format: PKCS#12 (p12) or PEM bundle"},{"name":"password","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Passphrase to protect the PKCS#12 file (p12 only)","title":"Password"},"description":"Passphrase to protect the PKCS#12 file (p12 only)"},{"name":"include_chain","in":"query","required":false,"schema":{"type":"boolean","description":"Include the full CA chain in the bundle","default":true,"title":"Include Chain"},"description":"Include the full CA chain in the bundle"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/{cert_id}/send-link":{"post":{"tags":["NAC PKI"],"summary":"Send download link for certificate","description":"Create a download token and send email to the certificate's linked user.","operationId":"send_cert_download_link_api_v1_nac_pki_certificates__cert_id__send_link_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Download format: p12 or pem","default":"p12","title":"Format"},"description":"Download format: p12 or pem"},{"name":"p12_password","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Passphrase for the PKCS#12 file (p12 only)","title":"P12 Password"},"description":"Passphrase for the PKCS#12 file (p12 only)"},{"name":"include_chain","in":"query","required":false,"schema":{"type":"boolean","description":"Include the full CA chain in the bundle","default":true,"title":"Include Chain"},"description":"Include the full CA chain in the bundle"}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Cert Download Link Api V1 Nac Pki Certificates  Cert Id  Send Link Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/send-bulk":{"post":{"tags":["NAC PKI"],"summary":"Send download links for multiple certificates","description":"Create download tokens for multiple certificates and send email.","operationId":"send_cert_bulk_links_api_v1_nac_pki_certificates_send_bulk_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"user_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Recipient user whose certificates are bundled","title":"User Id"},"description":"Recipient user whose certificates are bundled"},{"name":"cert_ids","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string","format":"uuid"}},{"type":"null"}],"description":"Certificates to include (defaults to all of the user's)","title":"Cert Ids"},"description":"Certificates to include (defaults to all of the user's)"},{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Download format: p12 or pem","default":"p12","title":"Format"},"description":"Download format: p12 or pem"},{"name":"p12_password","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Passphrase for the PKCS#12 files (p12 only)","title":"P12 Password"},"description":"Passphrase for the PKCS#12 files (p12 only)"},{"name":"include_chain","in":"query","required":false,"schema":{"type":"boolean","description":"Include the full CA chain in each bundle","default":true,"title":"Include Chain"},"description":"Include the full CA chain in each bundle"}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Cert Bulk Links Api V1 Nac Pki Certificates Send Bulk Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/{cert_id}/reissue-and-send":{"post":{"tags":["NAC PKI"],"summary":"Revoke old cert, issue new one, send download link","description":"Re-issue a certificate: revoke the old one, issue a replacement, send a link.\n\nThe old certificate is revoked (added to the CRL), a fresh certificate is\nissued with the same parameters, a one-time download token is created, and\na download link is emailed to the linked user. Requires both edit and\nrevoke permissions.","operationId":"reissue_and_send_api_v1_nac_pki_certificates__cert_id__reissue_and_send_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}},{"name":"revocation_reason","in":"query","required":false,"schema":{"type":"string","description":"CRL revocation reason for the old certificate","default":"superseded","title":"Revocation Reason"},"description":"CRL revocation reason for the old certificate"},{"name":"format","in":"query","required":false,"schema":{"type":"string","description":"Download format for the new certificate: p12 or pem","default":"p12","title":"Format"},"description":"Download format for the new certificate: p12 or pem"},{"name":"p12_password","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Passphrase for the new PKCS#12 file (p12 only)","title":"P12 Password"},"description":"Passphrase for the new PKCS#12 file (p12 only)"}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Reissue And Send Api V1 Nac Pki Certificates  Cert Id  Reissue And Send Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/certificates/{cert_id}/tokens":{"get":{"tags":["NAC PKI"],"summary":"List download tokens for certificate","description":"Return all download tokens for a certificate.","operationId":"list_cert_tokens_api_v1_nac_pki_certificates__cert_id__tokens_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Cert Tokens Api V1 Nac Pki Certificates  Cert Id  Tokens Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/download-tokens/{token_id}":{"delete":{"tags":["NAC PKI"],"summary":"Revoke (delete) a download token","description":"Delete a download token, preventing future use.","operationId":"delete_download_token_api_v1_nac_pki_download_tokens__token_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Token Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/ca-bundle/status":{"get":{"tags":["NAC CA Bundle"],"summary":"CA bundle composition and health","description":"Return CA bundle composition showing all three sources.","operationId":"get_ca_bundle_status_api_v1_nac_ca_bundle_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaBundleStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/trusted-cas":{"get":{"tags":["NAC Trusted CAs"],"summary":"List all trusted CAs","description":"Return all trusted CA entries (PEM content excluded).","operationId":"list_trusted_cas_api_v1_nac_trusted_cas_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response List Trusted Cas Api V1 Nac Trusted Cas Get"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["NAC Trusted CAs"],"summary":"Upload a trusted CA certificate","description":"Create a new trusted CA from a PEM-encoded certificate.\n\nThe PEM content is validated, parsed for metadata (issuer, expiry),\nand encrypted at rest. The CA bundle is regenerated automatically.","operationId":"create_trusted_ca_api_v1_nac_trusted_cas_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacTrustedCaCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacTrustedCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/trusted-cas/{ca_id}":{"get":{"tags":["NAC Trusted CAs"],"summary":"Get a trusted CA by ID","description":"Return a single trusted CA entry (PEM content excluded).","operationId":"get_trusted_ca_api_v1_nac_trusted_cas__ca_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacTrustedCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["NAC Trusted CAs"],"summary":"Update a trusted CA","description":"Update trusted CA metadata (PEM certificate is immutable).","operationId":"update_trusted_ca_api_v1_nac_trusted_cas__ca_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacTrustedCaUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacTrustedCaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NAC Trusted CAs"],"summary":"Delete a trusted CA","description":"Delete a trusted CA. The CA bundle is regenerated automatically.","operationId":"delete_trusted_ca_api_v1_nac_trusted_cas__ca_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/trusted-cas/rebuild-bundle":{"post":{"tags":["NAC Trusted CAs"],"summary":"Force rebuild of the CA bundle","description":"Force regeneration of the combined CA bundle PEM file.\n\nNormally the bundle is rebuilt automatically on CA create/update/delete.\nThis endpoint allows manual rebuild if the file got corrupted.","operationId":"rebuild_ca_bundle_api_v1_nac_trusted_cas_rebuild_bundle_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Rebuild Ca Bundle Api V1 Nac Trusted Cas Rebuild Bundle Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/trusted-cas/{ca_id}/fetch-crl":{"post":{"tags":["NAC Trusted CAs"],"summary":"Fetch CRL from URL and validate against CA cert","description":"Download CRL from URL, validate issuer. Returns PEM + info without saving.","operationId":"fetch_crl_from_url_api_v1_nac_trusted_cas__ca_id__fetch_crl_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Fetch Crl From Url Api V1 Nac Trusted Cas  Ca Id  Fetch Crl Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/server-cert":{"get":{"tags":["NAC Server Certificate"],"summary":"Get current server certificate","description":"Return the currently active server certificate info.","operationId":"get_current_server_cert_api_v1_nac_server_cert_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ServerCertResponse"},{"type":"null"}],"title":"Response Get Current Server Cert Api V1 Nac Server Cert Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/server-cert/issue":{"post":{"tags":["NAC Server Certificate"],"summary":"Issue server certificate from internal CA","description":"Issue a server certificate signed by an internal CA.","operationId":"issue_from_internal_ca_api_v1_nac_server_cert_issue_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueServerCert"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/server-cert/upload":{"post":{"tags":["NAC Server Certificate"],"summary":"Upload server certificate","description":"Upload a server certificate with private key and optional CA chain.","operationId":"upload_server_cert_api_v1_nac_server_cert_upload_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadServerCert"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/server-cert/self-signed":{"post":{"tags":["NAC Server Certificate"],"summary":"Generate self-signed server certificate","description":"Generate a new self-signed server certificate.","operationId":"generate_self_signed_api_v1_nac_server_cert_self_signed_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateSelfSigned"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerCertResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/server-cert/csr":{"post":{"tags":["NAC Server Certificate"],"summary":"Generate CSR for server certificate","description":"Generate a CSR and store the private key for later import.","operationId":"generate_server_csr_api_v1_nac_server_cert_csr_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerCsrData"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsrResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/server-cert/deploy":{"post":{"tags":["NAC Server Certificate"],"summary":"Deploy server certificate to FreeRADIUS","description":"Deploy the active server certificate to FreeRADIUS shared volume.","operationId":"deploy_server_cert_api_v1_nac_server_cert_deploy_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Deploy Server Cert Api V1 Nac Server Cert Deploy Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/server-cert/expiry":{"get":{"tags":["NAC Server Certificate"],"summary":"Get server certificate expiry info","description":"Return server certificate expiry status.","operationId":"get_server_cert_expiry_api_v1_nac_server_cert_expiry_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServerCertExpiryInfo"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/settings":{"get":{"tags":["NAC PKI Settings"],"summary":"Get PKI/EST settings","description":"Return the full PKI/EST settings document.\n\nRequires ``nac_pki.view`` permission.","operationId":"get_pki_settings_api_v1_nac_pki_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPkiSettingsResponse"}}}}},"security":[{"HTTPBearer":[]}]},"patch":{"tags":["NAC PKI Settings"],"summary":"Partially update PKI/EST settings","description":"Update only the provided PKI/EST settings; omitted fields are unchanged.\n\nRequires ``nac_pki.edit`` permission.","operationId":"patch_pki_settings_api_v1_nac_pki_settings_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPkiSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacPkiSettingsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/cert-store/cas":{"get":{"tags":["NAC Certificate Store"],"summary":"List installed CA certificates","description":"Return all CA certificates currently deployed in ca_clients.pem.\n\nParses the concatenated PEM bundle on the shared volume and returns\nmetadata for each certificate. This is what FreeRADIUS uses for\nEAP-TLS client certificate verification.","operationId":"list_installed_cas_api_v1_nac_cert_store_cas_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstalledCasResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/cert-store/crls":{"get":{"tags":["NAC Certificate Store"],"summary":"CRL deployment status","description":"Return CRL deployment status for each CA in the crl/ directory.\n\nFor each CA certificate in the crl/ directory, checks whether\nthe corresponding CRL file exists (via OpenSSL hash symlink).\nWhen CRL checking is enabled, a missing CRL causes FreeRADIUS\nto reject all certificates from that CA.","operationId":"get_crl_status_api_v1_nac_cert_store_crls_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrlStatusResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/cert-store/ca-list":{"get":{"tags":["NAC Certificate Store"],"summary":"Unified CA list for classification rules","description":"Return a unified list of all CAs from Trusted CAs and Internal CAs.\n\nUsed by the classification rule form when match_type=cert_issuer:\nadmin selects a CA from this dropdown, its UUID becomes the\nrule's match_value.\n\nPermission: nac_endpoint_groups.view (same as classification rules).","operationId":"list_ca_objects_api_v1_nac_cert_store_ca_list_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaListResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/pki/est-requests":{"get":{"tags":["NAC PKI"],"summary":"List EST enrollment requests","description":"Return the approval queue, oldest first.","operationId":"list_est_requests_api_v1_nac_pki_est_requests_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status (pending, approved, rejected, expired)","title":"Status"},"description":"Filter by status (pending, approved, rejected, expired)"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response List Est Requests Api V1 Nac Pki Est Requests Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/est-requests/{request_id}":{"get":{"tags":["NAC PKI"],"summary":"Get one EST enrollment request","operationId":"get_est_request_api_v1_nac_pki_est_requests__request_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstEnrollmentRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/est-requests/{request_id}/approve":{"post":{"tags":["NAC PKI"],"summary":"Approve an EST enrollment request","description":"Issue the requested certificate. The client's next poll collects it.","operationId":"approve_est_request_api_v1_nac_pki_est_requests__request_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstEnrollmentRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/pki/est-requests/{request_id}/reject":{"post":{"tags":["NAC PKI"],"summary":"Reject an EST enrollment request","description":"Refuse the request so the client stops polling instead of waiting forever.","operationId":"reject_est_request_api_v1_nac_pki_est_requests__request_id__reject_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstEnrollmentRequestReject"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstEnrollmentRequestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/.well-known/est/cacerts":{"get":{"tags":["EST Enrollment"],"summary":"Get CA certificates (PKCS#7)","description":"Return EST CA certificate(s) as PKCS#7 certs-only.\n\nNo authentication required per RFC 7030 §4.1.","operationId":"est_cacerts__well_known_est_cacerts_get","responses":{"200":{"description":"Successful Response"}}}},"/.well-known/est/simpleenroll":{"post":{"tags":["EST Enrollment"],"summary":"Simple enrollment (CSR → signed certificate)","description":"Submit a CSR and receive a signed certificate.\n\nAuthentication: HTTP Basic or TLS client certificate.\nRequest body: Base64-encoded DER CSR (application/pkcs10).\nResponse: Base64-encoded PKCS#7 with signed cert.","operationId":"est_simpleenroll__well_known_est_simpleenroll_post","responses":{"200":{"description":"Successful Response"}}}},"/.well-known/est/simplereenroll":{"post":{"tags":["EST Enrollment"],"summary":"Simple re-enrollment (certificate renewal)","description":"Re-enroll with an existing client certificate (mutual TLS required).\n\nThe client must present its current certificate via TLS.\nRequest body: Base64-encoded DER CSR (application/pkcs10).\nResponse: Base64-encoded PKCS#7 with renewed cert.","operationId":"est_simplereenroll__well_known_est_simplereenroll_post","responses":{"200":{"description":"Successful Response"}}}},"/.well-known/est/csrattrs":{"get":{"tags":["EST Enrollment"],"summary":"Get recommended CSR attributes","description":"Return recommended CSR attributes for enrollment requests.\n\nNo authentication required per RFC 7030 §4.5.","operationId":"est_csrattrs__well_known_est_csrattrs_get","responses":{"200":{"description":"Successful Response"}}}},"/api/v1/public/cert-download/{token}":{"get":{"tags":["Certificate Download (Public)"],"summary":"Preview certificate info (public, no auth)","description":"Validate token and return certificate metadata.\n\nDoes NOT consume the token — user can preview before downloading.","operationId":"cert_download_info_api_v1_public_cert_download__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Certificate Download (Public)"],"summary":"Download certificate (public, no auth)","description":"Consume token and return the certificate file.\n\nSets used_at, records client IP. Token becomes single-use.","operationId":"cert_download_execute_api_v1_public_cert_download__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/crl/{ca_id}.crl":{"get":{"tags":["CRL Distribution (Public)"],"summary":"Download CA revocation list, DER (public, no auth)","description":"Return the CA's CRL in DER — the encoding network gear expects.","operationId":"get_crl_der_api_v1_public_crl__ca_id__crl_get","parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/crl/{ca_id}.pem":{"get":{"tags":["CRL Distribution (Public)"],"summary":"Download CA revocation list, PEM (public, no auth)","description":"Return the CA's CRL in PEM — convenient for openssl and humans.","operationId":"get_crl_pem_api_v1_public_crl__ca_id__pem_get","parameters":[{"name":"ca_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Ca Id"}}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/est-approval/{token}":{"get":{"tags":["EST Approval (Public)"],"summary":"Preview an enrollment request behind an approval link (public, no auth)","description":"Describe the request this link decides on. Spends nothing.\n\nErrors are returned as a body rather than raised so the page can render\n\"already handled\" or \"link expired\" as a state instead of a crash — the\ncommon case for a second recipient opening the same request.","operationId":"preview_est_approval_api_v1_public_est_approval__token__get","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["EST Approval (Public)"],"summary":"Approve or reject via the emailed link (public, no auth)","description":"Spend the link on a decision. Only this endpoint changes anything.","operationId":"decide_est_approval_api_v1_public_est_approval__token__post","parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstApprovalLinkDecision"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions":{"get":{"tags":["NAC Sessions"],"summary":"List NAC sessions","description":"List NAC sessions with filtering and pagination.\n\n``state`` selects active (default, backward-compatible), closed (history),\nor all (merged).","operationId":"list_sessions_api_v1_nac_sessions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"state","in":"query","required":false,"schema":{"type":"string","pattern":"^(active|closed|all)$","description":"Session set: active, closed, or all","default":"active","title":"State"},"description":"Session set: active, closed, or all"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-based)","default":1,"title":"Page"},"description":"Page number (1-based)"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page (max 200)","default":50,"title":"Per Page"},"description":"Items per page (max 200)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search across MAC, username, NAS IP","title":"Search"},"description":"Search across MAC, username, NAS IP"},{"name":"nas_ip","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by NAS IP address","title":"Nas Ip"},"description":"Filter by NAS IP address"},{"name":"node_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by cluster node that authorized the session (HA)","title":"Node Id"},"description":"Filter by cluster node that authorized the session (HA)"},{"name":"endpoint_mac","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by endpoint MAC","title":"Endpoint Mac"},"description":"Filter by endpoint MAC"},{"name":"username","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by username","title":"Username"},"description":"Filter by username"},{"name":"vlan_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Filter by VLAN ID","title":"Vlan Id"},"description":"Filter by VLAN ID"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Field to sort by","title":"Sort By"},"description":"Field to sort by"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_NacSessionListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}":{"get":{"tags":["NAC Sessions"],"summary":"Get a NAC session","description":"Get a single session by ID (active or closed/history).","operationId":"get_session_detail_api_v1_nac_sessions__session_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSessionDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}/timeline":{"get":{"tags":["NAC Sessions"],"summary":"Get a session lifecycle timeline","description":"Get the lifecycle timeline (start, auth, stop/close) for a session.","operationId":"get_session_timeline_api_v1_nac_sessions__session_id__timeline_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSessionTimelineResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}/coa/disconnect":{"post":{"tags":["NAC Sessions"],"summary":"Disconnect a NAC session (CoA)","description":"Send CoA Disconnect-Request to terminate an active session.\n\nThe NAS will receive a RADIUS Disconnect-Request (RFC 5176) and\nterminate the session. On success, the NAS sends Accounting-Stop\nwhich causes the handler to delete the session row automatically.","operationId":"coa_disconnect_api_v1_nac_sessions__session_id__coa_disconnect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/NacSessionDisconnectRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacCoaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}/coa/reauth":{"post":{"tags":["NAC Sessions"],"summary":"Re-authenticate a NAC session (CoA)","description":"Send CoA-Request to force session re-authentication.\n\nSends Session-Timeout=0 + Termination-Action=RADIUS-Request,\ncausing the NAS to re-initiate 802.1X for the port. The endpoint\ngets a fresh policy evaluation with current rules and groups.","operationId":"coa_reauth_api_v1_nac_sessions__session_id__coa_reauth_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacCoaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}/coa/vlan-change":{"post":{"tags":["NAC Sessions"],"summary":"Change session VLAN (CoA)","description":"Send CoA-Request to change session VLAN without re-authentication.\n\nThe NAS applies new Tunnel attributes dynamically. The session\nrecord updates on the next Accounting Interim-Update from the NAS.","operationId":"coa_vlan_change_api_v1_nac_sessions__session_id__coa_vlan_change_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacCoaVlanChangeRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacCoaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}/coa/bounce-port":{"post":{"tags":["NAC Sessions"],"summary":"Bounce the switch port (CoA, Cisco)","description":"Send CoA-Request to bounce the switch port (Cisco-specific).\n\nSends Cisco-AVPair subscriber:port-bounce. The NAS administratively\nshuts down and re-enables the physical port. Non-Cisco devices\nwill typically respond with CoA-NAK.","operationId":"coa_bounce_port_api_v1_nac_sessions__session_id__coa_bounce_port_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacCoaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/sessions/{session_id}/block-endpoint":{"post":{"tags":["NAC Sessions"],"summary":"Block the session's endpoint","description":"Block the endpoint associated with a session.\n\nFetches the session, resolves the linked endpoint, and blocks it via\n``EndpointService.block_endpoint`` (which preserves validation + audit).\nBlocking tears down all of the endpoint's live sessions via CoA — including\nthis one — so there is no separate \"disconnect\" toggle. CoA is best-effort:\nthe block persists even if a Disconnect fails (failures are logged\nserver-side, not returned here).","operationId":"block_session_endpoint_api_v1_nac_sessions__session_id__block_endpoint_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacSessionBlockEndpointResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/nac/vendor-dictionary":{"get":{"tags":["Vendor Dictionary"],"summary":"List vendor dictionary entries","description":"List all vendors from the dictionary with full detail.","operationId":"list_vendors_api_v1_nac_vendor_dictionary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacVendorDictionaryListResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["Vendor Dictionary"],"summary":"Create a vendor entry","description":"Create a new vendor dictionary entry.","operationId":"create_vendor_api_v1_nac_vendor_dictionary_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacVendorDictionaryCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacVendorDictionaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/nac/vendor-dictionary/{key}":{"get":{"tags":["Vendor Dictionary"],"summary":"Get a vendor entry","description":"Get a single vendor entry by key.","operationId":"get_vendor_api_v1_nac_vendor_dictionary__key__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","description":"Vendor dictionary key","title":"Key"},"description":"Vendor dictionary key"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacVendorDictionaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Vendor Dictionary"],"summary":"Update a vendor entry","description":"Update a vendor dictionary entry (full replace of mutable fields).","operationId":"update_vendor_api_v1_nac_vendor_dictionary__key__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacVendorDictionaryUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NacVendorDictionaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Vendor Dictionary"],"summary":"Delete a vendor entry","description":"Delete a vendor dictionary entry.\n\nBuilt-in vendors and the 'generic' fallback cannot be deleted.","operationId":"delete_vendor_api_v1_nac_vendor_dictionary__key__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","description":"Vendor dictionary key","title":"Key"},"description":"Vendor dictionary key"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/snapshots/{snapshot_id}/aaa-activity":{"get":{"tags":["NCM Tracked Configs"],"summary":"AAA activity in a config-change window (who connected / ran what / accounting)","description":"Return the AAA activity correlated to the tracked device in the change window.\n\nCovers device administration over **both** TACACS+ and RADIUS (each authn/acct row is\ntagged with ``protocol``); the command dimension is TACACS+-only. Window =\n``(previous snapshot.captured_at, this snapshot.captured_at]`` (a bounded 24h lookback\nfor the first snapshot). Best-effort: a config with no addresses or no AAA logs returns\nempty lists, not an error. ``?user=`` filters the three event lists; the ``users`` list\nalways carries the full window's distinct usernames for the filter UI.","operationId":"get_aaa_activity_api_v1_ncm_tracked_configs__tracked_config_id__snapshots__snapshot_id__aaa_activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}},{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}},{"name":"user","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter authn/authz/acct lists to this username","title":"User"},"description":"Filter authn/authz/acct lists to this username"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/app__modules__ncm__aaa_activity__schemas__AaaActivityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/collectors/{collector_id}/enrollment-token":{"post":{"tags":["NCM Collector Gateway"],"summary":"Issue a one-time collector enrollment token","description":"Mint a reveal-once enrollment secret for a standalone collector.\n\nRefused (4xx) if the collector doesn't exist or is not ``standalone``. Any\nprior pending token for the collector is retired.","operationId":"issue_enrollment_token_api_v1_ncm_collector_collectors__collector_id__enrollment_token_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collector_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Collector Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollmentTokenIssueRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssuedEnrollmentTokenResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/collectors/{collector_id}/revoke-identity":{"post":{"tags":["NCM Collector Gateway"],"summary":"Revoke a collector's pinned identity","description":"Withdraw a collector's pinned cert — its next signed request 401s.","operationId":"revoke_identity_api_v1_ncm_collector_collectors__collector_id__revoke_identity_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"collector_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Collector Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevokeIdentityResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/enroll":{"post":{"tags":["NCM Collector Gateway"],"summary":"Redeem an enrollment token (token-authenticated)","description":"Redeem an enrollment token and pin the collector's self-signed cert.\n\n**Not** RBAC-gated: the one-time enrollment secret is the credential (a\ncollector has no user session). Invalid/used/expired tokens and malformed\ncerts are rejected (4xx).","operationId":"enroll_api_v1_ncm_collector_enroll_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrollResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/jobs":{"get":{"tags":["NCM Collector Gateway"],"summary":"Claim the next dispatched collection targets (collector-authenticated)","description":"Held **long-poll**: block until this collector has work, or the hold times out.\n\nSignature-authenticated (:func:`authenticate_collector`). The collector declares\nits snapshot-identity version via ``X-Collector-Snapshot-Version``; a mismatch\nfail-closes (409) and dispatches NOTHING — a version-skewed collector is idled,\nnever handed work it would hash incompatibly.\n\nThe core keeps the request open for up to ``JOBS_LONGPOLL_HOLD_SECONDS``, re-running the\natomic claim every ``JOBS_LONGPOLL_RECHECK_SECONDS`` and returning THE INSTANT a dispatch\n(collect OR preview) appears — push-like pickup latency over the dial-out channel. Returns\n``[]`` on hold-timeout (the collector immediately reopens). The claim/lease/JIT machinery is\nunchanged; long-poll only changes WHEN the claim returns.","operationId":"claim_jobs_api_v1_ncm_collector_jobs_get","parameters":[{"name":"batch_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Batch Size"}},{"name":"X-Collector-Snapshot-Version","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Collector-Snapshot-Version"}},{"name":"X-Collector-Version","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Collector-Version"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/JobPayload"},"title":"Response Claim Jobs Api V1 Ncm Collector Jobs Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/lease/renew":{"post":{"tags":["NCM Collector Gateway"],"summary":"Renew the lease on claimed targets (collector-authenticated)","description":"Extend the claim-lease on the targets a collector is still working.\n\nA slow-but-alive collector calls this mid-collect so its in-flight targets aren't\nre-dispatched to another collector when the lease would otherwise lapse. Only\ntargets still ``claimed`` by THIS collector are renewed; the response lists exactly\nthose, so the collector learns which it still owns.","operationId":"renew_lease_api_v1_ncm_collector_lease_renew_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaseRenewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeaseRenewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/ingest":{"post":{"tags":["NCM Collector Gateway"],"summary":"Ingest a collected result (collector-authenticated)","description":"Ingest a collector's collection outcome for one claimed target.\n\nSignature-authenticated (:func:`authenticate_collector`). The core does NOT trust\nthe payload: it version-gates first, verifies the ``ingest_key`` names a *live* claim\nthis collector holds (else 401), re-scrubs the body with the core's current rules,\nrecomputes attribution + the content hash, clamps ``captured_at``, and threads the\ndispatch's own ``run_id`` / ``ingest_key`` onto the snapshot. Idempotent: a re-POST of\nan already-``done`` key returns the landed result without a second snapshot.","operationId":"ingest_api_v1_ncm_collector_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestPayload"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/collector/preview-result":{"post":{"tags":["NCM Collector Gateway"],"summary":"Submit a routed preview's traced result (collector-authenticated)","description":"Land a collector's traced dry-run for one claimed preview request (persists no history).\n\nSignature-authenticated (:func:`authenticate_collector`). The core version-gates first,\nverifies the ``request_id`` names a *live* claim this collector holds (else 401), re-scrubs\nthe would-be config with the core's current rules, recomputes the content hash + the\n``changed``/``would_be_version`` version delta on the CORE, and assembles the result for the\noperator's poll. A DEVICE failure is a normal preview outcome carried in the trace — not a\ncollector-level error. Idempotent: a re-POST of an already-done request is accepted.","operationId":"submit_preview_result_api_v1_ncm_collector_preview_result_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewJobResultPayload"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewResultAck"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credential-bindings":{"get":{"tags":["NCM Credential Bindings"],"summary":"List bindings","description":"List credential bindings with pagination, filtering and sorting.","operationId":"list_bindings_api_v1_ncm_credential_bindings_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"credential_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by credential","title":"Credential Id"},"description":"Filter by credential"},{"name":"address","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by address","title":"Address"},"description":"Filter by address"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CredentialBindingResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Credential Bindings"],"summary":"Record a binding","description":"Record (upsert) that a credential worked at an address.","operationId":"record_binding_api_v1_ncm_credential_bindings_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialBindingRecord"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialBindingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credential-bindings/{binding_id}":{"get":{"tags":["NCM Credential Bindings"],"summary":"Get a binding","description":"Get a single binding by ID.","operationId":"get_binding_api_v1_ncm_credential_bindings__binding_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"binding_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Binding Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialBindingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Credential Bindings"],"summary":"Delete a binding","description":"Delete a single binding.","operationId":"delete_binding_api_v1_ncm_credential_bindings__binding_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"binding_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Binding Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credential-providers":{"get":{"tags":["NCM Credential Providers"],"summary":"List providers","description":"List credential providers with pagination, filtering and sorting.","operationId":"list_providers_api_v1_ncm_credential_providers_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by provider name","title":"Search"},"description":"Search by provider name"},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by kind","title":"Kind"},"description":"Filter by kind"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CredentialProviderListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Credential Providers"],"summary":"Create a provider","description":"Create a credential provider (seam — no resolver in v1).","operationId":"create_provider_api_v1_ncm_credential_providers_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProviderCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProviderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credential-providers/{provider_id}":{"get":{"tags":["NCM Credential Providers"],"summary":"Get a provider","description":"Get a single provider by ID.","operationId":"get_provider_api_v1_ncm_credential_providers__provider_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProviderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Credential Providers"],"summary":"Update a provider","description":"Update a credential provider.","operationId":"update_provider_api_v1_ncm_credential_providers__provider_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProviderUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialProviderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Credential Providers"],"summary":"Delete a provider","description":"Delete a credential provider.","operationId":"delete_provider_api_v1_ncm_credential_providers__provider_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Provider Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credentials":{"get":{"tags":["NCM Credentials"],"summary":"List credentials","description":"List credentials with pagination, filtering and sorting.","operationId":"list_credentials_api_v1_ncm_credentials_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by credential name","title":"Search"},"description":"Search by credential name"},{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CredentialType"},{"type":"null"}],"description":"Filter by type","title":"Type"},"description":"Filter by type"},{"name":"mode","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CredentialMode"},{"type":"null"}],"description":"Filter by mode","title":"Mode"},"description":"Filter by mode"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CredentialListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Credentials"],"summary":"Create a credential","description":"Create a credential (stored mode only in v1).","operationId":"create_credential_api_v1_ncm_credentials_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credentials/{credential_id}":{"get":{"tags":["NCM Credentials"],"summary":"Get a credential","description":"Get a single credential by ID (secret values masked).","operationId":"get_credential_api_v1_ncm_credentials__credential_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Credential Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Credentials"],"summary":"Update a credential","description":"Update a credential.\n\nSecret fields follow the sentinel convention: send the sentinel to keep a\nstored value, an empty string to clear it, or a new value to re-encrypt.","operationId":"update_credential_api_v1_ncm_credentials__credential_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Credential Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Credentials"],"summary":"Delete a credential","description":"Delete a credential (its address bindings cascade away).","operationId":"delete_credential_api_v1_ncm_credentials__credential_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Credential Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credentials/{credential_id}/secrets":{"get":{"tags":["NCM Credentials"],"summary":"Reveal a credential secret (decrypted, audited)","description":"Reveal a credential's decrypted secret_fields.\n\nRequires the high-privilege ``ncm_credentials.reveal`` action. Access is\naudited (``NCM_CREDENTIAL_SECRET_REVEALED``).","operationId":"reveal_credential_secret_api_v1_ncm_credentials__credential_id__secrets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Credential Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CredentialSecretRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credentials/{credential_id}/references":{"get":{"tags":["NCM Credentials"],"summary":"Where a credential is used (blocking + auto-clearing references)","description":"Itemised references to a credential for the delete drawer.","operationId":"credential_references_api_v1_ncm_credentials__credential_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"credential_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Credential Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/credentials/references/counts":{"post":{"tags":["NCM Credentials"],"summary":"Batch reference counts for a page of credentials (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"credential_reference_counts_api_v1_ncm_credentials_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Credential Reference Counts Api V1 Ncm Credentials References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/onboarding/preview-sample":{"post":{"tags":["NCM Onboarding"],"summary":"Probe a sample of the pool (validate credential/recipe — persists nothing)","description":"Probe 1–10 addresses with the shared header and return per-item reachability.\n\nPersists nothing (each probe runs in a rolled-back savepoint), makes at most ONE\nlogin per address (no retry). Use it to catch a bad shared credential/recipe before\nimporting the whole pool.","operationId":"preview_sample_api_v1_ncm_onboarding_preview_sample_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingSampleRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingSampleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/onboarding/import":{"post":{"tags":["NCM Onboarding"],"summary":"Import an address pool into ready tracked configs (bounded, synchronous)","description":"Create a source + tracked config + address per pool address, probing each once.\n\nDedup-skips already-tracked ``(address, collector, recipe)``; a matching host Device\nonly auto-names the config (no link, never its AAA secret); creates only the\nsuccessful, reporting every item (created / skipped / unreachable / auth_fail / error).","operationId":"import_pool_api_v1_ncm_onboarding_import_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingImportRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingImportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/recipes":{"get":{"tags":["NCM Recipes"],"summary":"List recipes","description":"List recipes with pagination, filtering and sorting.","operationId":"list_recipes_api_v1_ncm_recipes_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by recipe name","title":"Search"},"description":"Search by recipe name"},{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/RecipeKind"},{"type":"null"}],"description":"Filter by kind","title":"Kind"},"description":"Filter by kind"},{"name":"is_system","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by system flag","title":"Is System"},"description":"Filter by system flag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CollectionRecipeListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Recipes"],"summary":"Create a recipe","description":"Create a recipe.","operationId":"create_recipe_api_v1_ncm_recipes_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRecipeCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRecipeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/recipes/{recipe_id}":{"get":{"tags":["NCM Recipes"],"summary":"Get a recipe","description":"Get a single recipe by ID.","operationId":"get_recipe_api_v1_ncm_recipes__recipe_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRecipeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Recipes"],"summary":"Update a recipe","description":"Update a recipe.","operationId":"update_recipe_api_v1_ncm_recipes__recipe_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRecipeUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRecipeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Recipes"],"summary":"Delete a recipe","description":"Delete a recipe (system recipes are protected).","operationId":"delete_recipe_api_v1_ncm_recipes__recipe_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/recipes/{recipe_id}/clone":{"post":{"tags":["NCM Recipes"],"summary":"Clone a recipe","description":"Clone a recipe (system or custom) into a new editable copy.","operationId":"clone_recipe_api_v1_ncm_recipes__recipe_id__clone_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CollectionRecipeClone"},{"type":"null"}],"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRecipeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/recipes/{recipe_id}/references":{"get":{"tags":["NCM Recipes"],"summary":"Where a recipe is used (blocking + auto-clearing references)","description":"Itemised references to a recipe for the delete drawer.","operationId":"recipe_references_api_v1_ncm_recipes__recipe_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Recipe Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/recipes/references/counts":{"post":{"tags":["NCM Recipes"],"summary":"Batch reference counts for a page of recipes (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"recipe_reference_counts_api_v1_ncm_recipes_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Recipe Reference Counts Api V1 Ncm Recipes References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/netmiko-platforms":{"get":{"tags":["NCM Recipes"],"summary":"List netmiko platforms","description":"Return the installed netmiko platforms ({value, label, vendor}) for the driver picker.","operationId":"list_netmiko_platforms_api_v1_ncm_netmiko_platforms_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/NetmikoPlatform"},"type":"array","title":"Response List Netmiko Platforms Api V1 Ncm Netmiko Platforms Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/overview":{"get":{"tags":["NCM Collection Runs"],"summary":"NCM module overview (health tiles + recent changes)","description":"Front-door dashboard: health tiles + the most-recent config-change feed.\n\nA single efficient read (bounded aggregate counters + one joined recent-list\nquery); persists nothing. See ``docs/spec/backend/ncm/overview.md``.","operationId":"get_overview_api_v1_ncm_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/runs":{"get":{"tags":["NCM Collection Runs"],"summary":"List collection runs","description":"List collection runs (most recent first).","operationId":"list_runs_api_v1_ncm_runs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"trigger","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by trigger (scheduled|on_demand)","title":"Trigger"},"description":"Filter by trigger (scheduled|on_demand)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by status (running|completed|interrupted)","title":"Status"},"description":"Filter by status (running|completed|interrupted)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CollectionRunResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/runs/{run_id}":{"get":{"tags":["NCM Collection Runs"],"summary":"Get a collection run","description":"Get a run with its per-target results.","operationId":"get_run_api_v1_ncm_runs__run_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionRunDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/runs/{run_id}/progress":{"get":{"tags":["NCM Collection Runs"],"summary":"Per-collector fan-in progress for a run","description":"Computed per-collector progress (``pending|claimed|done|dead`` buckets + roll-up).\n\nA ``completed`` run means orchestration was handed off, not that every standalone\ncollector finished — this read reconstructs the true fan-in from the dispatch rows\n(standalone) and this run's results (embedded). Reuses the \"NCM Collection Runs\" tag.","operationId":"get_run_progress_api_v1_ncm_runs__run_id__progress_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunProgressResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/collect":{"post":{"tags":["NCM Collection Runs"],"summary":"Collect a tracked config now (on-demand)","description":"Open an on-demand run for one tracked config and collect it now.\n\nAn **embedded** source collects in-process and returns a synchronous\n:class:`CollectNowResponse` (run + result) — unchanged. A **standalone** source (the\ncore can't reach the device directly) is routed to its dial-out collector: this returns\na :class:`CollectNowPendingResponse` (``status='pending'`` with the ``run`` to poll via\n``GET /ncm/runs/{run_id}/progress``, or a fast-fail ``status='error'`` +\n``collector_error='collector_offline'`` if the collector is offline).","operationId":"collect_now_api_v1_ncm_tracked_configs__tracked_config_id__collect_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CollectNowRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CollectNowResponse"},{"$ref":"#/components/schemas/CollectNowPendingResponse"}],"title":"Response Collect Now Api V1 Ncm Tracked Configs  Tracked Config Id  Collect Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/preview":{"post":{"tags":["NCM Collection Runs"],"summary":"Preview a collection (dry-run — persists nothing)","description":"Dry-run the SAME collection as \"Collect now\" and return the would-be config + trace.\n\nPersists nothing (no run/result/snapshot), makes at most ONE device login (never a retry).\nAn **embedded** source is fully synchronous — a full :class:`PreviewResponse` in one call\n(unchanged). A **standalone** source (the core can't reach the device directly) is routed\nto the source's collector over the dial-out channel: this returns a\n:class:`PreviewPendingResponse` with a ``request_id`` to poll (or a fast-fail\n``collector_error='collector_offline'`` if the collector is offline). Gated by\n``ncm_jobs.create`` — like Collect-now it decrypts a credential and performs one real login.\nSee ``docs/spec/backend/ncm/jobs.md``.","operationId":"preview_collection_api_v1_ncm_tracked_configs__tracked_config_id__preview_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PreviewResponse"},{"$ref":"#/components/schemas/PreviewPendingResponse"}],"title":"Response Preview Collection Api V1 Ncm Tracked Configs  Tracked Config Id  Preview Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/runs/preview/{request_id}":{"get":{"tags":["NCM Collection Runs"],"summary":"Poll a routed (standalone) preview by request id","description":"Poll a standalone-routed preview: the assembled result, still-``pending``, or an error.\n\nA collector-routed preview is async: the POST returns a ``request_id`` and the target\ncollector picks it up on its normal ``/jobs`` poll. This read returns the assembled\n:class:`PreviewResponse` once the collector has posted its traced result, or a\n:class:`PreviewPendingResponse` (``pending`` while in flight; ``error`` with a\n``collector_error`` once it lazy-expires — ``collector_offline`` if never polled,\n``preview_timed_out`` if picked up but never finished). Gated by ``ncm_jobs.create`` to\nmatch the preview POST.","operationId":"get_preview_result_api_v1_ncm_runs_preview__request_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PreviewResponse"},{"$ref":"#/components/schemas/PreviewPendingResponse"}],"title":"Response Get Preview Result Api V1 Ncm Runs Preview  Request Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/scrub-sets":{"get":{"tags":["NCM Scrub Rule Sets"],"summary":"List scrub rule sets","description":"List scrub rule sets with pagination, filtering and sorting.","operationId":"list_scrub_sets_api_v1_ncm_scrub_sets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by set name","title":"Search"},"description":"Search by set name"},{"name":"is_system","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by system flag","title":"Is System"},"description":"Filter by system flag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ScrubRuleSetListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Scrub Rule Sets"],"summary":"Create a scrub rule set","description":"Create a scrub rule set with its rules.","operationId":"create_scrub_set_api_v1_ncm_scrub_sets_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrubRuleSetCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrubRuleSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/scrub-sets/{set_id}":{"get":{"tags":["NCM Scrub Rule Sets"],"summary":"Get a scrub rule set","description":"Get a single scrub rule set (with its rules) by ID.","operationId":"get_scrub_set_api_v1_ncm_scrub_sets__set_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Set Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrubRuleSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Scrub Rule Sets"],"summary":"Update a scrub rule set","description":"Update a scrub rule set (passing ``rules`` replaces them).","operationId":"update_scrub_set_api_v1_ncm_scrub_sets__set_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Set Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrubRuleSetUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrubRuleSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Scrub Rule Sets"],"summary":"Delete a scrub rule set","description":"Delete a scrub rule set (system sets are protected).","operationId":"delete_scrub_set_api_v1_ncm_scrub_sets__set_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Set Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/scrub-sets/{set_id}/clone":{"post":{"tags":["NCM Scrub Rule Sets"],"summary":"Clone a scrub rule set","description":"Clone a scrub rule set (system or custom) into a new editable copy.","operationId":"clone_scrub_set_api_v1_ncm_scrub_sets__set_id__clone_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Set Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ScrubRuleSetClone"},{"type":"null"}],"title":"Data"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScrubRuleSetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/scrub-sets/{set_id}/references":{"get":{"tags":["NCM Scrub Rule Sets"],"summary":"Where a scrub rule set is used (blocking + auto-clearing references)","description":"Itemised references to a scrub rule set for the delete drawer.","operationId":"scrub_set_references_api_v1_ncm_scrub_sets__set_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"set_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Set Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/scrub-sets/references/counts":{"post":{"tags":["NCM Scrub Rule Sets"],"summary":"Batch reference counts for a page of scrub rule sets (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"scrub_set_reference_counts_api_v1_ncm_scrub_sets_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Scrub Set Reference Counts Api V1 Ncm Scrub Sets References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/snapshots":{"get":{"tags":["NCM Snapshots"],"summary":"List a config's snapshots","description":"List a tracked config's snapshots (timeline). Never loads blob bytes.","operationId":"list_snapshots_api_v1_ncm_snapshots_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"The tracked config whose timeline to list","title":"Tracked Config Id"},"description":"The tracked config whose timeline to list"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"content_kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by content kind (text|binary)","title":"Content Kind"},"description":"Filter by content kind (text|binary)"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by content_hash prefix OR version-label title substring (compare-version picker)","title":"Search"},"description":"Filter by content_hash prefix OR version-label title substring (compare-version picker)"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_SnapshotListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}":{"get":{"tags":["NCM Snapshots"],"summary":"Get a snapshot","description":"Get a single snapshot (scrubbed body; never raw_body or blob).","operationId":"get_snapshot_api_v1_ncm_snapshots__snapshot_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}/diff":{"get":{"tags":["NCM Snapshots"],"summary":"Diff a snapshot","description":"Diff a snapshot against prev / baseline / any snapshot. Binary is refused.","operationId":"diff_snapshot_api_v1_ncm_snapshots__snapshot_id__diff_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}},{"name":"compare_with","in":"query","required":false,"schema":{"type":"string","pattern":"^(prev|baseline|snapshot)$","default":"prev","title":"Compare With"}},{"name":"other_snapshot_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Required when compare_with=snapshot","title":"Other Snapshot Id"},"description":"Required when compare_with=snapshot"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotDiffResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}/blob":{"get":{"tags":["NCM Snapshots"],"summary":"Download a binary snapshot's bytes","description":"Download the binary payload of a binary snapshot (the only blob-loading path).","operationId":"download_blob_api_v1_ncm_snapshots__snapshot_id__blob_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}/raw":{"get":{"tags":["NCM Snapshots"],"summary":"Reveal a snapshot's raw unscrubbed body (audited)","description":"Reveal a snapshot's decrypted raw body.\n\nRequires the high-privilege ``ncm_tracked_configs.reveal_raw`` action (distinct from\nviewing the scrubbed body). Access is audited (``NCM_SNAPSHOT_RAW_REVEALED``).","operationId":"reveal_raw_body_api_v1_ncm_snapshots__snapshot_id__raw_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SnapshotRawRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}/labels":{"get":{"tags":["NCM Snapshots"],"summary":"List a snapshot's labels","description":"List a snapshot's version labels.","operationId":"list_labels_api_v1_ncm_snapshots__snapshot_id__labels_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VersionLabelResponse"},"title":"Response List Labels Api V1 Ncm Snapshots  Snapshot Id  Labels Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Snapshots"],"summary":"Apply a label to a snapshot (baseline ⟹ auto-pin)","description":"Apply a label; a baseline/golden/approved also materialises a pin.","operationId":"apply_label_api_v1_ncm_snapshots__snapshot_id__labels_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionLabelCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VersionLabelResponse"},"title":"Response Apply Label Api V1 Ncm Snapshots  Snapshot Id  Labels Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}/labels/{kind}":{"delete":{"tags":["NCM Snapshots"],"summary":"Remove a snapshot label","description":"Remove a specific label from a snapshot.","operationId":"remove_label_api_v1_ncm_snapshots__snapshot_id__labels__kind__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}},{"name":"kind","in":"path","required":true,"schema":{"$ref":"#/components/schemas/LabelKind"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/snapshots/{snapshot_id}/tag":{"put":{"tags":["NCM Snapshots"],"summary":"Set (create-or-replace) the user tag on a snapshot","description":"Set or replace the snapshot's single user tag (title + optional note; no side-effects).","operationId":"set_tag_api_v1_ncm_snapshots__snapshot_id__tag_put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TagUpsert"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionLabelResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Snapshots"],"summary":"Remove the user tag from a snapshot","description":"Remove the snapshot's user tag.","operationId":"clear_tag_api_v1_ncm_snapshots__snapshot_id__tag_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"snapshot_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Snapshot Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources":{"get":{"tags":["NCM Sources"],"summary":"List collection sources","description":"List collection sources with pagination, filtering and sorting.","operationId":"list_sources_api_v1_ncm_sources_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by source name","title":"Search"},"description":"Search by source name"},{"name":"transport_type","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/TransportType"},{"type":"null"}],"description":"Filter by transport type","title":"Transport Type"},"description":"Filter by transport type"},{"name":"collector_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by collector","title":"Collector Id"},"description":"Filter by collector"},{"name":"credential_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by credential","title":"Credential Id"},"description":"Filter by credential"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_CollectionSourceListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Sources"],"summary":"Create a collection source","description":"Create a collection source.","operationId":"create_source_api_v1_ncm_sources_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionSourceCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionSourceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources/{source_id}":{"get":{"tags":["NCM Sources"],"summary":"Get a collection source","description":"Get a single collection source by ID.","operationId":"get_source_api_v1_ncm_sources__source_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionSourceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Sources"],"summary":"Update a collection source","description":"Update a collection source.","operationId":"update_source_api_v1_ncm_sources__source_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionSourceUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionSourceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Sources"],"summary":"Delete a collection source","description":"Delete a collection source.","operationId":"delete_source_api_v1_ncm_sources__source_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources/{source_id}/host-key":{"get":{"tags":["NCM Sources"],"summary":"Get a source's pinned SSH host key","description":"Return the pin (and any candidate) plus whether pinning is enforced for a source.","operationId":"get_source_host_key_api_v1_ncm_sources__source_id__host_key_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostKeyStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources/{source_id}/host-key/accept":{"post":{"tags":["NCM Sources"],"summary":"Accept the changed host key (re-trust)","description":"Promote the recorded candidate key to the trusted pin (one-click after OOB verify).","operationId":"accept_source_host_key_api_v1_ncm_sources__source_id__host_key_accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostKeyActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources/{source_id}/host-key/reset":{"post":{"tags":["NCM Sources"],"summary":"Reset (unpin) the host key","description":"Clear the pin (and any candidate) so the next collection re-pins from scratch.","operationId":"reset_source_host_key_api_v1_ncm_sources__source_id__host_key_reset_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HostKeyActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources/{source_id}/references":{"get":{"tags":["NCM Sources"],"summary":"Where a collection source is used (blocking + auto-clearing references)","description":"Itemised references to a collection source for the delete drawer.","operationId":"ncm_source_references_api_v1_ncm_sources__source_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Source Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/sources/references/counts":{"post":{"tags":["NCM Sources"],"summary":"Batch reference counts for a page of collection sources (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"ncm_source_reference_counts_api_v1_ncm_sources_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Ncm Source Reference Counts Api V1 Ncm Sources References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/transports":{"get":{"tags":["NCM Transports"],"summary":"List transport registry metadata","description":"Return static per-transport registry metadata for the data-driven source form.\n\nRead-only projection of the in-process transport registry (no DB): default port,\nwhether a credential/TLS-verify applies, and whether a working collector driver\nexists today (``available``).","operationId":"list_transports_api_v1_ncm_transports_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TransportMetadataResponse"},"type":"array","title":"Response List Transports Api V1 Ncm Transports Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/ncm/tracked-configs":{"get":{"tags":["NCM Tracked Configs"],"summary":"List tracked configs","description":"List tracked configs with pagination, filtering and sorting.","operationId":"list_tracked_configs_api_v1_ncm_tracked_configs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by config name","title":"Search"},"description":"Search by config name"},{"name":"source_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by source","title":"Source Id"},"description":"Filter by source"},{"name":"is_enabled","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by enabled state","title":"Is Enabled"},"description":"Filter by enabled state"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by derived health: ok | drifted | failing | collector_offline | disabled | never","title":"Status"},"description":"Filter by derived health: ok | drifted | failing | collector_offline | disabled | never"},{"name":"collector_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by the collector of a config's address(es)","title":"Collector Id"},"description":"Filter by the collector of a config's address(es)"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TrackedConfigListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Tracked Configs"],"summary":"Create a tracked config","description":"Create a tracked config.","operationId":"create_tracked_config_api_v1_ncm_tracked_configs_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}":{"get":{"tags":["NCM Tracked Configs"],"summary":"Get a tracked config","description":"Get a single tracked config by ID (addresses included).","operationId":"get_tracked_config_api_v1_ncm_tracked_configs__tracked_config_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["NCM Tracked Configs"],"summary":"Update a tracked config","description":"Update a tracked config.","operationId":"update_tracked_config_api_v1_ncm_tracked_configs__tracked_config_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["NCM Tracked Configs"],"summary":"Delete a tracked config","description":"Delete a tracked config (addresses and snapshots cascade).","operationId":"delete_tracked_config_api_v1_ncm_tracked_configs__tracked_config_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/addresses":{"post":{"tags":["NCM Tracked Configs"],"summary":"Add an address to a tracked config","description":"Add a concrete, collector-scoped address (subnets rejected).","operationId":"add_address_api_v1_ncm_tracked_configs__tracked_config_id__addresses_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigAddressCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrackedConfigAddressResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/addresses/{address_id}":{"delete":{"tags":["NCM Tracked Configs"],"summary":"Remove an address from a tracked config","description":"Remove an address child.","operationId":"remove_address_api_v1_ncm_tracked_configs__tracked_config_id__addresses__address_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}},{"name":"address_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Address Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/recipient-groups":{"get":{"tags":["NCM Tracked Configs"],"summary":"List a config's change-notification recipient groups","description":"List the user groups subscribed to this config's change notifications.","operationId":"list_recipient_groups_api_v1_ncm_tracked_configs__tracked_config_id__recipient_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RecipientGroupResponse"},"title":"Response List Recipient Groups Api V1 Ncm Tracked Configs  Tracked Config Id  Recipient Groups Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["NCM Tracked Configs"],"summary":"Subscribe a group to a config's change notifications","description":"Bind a user group as a change-notification recipient (rejects an email-less group).","operationId":"add_recipient_group_api_v1_ncm_tracked_configs__tracked_config_id__recipient_groups_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipientGroupCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipientGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ncm/tracked-configs/{tracked_config_id}/recipient-groups/{group_id}":{"delete":{"tags":["NCM Tracked Configs"],"summary":"Unsubscribe a group from a config's change notifications","description":"Remove a group subscription.","operationId":"remove_recipient_group_api_v1_ncm_tracked_configs__tracked_config_id__recipient_groups__group_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"tracked_config_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tracked Config Id"}},{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/device-groups":{"get":{"tags":["Device Groups"],"summary":"List device groups","description":"List device groups with pagination.","operationId":"list_device_groups_api_v1_device_groups_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name or description","title":"Search"},"description":"Search name or description"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag","title":"Tag"},"description":"Filter by tag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_DeviceGroupListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Device Groups"],"summary":"Create a device group","description":"Create a new device group.","operationId":"create_device_group_api_v1_device_groups_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/device-groups/{group_id}":{"get":{"tags":["Device Groups"],"summary":"Get a device group","description":"Get a single device group with device list.","operationId":"get_device_group_api_v1_device_groups__group_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Device Groups"],"summary":"Update a device group","description":"Update a device group.\n\nEncrypted secrets (TACACS+ key, RADIUS secret, CoA secret) follow sentinel\nrules: send the sentinel to keep the stored value, null to clear it, or a new\nplaintext value to re-encrypt.","operationId":"update_device_group_api_v1_device_groups__group_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Device Groups"],"summary":"Delete a device group","description":"Delete a device group.","operationId":"delete_device_group_api_v1_device_groups__group_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/device-groups/{group_id}/references":{"get":{"tags":["Device Groups"],"summary":"Where a device group is used (blocking + auto-clearing references)","description":"Itemised references to a device group for the delete drawer.","operationId":"device_group_references_api_v1_device_groups__group_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/device-groups/references/counts":{"post":{"tags":["Device Groups"],"summary":"Batch reference counts for a page of device groups (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"device_group_reference_counts_api_v1_device_groups_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Device Group Reference Counts Api V1 Device Groups References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/device-groups/{group_id}/secrets":{"get":{"tags":["Device Groups"],"summary":"Reveal device-group secrets (decrypted)","description":"Reveal decrypted TACACS+ key, RADIUS secret, and CoA secret for a device group.\n\nThis endpoint returns the actual plaintext values.\nAccess is audited for security tracking.","operationId":"reveal_device_group_secrets_api_v1_device_groups__group_id__secrets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/device-groups/{group_id}/members":{"post":{"tags":["Device Groups"],"summary":"Add devices to a group","description":"Add devices to a group.","operationId":"add_members_api_v1_device_groups__group_id__members_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupMemberAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Device Groups"],"summary":"Remove devices from a group","description":"Remove devices from a group.","operationId":"remove_members_api_v1_device_groups__group_id__members_delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"group_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Group Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupMemberAction"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceGroupDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/devices":{"get":{"tags":["Devices"],"summary":"List devices","description":"List devices with pagination, filtering, and sorting.","operationId":"list_devices_api_v1_devices_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, hostname, vendor, location, network object name","title":"Search"},"description":"Search name, hostname, vendor, location, network object name"},{"name":"is_enabled","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by enabled status","title":"Is Enabled"},"description":"Filter by enabled status"},{"name":"vendor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by vendor","title":"Vendor"},"description":"Filter by vendor"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag","title":"Tag"},"description":"Filter by tag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, hostname, vendor, platform, location, is_enabled, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, hostname, vendor, platform, location, is_enabled, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_DeviceListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Devices"],"summary":"Create a device","description":"Create a new device.","operationId":"create_device_api_v1_devices_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/devices/{device_id}":{"get":{"tags":["Devices"],"summary":"Get a device","description":"Get a single device with group membership.","operationId":"get_device_api_v1_devices__device_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Devices"],"summary":"Update a device","description":"Update a device.\n\nEncrypted secrets (TACACS+ key, RADIUS secret, CoA secret) follow sentinel\nrules: send the sentinel to keep the stored value, null to clear it, or a new\nplaintext value to re-encrypt.","operationId":"update_device_api_v1_devices__device_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Devices"],"summary":"Delete a device","description":"Delete a device.","operationId":"delete_device_api_v1_devices__device_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/devices/{device_id}/references":{"get":{"tags":["Devices"],"summary":"Where a device is used (blocking + auto-clearing references)","description":"Itemised references to a device for the delete drawer.","operationId":"device_references_api_v1_devices__device_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/devices/references/counts":{"post":{"tags":["Devices"],"summary":"Batch reference counts for a page of devices (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"device_reference_counts_api_v1_devices_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Device Reference Counts Api V1 Devices References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/devices/{device_id}/secrets":{"get":{"tags":["Devices"],"summary":"Reveal device secrets (decrypted)","description":"Reveal decrypted TACACS+ key, RADIUS secret, and CoA secret for a device.\n\nThis endpoint returns the actual plaintext values.\nAccess is audited for security tracking.","operationId":"reveal_device_secrets_api_v1_devices__device_id__secrets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecretRevealResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/devices/{device_id}/inheritance":{"get":{"tags":["Devices"],"summary":"Resolve device field inheritance","description":"Where each inheritable field resolves from (device / group / global / none).\n\nView-only metadata — returns no secret values, only the inheritance level and\nthe source group name. Used by the device-detail card.","operationId":"get_device_inheritance_api_v1_devices__device_id__inheritance_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"device_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Device Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceInheritanceResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/network-objects":{"get":{"tags":["Network Objects"],"summary":"List network objects","description":"List network objects with pagination, filtering, and sorting.","operationId":"list_network_objects_api_v1_network_objects_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name, description, or IP value","title":"Search"},"description":"Search name, description, or IP value"},{"name":"entry_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by type: host, subnet, range, fqdn","title":"Entry Type"},"description":"Filter by type: host, subnet, range, fqdn"},{"name":"exclude_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Exclude entry types (comma-separated), e.g. 'range,fqdn' for IP-matching pickers","title":"Exclude Type"},"description":"Exclude entry types (comma-separated), e.g. 'range,fqdn' for IP-matching pickers"},{"name":"tag","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag","title":"Tag"},"description":"Filter by tag"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, entry_type, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, entry_type, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_NetworkObjectListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Network Objects"],"summary":"Create a network object","description":"Create a new network object.","operationId":"create_network_object_api_v1_network_objects_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkObjectCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkObjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/network-objects/{object_id}":{"get":{"tags":["Network Objects"],"summary":"Get a network object","description":"Get a single network object by ID.","operationId":"get_network_object_api_v1_network_objects__object_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"object_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Object Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkObjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Network Objects"],"summary":"Update a network object","description":"Update a network object.","operationId":"update_network_object_api_v1_network_objects__object_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"object_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Object Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkObjectUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkObjectResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Network Objects"],"summary":"Delete a network object","description":"Delete a network object.","operationId":"delete_network_object_api_v1_network_objects__object_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"object_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Object Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/network-objects/{object_id}/references":{"get":{"tags":["Network Objects"],"summary":"Where a network object is used (blocking + auto-clearing references)","description":"Itemised references to a network object for the delete drawer.","operationId":"network_object_references_api_v1_network_objects__object_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"object_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Object Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/network-objects/references/counts":{"post":{"tags":["Network Objects"],"summary":"Batch reference counts for a page of network objects (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"network_object_reference_counts_api_v1_network_objects_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Network Object Reference Counts Api V1 Network Objects References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/network-objects/contains":{"post":{"tags":["Network Objects"],"summary":"Find network objects containing an IP","description":"Find all network objects that contain the given IP address.\n\nUseful for policy debugging — check which objects match a source IP.","operationId":"check_contains_api_v1_network_objects_contains_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NetworkObjectContainsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/NetworkObjectResponse"},"type":"array","title":"Response Check Contains Api V1 Network Objects Contains Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/time-ranges":{"get":{"tags":["Time Ranges"],"summary":"List time ranges","description":"List time ranges with pagination.","operationId":"list_time_ranges_api_v1_time_ranges_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Per Page"},"description":"Items per page"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by name or description","title":"Search"},"description":"Search by name or description"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"description":"Sort direction (asc, desc)","title":"Sort Order"},"description":"Sort direction (asc, desc)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_TimeRangeListResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Time Ranges"],"summary":"Create a time range","description":"Create a new time range.","operationId":"create_time_range_api_v1_time_ranges_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeRangeCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeRangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/time-ranges/{time_range_id}":{"get":{"tags":["Time Ranges"],"summary":"Get a time range","description":"Get a single time range by ID.","operationId":"get_time_range_api_v1_time_ranges__time_range_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"time_range_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Time Range Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeRangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Time Ranges"],"summary":"Update a time range","description":"Update a time range.","operationId":"update_time_range_api_v1_time_ranges__time_range_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"time_range_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Time Range Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeRangeUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeRangeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Time Ranges"],"summary":"Delete a time range","description":"Delete a time range.","operationId":"delete_time_range_api_v1_time_ranges__time_range_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"time_range_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Time Range Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/time-ranges/{time_range_id}/references":{"get":{"tags":["Time Ranges"],"summary":"Where a time range is used (AAA + NAC rules)","description":"Itemised references to a time range for the delete drawer.","operationId":"time_range_references_api_v1_time_ranges__time_range_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"time_range_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Time Range Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/time-ranges/references/counts":{"post":{"tags":["Time Ranges"],"summary":"Batch reference counts for a page of time ranges (the Ref column)","description":"Compact per-id counts driving the list Ref column.","operationId":"time_range_reference_counts_api_v1_time_ranges_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Time Range Reference Counts Api V1 Time Ranges References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/reports/templates":{"get":{"tags":["Reports"],"summary":"List Templates","description":"List every in-code report template (the catalog), labels resolved to lang.","operationId":"list_templates_api_v1_reports_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateListResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/reports/templates/{template_id}":{"get":{"tags":["Reports"],"summary":"Get Template Endpoint","description":"Return one template's full public shape, including filters/columns/capabilities.","operationId":"get_template_endpoint_api_v1_reports_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/templates/{template_id}/run":{"post":{"tags":["Reports"],"summary":"Run Template Endpoint","description":"Run a template with the supplied filter values and return tidy results.","operationId":"run_template_endpoint_api_v1_reports_templates__template_id__run_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/templates/{template_id}/render":{"post":{"tags":["Reports"],"summary":"Render Template Endpoint","description":"Compose a template ad-hoc and return a self-contained HTML document.\n\nRuns read-only on the reports engine (``get_reports_session``); the result is\nrendered to HTML the frontend embeds in a sandboxed ``<iframe srcdoc>``. A\npreset with no chosen view defaults to its first authored view.","operationId":"render_template_endpoint_api_v1_reports_templates__template_id__render_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/datasets":{"get":{"tags":["Reports"],"summary":"List report datasets","description":"List datasets with pagination, filtering and sorting.","operationId":"list_datasets_api_v1_reports_datasets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search name or template id","title":"Search"},"description":"Search name or template id"},{"name":"template_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by template id","title":"Template Id"},"description":"Filter by template id"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, template_id, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, template_id, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_DatasetResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Reports"],"summary":"Create a report dataset","description":"Create a dataset over an in-code template.","operationId":"create_dataset_api_v1_reports_datasets_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/datasets/{dataset_id}":{"get":{"tags":["Reports"],"summary":"Get a report dataset","description":"Get a single dataset by id.","operationId":"get_dataset_api_v1_reports_datasets__dataset_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Reports"],"summary":"Update a report dataset","description":"Update a dataset (template id is immutable).","operationId":"update_dataset_api_v1_reports_datasets__dataset_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Reports"],"summary":"Delete a report dataset","description":"Delete a dataset.","operationId":"delete_dataset_api_v1_reports_datasets__dataset_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/datasets/{dataset_id}/references":{"get":{"tags":["Reports"],"summary":"Where a dataset is used (reports referencing it)","description":"Itemised references to a dataset for the delete drawer.","operationId":"dataset_references_api_v1_reports_datasets__dataset_id__references_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferenceReport"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/datasets/references/counts":{"post":{"tags":["Reports"],"summary":"Batch reference counts for a page of datasets (the Ref column)","description":"Compact per-id counts driving the datasets list Ref column.","operationId":"dataset_reference_counts_api_v1_reports_datasets_references_counts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefCountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"$ref":"#/components/schemas/RefCount"},"propertyNames":{"format":"uuid"},"type":"object","title":"Response Dataset Reference Counts Api V1 Reports Datasets References Counts Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/reports/datasets/{dataset_id}/run":{"post":{"tags":["Reports"],"summary":"Run a report dataset","description":"Run a saved dataset on the read-only reports engine and return tidy results.\n\nThe dataset row is loaded from the main DB; the composed query executes on the\nread-only reports session. The relative period resolves to bounds at run time.","operationId":"run_dataset_endpoint_api_v1_reports_datasets__dataset_id__run_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetRunRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetRunResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/datasets/{dataset_id}/render":{"post":{"tags":["Reports"],"summary":"Render a report dataset to HTML","description":"Render a saved dataset to a self-contained HTML document (for ``srcdoc``).\n\nThe dataset row is loaded from the main DB (writable session); the composed\nquery runs on the read-only reports session. A dataset whose template a release\ndropped is a 404 (``template_removed``). The relative period resolves at run\ntime, so the rendered report shows a live rolling window.","operationId":"render_dataset_endpoint_api_v1_reports_datasets__dataset_id__render_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/datasets/{dataset_id}/export":{"post":{"tags":["Reports"],"summary":"Export a report dataset (CSV/XLSX/PDF)","description":"Export a saved dataset to a file (§6).\n\nCSV/XLSX are the flat table under the dataset's chart (Variant A, never the\naggregated shape); PDF is the rendered document — the *same* self-contained\nHTML the preview shows, printed by ``taranac-renderer`` (so PDF == preview). A\nformat not in the template's ``export_formats`` is a 422 (this subsumes the\npreset case: a preset offers only PDF). The analytical query runs on the\nread-only reports session; the dataset load, timezone resolve and audit use the\nwritable session. Ad-hoc export of an unsaved builder config is a later wave.","operationId":"export_dataset_endpoint_api_v1_reports_datasets__dataset_id__export_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetExportRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/reports":{"get":{"tags":["Reports"],"summary":"List reports","description":"List reports with pagination, filtering and sorting.","operationId":"list_reports_api_v1_reports_reports_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by report name","title":"Search"},"description":"Search by report name"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field (name, created_at, updated_at)","title":"Sort By"},"description":"Sort field (name, created_at, updated_at)"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ReportResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Reports"],"summary":"Create a report","description":"Create a report composition.","operationId":"create_report_api_v1_reports_reports_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/reports/{report_id}":{"get":{"tags":["Reports"],"summary":"Get a report","description":"Get a single report by id.\n\nEmbeds ``dataset_names`` (page dataset_id → name, resolved in one query) so the\nbuilder labels its page list without a per-page fan-out.","operationId":"get_report_api_v1_reports_reports__report_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Reports"],"summary":"Update a report","description":"Update a report (name and/or composition).","operationId":"update_report_api_v1_reports_reports__report_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Report Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Reports"],"summary":"Delete a report","description":"Delete a report.","operationId":"delete_report_api_v1_reports_reports__report_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Report Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/reports/render":{"post":{"tags":["Reports"],"summary":"Render an ad-hoc report config to HTML","description":"Render an unsaved builder composition to one self-contained HTML document.\n\nThe builder previews a dirty/unsaved report without persisting it (§16). Dataset\nrows load from the main DB (writable session); each page's query runs on the\nread-only reports session. A missing dataset degrades to a placeholder page. This\nis the literal path — ``/render`` — matched ahead of ``/{report_id}/render`` (one\nURL segment vs two), so it never collides with the per-report render below.","operationId":"render_report_adhoc_api_v1_reports_reports_render_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportRenderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/reports/reports/{report_id}/render":{"post":{"tags":["Reports"],"summary":"Render a saved report to HTML","description":"Render a saved report to the one self-contained HTML the preview and PDF share.\n\nThe report row loads from the main DB (writable session); each page's dataset runs\non the read-only reports session. The relative period resolves at run time, so a\nsaved report always shows a live rolling window.","operationId":"render_report_endpoint_api_v1_reports_reports__report_id__render_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenderResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/reports/{report_id}/export":{"post":{"tags":["Reports"],"summary":"Export a report to PDF","description":"Export a saved report to PDF — the *same* self-contained HTML the preview shows,\nprinted by ``taranac-renderer`` (so PDF == preview). Reports are PDF-only: a composed\nmulti-page document has no flat CSV/XLSX meaning. The page queries run on the\nread-only reports session; the report load, timezone resolve and audit use the\nwritable session.","operationId":"export_report_endpoint_api_v1_reports_reports__report_id__export_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"report_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Report Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/schedules":{"get":{"tags":["Reports"],"summary":"List report schedules","description":"List schedules with pagination, filtering and sorting.","operationId":"list_schedules_api_v1_reports_schedules_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"per_page","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Per Page"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by schedule name","title":"Search"},"description":"Search by schedule name"},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort field","title":"Sort By"},"description":"Sort field"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/SortOrder"},{"type":"null"}],"title":"Sort Order"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedResponse_ReportScheduleResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["Reports"],"summary":"Create a report schedule","description":"Create a delivery schedule.","operationId":"create_schedule_api_v1_reports_schedules_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportScheduleCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportScheduleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/schedules/{schedule_id}":{"get":{"tags":["Reports"],"summary":"Get a report schedule","description":"Get a single schedule by id.","operationId":"get_schedule_api_v1_reports_schedules__schedule_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportScheduleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["Reports"],"summary":"Update a report schedule","description":"Update a schedule (name, items, recurrence, window, recipients, enabled).","operationId":"update_schedule_api_v1_reports_schedules__schedule_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportScheduleUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReportScheduleResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["Reports"],"summary":"Delete a report schedule","description":"Delete a schedule.","operationId":"delete_schedule_api_v1_reports_schedules__schedule_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/reports/schedules/{schedule_id}/send-now":{"post":{"tags":["Reports"],"summary":"Deliver a schedule now","description":"Run a schedule's delivery immediately (ad-hoc), attributed to the caller.\n\nThe same pipeline the tick job runs — resolve recipients, render/serialize the\nitems, split by size, e-mail — but with ``actor`` = the clicking user (recorded\nin the delivery audit). ``next_run_at`` is **not** touched: this is an out-of\n-band send, not a scheduled occurrence.","operationId":"send_schedule_now_api_v1_reports_schedules__schedule_id__send_now_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"schedule_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Schedule Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduleSendResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"AaaActivityBucket":{"properties":{"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"tacacs_authn_success":{"type":"integer","title":"Tacacs Authn Success","default":0},"tacacs_authn_fail":{"type":"integer","title":"Tacacs Authn Fail","default":0},"tacacs_authz_total":{"type":"integer","title":"Tacacs Authz Total","default":0},"radius_auth_success":{"type":"integer","title":"Radius Auth Success","default":0},"radius_auth_fail":{"type":"integer","title":"Radius Auth Fail","default":0}},"type":"object","required":["timestamp"],"title":"AaaActivityBucket","description":"Single time-bucket with aggregated auth counts."},"AaaActivityTotals":{"properties":{"tacacs_authn_success":{"type":"integer","title":"Tacacs Authn Success","default":0},"tacacs_authn_fail":{"type":"integer","title":"Tacacs Authn Fail","default":0},"tacacs_authz_total":{"type":"integer","title":"Tacacs Authz Total","default":0},"radius_auth_success":{"type":"integer","title":"Radius Auth Success","default":0},"radius_auth_fail":{"type":"integer","title":"Radius Auth Fail","default":0}},"type":"object","title":"AaaActivityTotals","description":"Period totals across all buckets."},"AaaPolicyReorderRequest":{"properties":{"rule_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":10000,"minItems":1,"title":"Rule Ids","description":"Complete list of rule IDs in new order"}},"additionalProperties":false,"type":"object","required":["rule_ids"],"title":"AaaPolicyReorderRequest","description":"Request body for bulk reorder."},"AaaPolicyRuleCreate":{"properties":{"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true},"insert_at_position":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Insert At Position","description":"1-based position to insert the rule at. Existing rules at this position and below are shifted down. If omitted, the rule is appended at the end (before default rule)."},"who_any":{"type":"boolean","title":"Who Any","default":true},"who_user_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000,"title":"Who User Ids"},"who_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000,"title":"Who Group Ids"},"where_any":{"type":"boolean","title":"Where Any","default":true},"where_device_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000,"title":"Where Device Ids"},"where_device_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000,"title":"Where Device Group Ids"},"source_any":{"type":"boolean","title":"Source Any","default":true},"source_console":{"type":"boolean","title":"Source Console","default":false},"source_network_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000,"title":"Source Network Ids"},"when_type":{"type":"string","enum":["always","time_range"],"title":"When Type","default":"always"},"when_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"When Id"},"mfa":{"type":"string","enum":["off","required"],"title":"Mfa","default":"off"},"tacacs_profile_mode":{"type":"string","enum":["none","deny","auth_only","profile"],"title":"Tacacs Profile Mode","default":"none"},"tacacs_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tacacs Profile Id"},"tacacs_message":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Tacacs Message"},"radius_profile_mode":{"type":"string","enum":["none","deny","auth_only","profile"],"title":"Radius Profile Mode","default":"none"},"radius_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Radius Profile Id"},"radius_message":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Radius Message"}},"additionalProperties":false,"type":"object","title":"AaaPolicyRuleCreate","description":"Schema for creating a new AAA policy rule."},"AaaPolicyRuleResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"order":{"type":"integer","title":"Order"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"who_any":{"type":"boolean","title":"Who Any"},"who_users":{"items":{"$ref":"#/components/schemas/UserRefItem"},"type":"array","title":"Who Users"},"who_groups":{"items":{"$ref":"#/components/schemas/GroupRefItem"},"type":"array","title":"Who Groups"},"where_any":{"type":"boolean","title":"Where Any"},"where_devices":{"items":{"$ref":"#/components/schemas/DeviceRefItem"},"type":"array","title":"Where Devices"},"where_device_groups":{"items":{"$ref":"#/components/schemas/DeviceGroupRefItem"},"type":"array","title":"Where Device Groups"},"source_any":{"type":"boolean","title":"Source Any"},"source_console":{"type":"boolean","title":"Source Console"},"source_networks":{"items":{"$ref":"#/components/schemas/NetworkRefItem"},"type":"array","title":"Source Networks"},"when_type":{"type":"string","title":"When Type"},"when_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"When Id"},"when_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"When Name"},"when_entries_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"When Entries Count"},"mfa":{"type":"string","title":"Mfa"},"tacacs_profile_mode":{"type":"string","title":"Tacacs Profile Mode"},"tacacs_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tacacs Profile Id"},"tacacs_profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tacacs Profile Name"},"tacacs_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tacacs Message"},"radius_profile_mode":{"type":"string","title":"Radius Profile Mode"},"radius_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Radius Profile Id"},"radius_profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Radius Profile Name"},"radius_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Radius Message"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"is_default":{"type":"boolean","title":"Is Default"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","order","who_any","where_any","source_any","source_console","when_type","mfa","tacacs_profile_mode","radius_profile_mode","is_enabled","is_default","created_at","updated_at"],"title":"AaaPolicyRuleResponse","description":"Full AAA policy rule response with resolved names."},"AaaPolicyRuleUpdate":{"properties":{"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"},"who_any":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Who Any"},"who_user_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000},{"type":"null"}],"title":"Who User Ids"},"who_group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000},{"type":"null"}],"title":"Who Group Ids"},"where_any":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Where Any"},"where_device_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000},{"type":"null"}],"title":"Where Device Ids"},"where_device_group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000},{"type":"null"}],"title":"Where Device Group Ids"},"source_any":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Source Any"},"source_console":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Source Console"},"source_network_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":1000},{"type":"null"}],"title":"Source Network Ids"},"when_type":{"anyOf":[{"type":"string","enum":["always","time_range"]},{"type":"null"}],"title":"When Type"},"when_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"When Id"},"mfa":{"anyOf":[{"type":"string","enum":["off","required"]},{"type":"null"}],"title":"Mfa"},"tacacs_profile_mode":{"anyOf":[{"type":"string","enum":["none","deny","auth_only","profile"]},{"type":"null"}],"title":"Tacacs Profile Mode"},"tacacs_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tacacs Profile Id"},"tacacs_message":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Tacacs Message"},"radius_profile_mode":{"anyOf":[{"type":"string","enum":["none","deny","auth_only","profile"]},{"type":"null"}],"title":"Radius Profile Mode"},"radius_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Radius Profile Id"},"radius_message":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Radius Message"}},"additionalProperties":false,"type":"object","title":"AaaPolicyRuleUpdate","description":"Schema for updating an AAA policy rule. All fields optional."},"AbsoluteWindow":{"properties":{"type":{"type":"string","const":"absolute","title":"Type","default":"absolute"},"start":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End"}},"additionalProperties":false,"type":"object","title":"AbsoluteWindow","description":"A fixed date range. Either bound may be open (``None`` → since the beginning /\nup to now); the wall-clock bounds are anchored to the system timezone at render\ntime, exactly as the dataset export window is (``build_export_window``)."},"AccountingEvent":{"properties":{"time":{"type":"string","format":"date-time","title":"Time"},"user":{"type":"string","title":"User"},"nas_ip":{"type":"string","title":"Nas Ip","description":"The device (NAS) address the session/command ran on"},"event":{"type":"string","title":"Event","description":"TACACS+: 'start' | 'stop' | 'watchdog'. RADIUS: 'Start' | 'Stop' | 'Interim-Update'"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service","description":"TACACS+ service, or RADIUS Service-Type (e.g. 'NAS-Prompt-User')"},"command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command","description":"Command for command-accounting rows (TACACS+ only; NULL for RADIUS)"},"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Id","description":"Session/task correlation id (TACACS+ task_id / RADIUS session id)"},"priv_lvl":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priv Lvl","description":"Privilege level (TACACS+ only; NULL for RADIUS)"},"elapsed_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Elapsed Time","description":"Session elapsed time in seconds (TACACS+ stop rows / RADIUS Acct-Session-Time)"},"protocol":{"type":"string","enum":["tacacs","radius"],"title":"Protocol","description":"AAA protocol this row came from (for a UI badge)"}},"type":"object","required":["time","user","nas_ip","event","protocol"],"title":"AccountingEvent","description":"An accounting event — session/command accounting (``tacacs_acct_logs`` + ``radius_acct_logs``)."},"ActivityWindow":{"properties":{"from":{"type":"string","format":"date-time","title":"From","description":"Window start (previous snapshot's captured_at, or lookback)"},"to":{"type":"string","format":"date-time","title":"To","description":"Window end (this snapshot's captured_at)"}},"type":"object","required":["from","to"],"title":"ActivityWindow","description":"The change window the activity is reported over (both bounds UTC)."},"AggFn":{"type":"string","enum":["count","sum","avg","min","max"],"title":"AggFn","description":"A fixed aggregate function a raw-table aggregation may synthesize (§5.3).\n\n``COUNT`` needs no measure column (it counts rows); every other function\naggregates a declared ``MEASURE`` column. The set is closed — the composer maps\na member to a SQL function *literal* (never user text), so the aggregation\nclause can never be user-controlled SQL."},"AggregationCapabilitySummary":{"properties":{"groupable":{"items":{"type":"string"},"type":"array","title":"Groupable"},"functions":{"items":{"$ref":"#/components/schemas/AggFn"},"type":"array","title":"Functions"},"charts":{"items":{"$ref":"#/components/schemas/ChartType"},"type":"array","title":"Charts"},"time_column":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Time Column"},"granularities":{"items":{"$ref":"#/components/schemas/Granularity"},"type":"array","title":"Granularities","default":[]}},"type":"object","required":["groupable","functions","charts"],"title":"AggregationCapabilitySummary","description":"Group-by control (raw table only) — the groupable columns, offered aggregate\nfunctions and chart forms a dataset may synthesize (§5.1, wave 1b.1).\n\n``groupable`` are column *names*; the frontend resolves their labels (and the\nmeasure columns for a measure function) from the template's ``columns`` list,\nexactly as the sort whitelist does. ``time_column`` / ``granularities`` drive the\nline (time-series) chart (wave 1b.2); they are absent when ``line`` is not\noffered."},"AlertAcknowledge":{"properties":{"is_acknowledged":{"type":"boolean","title":"Is Acknowledged","default":true}},"type":"object","title":"AlertAcknowledge","description":"Payload for acknowledging an alert (PATCH)."},"AlertListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AlertResponse"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total","description":"Total alerts, ignoring filters"},"total_by_filter":{"type":"integer","title":"Total By Filter","description":"Total alerts matching the active filters"}},"type":"object","required":["items","total","total_by_filter"],"title":"AlertListResponse","description":"Paginated list of alerts."},"AlertResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"severity":{"type":"string","title":"Severity","description":"info | warning | error | critical"},"status":{"type":"string","title":"Status","description":"firing | resolved"},"title":{"type":"string","title":"Title"},"message":{"type":"string","title":"Message"},"source":{"type":"string","title":"Source"},"fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fingerprint"},"details":{"additionalProperties":true,"type":"object","title":"Details"},"occurrence_count":{"type":"integer","title":"Occurrence Count"},"is_acknowledged":{"type":"boolean","title":"Is Acknowledged"},"acknowledged_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Acknowledged At"},"acknowledged_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acknowledged By"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When this firing instance opened (first seen)"},"last_seen_at":{"type":"string","format":"date-time","title":"Last Seen At"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","severity","status","title","message","source","occurrence_count","is_acknowledged","created_at","last_seen_at"],"title":"AlertResponse","description":"Read representation of a system alert."},"AlertStatsResponse":{"properties":{"total":{"type":"integer","title":"Total","default":0},"firing":{"type":"integer","title":"Firing","default":0},"resolved":{"type":"integer","title":"Resolved","default":0},"acknowledged":{"type":"integer","title":"Acknowledged","default":0},"unacknowledged_firing":{"type":"integer","title":"Unacknowledged Firing","default":0},"by_severity":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Severity"}},"type":"object","title":"AlertStatsResponse","description":"Aggregate counters for badges and dashboards."},"AuditLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"event_type":{"type":"string","title":"Event Type"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"actor_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Username"},"target_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Id"},"target_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Type"},"target_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Username"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Details"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","event_type","created_at"],"title":"AuditLogResponse","description":"Schema for a single audit log entry."},"AupAcceptRequest":{"properties":{"portal_slug":{"type":"string","maxLength":100,"title":"Portal Slug"},"terms_accepted":{"type":"boolean","title":"Terms Accepted","default":true}},"type":"object","required":["portal_slug"],"title":"AupAcceptRequest","description":"AUP acceptance request.\n\nPUBLIC endpoint — posted by the guest's browser. No extra=\"forbid\". Bounds\nonly."},"AupAcceptResponse":{"properties":{"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"},"token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["status","message"],"title":"AupAcceptResponse","description":"Response after AUP acceptance."},"AuthenticationEvent":{"properties":{"time":{"type":"string","format":"date-time","title":"Time"},"user":{"type":"string","title":"User"},"nas_ip":{"type":"string","title":"Nas Ip","description":"The device (NAS) address the login hit"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Remote client address of the admin (TACACS+ rem_addr / RADIUS Calling-Station-Id)"},"line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line","description":"TTY/VTY line (TACACS+ only; NULL for RADIUS)"},"action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action","description":"Raw tac_plus-ng action string (TACACS+ only; NULL for RADIUS)"},"result":{"type":"string","title":"Result","description":"TACACS+: 'success' | 'failure'. RADIUS: 'accept' | 'reject'"},"protocol":{"type":"string","enum":["tacacs","radius"],"title":"Protocol","description":"AAA protocol this row came from (for a UI badge)"}},"type":"object","required":["time","user","nas_ip","result","protocol"],"title":"AuthenticationEvent","description":"An authentication event — 'who connected' (``tacacs_authn_logs`` + ``radius_auth_logs``)."},"AuthorizationEvent":{"properties":{"time":{"type":"string","format":"date-time","title":"Time"},"user":{"type":"string","title":"User"},"nas_ip":{"type":"string","title":"Nas Ip","description":"The device (NAS) address the command hit"},"command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command","description":"The authorized command (NULL for non-command authz, e.g. shell)"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service","description":"Service name, e.g. 'shell'"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source","description":"Remote client address (rem_addr)"},"line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line"},"result":{"type":"string","title":"Result","description":"'permit' | 'deny'"}},"type":"object","required":["time","user","nas_ip","result"],"title":"AuthorizationEvent","description":"A TACACS+ command-authorization event — 'who ran which commands' (``tacacs_authz_logs``).\n\nTACACS+-only by nature: RADIUS device-admin does not do per-command accounting, so\nthere is no RADIUS analog for this dimension (every row here is implicitly ``tacacs``)."},"BackupItem":{"properties":{"filename":{"type":"string","title":"Filename"},"size_bytes":{"type":"integer","title":"Size Bytes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"trigger":{"type":"string","title":"Trigger"},"app_version":{"type":"string","title":"App Version"},"alembic_head":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alembic Head"},"included":{"items":{"type":"string"},"type":"array","title":"Included"},"missing":{"items":{"type":"string"},"type":"array","title":"Missing"},"kek_fingerprint":{"type":"string","title":"Kek Fingerprint"}},"type":"object","required":["filename","size_bytes","created_at","trigger","app_version","included","kek_fingerprint"],"title":"BackupItem","description":"One configuration archive (from its plaintext manifest)."},"BackupListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/BackupItem"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["items","total"],"title":"BackupListResponse","description":"All archives currently in storage (newest first)."},"BackupSettingsResponse":{"properties":{"schedule_enabled":{"type":"boolean","title":"Schedule Enabled"},"interval_hours":{"type":"integer","title":"Interval Hours"},"retention_count":{"type":"integer","title":"Retention Count"},"include_certs":{"type":"boolean","title":"Include Certs"},"include_daemon_configs":{"type":"boolean","title":"Include Daemon Configs"},"include_host_files":{"type":"boolean","title":"Include Host Files"}},"type":"object","required":["schedule_enabled","interval_hours","retention_count","include_certs","include_daemon_configs","include_host_files"],"title":"BackupSettingsResponse","description":"Editable ``backup.*`` settings."},"BackupSettingsUpdate":{"properties":{"schedule_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Schedule Enabled"},"interval_hours":{"anyOf":[{"type":"integer","maximum":8760.0,"minimum":1.0},{"type":"null"}],"title":"Interval Hours"},"retention_count":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Retention Count"},"include_certs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Include Certs"},"include_daemon_configs":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Include Daemon Configs"},"include_host_files":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Include Host Files"}},"type":"object","title":"BackupSettingsUpdate","description":"Partial update of editable backup settings (only provided fields change).\n\nDocument-style flat PATCH (only provided fields change), so ``extra=\"forbid\"``\nis intentionally NOT set — the settings page may echo back read-only/derived\nfields and a stray key must not 422 a save. Numeric fields carry sane upper\nbounds so a typo can't schedule a 100-year interval or unbounded retention."},"BackupStatusResponse":{"properties":{"last_created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Created At","description":"created_at of the most recent archive (UTC)"},"last_size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Size Bytes","description":"Size of the most recent archive"},"last_trigger":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Trigger","description":"manual | scheduled (most recent archive)"},"last_app_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last App Version","description":"App version that produced the archive"},"schedule_enabled":{"type":"boolean","title":"Schedule Enabled","description":"Whether the scheduled-backup job is enabled"},"interval_hours":{"type":"integer","title":"Interval Hours","description":"Scheduled backup interval in hours"},"stale":{"type":"boolean","title":"Stale","description":"True when backups are overdue / missing"}},"type":"object","required":["schedule_enabled","interval_hours","stale"],"title":"BackupStatusResponse","description":"Last-archive metadata + schedule state for the backup-status widget.\n\nNot cached. ``last_*`` fields are null when no archive exists. ``stale`` is\ntrue when backups are overdue (see service for the truth table)."},"Body_import_device_groups_api_v1_import_export_device_groups_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"JSON, XLSX, or CSV file"}},"type":"object","required":["file"],"title":"Body_import_device_groups_api_v1_import_export_device_groups_import_post"},"Body_import_devices_api_v1_import_export_devices_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"JSON, XLSX, or CSV file"}},"type":"object","required":["file"],"title":"Body_import_devices_api_v1_import_export_devices_import_post"},"Body_import_groups_api_v1_import_export_groups_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"JSON, XLSX, or CSV file"}},"type":"object","required":["file"],"title":"Body_import_groups_api_v1_import_export_groups_import_post"},"Body_import_network_objects_api_v1_import_export_network_objects_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"JSON, XLSX, or CSV file"}},"type":"object","required":["file"],"title":"Body_import_network_objects_api_v1_import_export_network_objects_import_post"},"Body_import_users_api_v1_import_export_users_import_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"JSON, XLSX, or CSV file"}},"type":"object","required":["file"],"title":"Body_import_users_api_v1_import_export_users_import_post"},"Body_upload_template_api_v1_tacacs_templates_upload_post":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"YAML template file"}},"type":"object","required":["file"],"title":"Body_upload_template_api_v1_tacacs_templates_upload_post"},"BootstrapResponse":{"properties":{"app_env":{"type":"string","title":"App Env","description":"Deployment environment: development | demo | production | testing"},"login_hint":{"anyOf":[{"$ref":"#/components/schemas/LoginHint"},{"type":"null"}],"description":"Pre-fill credentials, or null in production"}},"type":"object","required":["app_env"],"title":"BootstrapResponse","description":"GET /auth/bootstrap response — public, unauthenticated runtime config.\n\nLets the login page learn the deployment environment at runtime (the frontend\nis a single static build, so a build-time flag cannot tell dev from demo from\nprod). ``login_hint`` is populated ONLY in development (admin creds from env)\nand demo (the published demo creds); in production it is always ``null`` —\ncredentials are never served to an unauthenticated client."},"ByodMfaStatusResponse":{"properties":{"status":{"type":"string","title":"Status"},"resolved_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved At"}},"type":"object","required":["status"],"title":"ByodMfaStatusResponse","description":"BYOD push challenge status (polling). Mirrors the web challenge status."},"ByodMfaVerifyRequest":{"properties":{"mfa_token":{"type":"string","maxLength":512,"minLength":1,"title":"Mfa Token"},"code":{"anyOf":[{"type":"string","maxLength":16},{"type":"null"}],"title":"Code"},"challenge_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Challenge Id"}},"type":"object","required":["mfa_token"],"title":"ByodMfaVerifyRequest","description":"BYOD MFA verification — submit the second factor.\n\n``code`` for TOTP / code-based providers; ``challenge_id`` for push\nproviders (mirrors the web ``/mfa/verify`` request shape).\n\nPUBLIC endpoint — posted by the guest's browser. No extra=\"forbid\". Bounds\nonly; the opaque tokens/codes are not stripped."},"ByodRegisterRequest":{"properties":{"portal_slug":{"type":"string","maxLength":100,"title":"Portal Slug"},"username":{"type":"string","maxLength":255,"title":"Username"},"password":{"type":"string","maxLength":256,"title":"Password"},"terms_accepted":{"type":"boolean","title":"Terms Accepted","default":false},"captcha_token":{"anyOf":[{"type":"string","maxLength":8192},{"type":"null"}],"title":"Captcha Token"},"website":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Website"}},"type":"object","required":["portal_slug","username","password"],"title":"ByodRegisterRequest","description":"BYOD device registration — existing user credentials.\n\nPUBLIC endpoint — posted by the guest's browser. No extra=\"forbid\". Bounds\nonly; credentials are NOT stripped (a password may legitimately hold\nsurrounding whitespace)."},"ByodRegisterResponse":{"properties":{"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"},"endpoint_mac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Mac"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"mfa_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mfa Token"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode"},"prompt_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Type"},"prompt_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prompt Data"},"challenge_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Challenge Id"},"challenge_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Challenge Expires At"}},"type":"object","required":["status","message"],"title":"ByodRegisterResponse","description":"Response after BYOD registration.\n\n``status`` is one of:\n  - ``active`` — device bound, access granted (no MFA, or MFA verified);\n    ``endpoint_mac`` set, ``expires_at`` set only for time_limited access.\n  - ``mfa_required`` — second factor needed before binding; ``mfa_token``\n    plus the created challenge fields are returned. The client submits the\n    factor to ``POST /byod-mfa-verify`` (and, for push, polls\n    ``GET /byod-mfa-status/{challenge_id}``).\n  - ``mfa_setup_required`` — the flow requires MFA but the user has no\n    provider configured; no token is issued."},"CaBundleSourceInfo":{"properties":{"type":{"type":"string","title":"Type"},"name":{"type":"string","title":"Name"},"expires":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires"},"certs_issued":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Certs Issued"}},"type":"object","required":["type","name"],"title":"CaBundleSourceInfo","description":"Single source in the CA bundle status."},"CaBundleStatusResponse":{"properties":{"sources":{"items":{"$ref":"#/components/schemas/CaBundleSourceInfo"},"type":"array","title":"Sources","default":[]},"total_cas":{"type":"integer","title":"Total Cas","default":0},"bundle_hash":{"type":"string","title":"Bundle Hash","default":""},"bundle_size_bytes":{"type":"integer","title":"Bundle Size Bytes","default":0},"last_rebuilt":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Rebuilt"}},"type":"object","title":"CaBundleStatusResponse","description":"CA bundle composition and health."},"CaCertInfo":{"properties":{"subject_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Dn"},"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"not_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not Before"},"not_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not After"},"serial_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial Number"},"key_algorithm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Key Algorithm"},"is_ca":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Ca"}},"type":"object","title":"CaCertInfo","description":"Parsed certificate metadata returned in LDAP config responses.\n\nOne shape for both certificates a configuration can hold — the directory\nserver's trust anchor and the EAP-TLS client-certificate CA."},"CaListItem":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"source":{"type":"string","enum":["trusted","internal","ldap"],"title":"Source"},"subject_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Dn"},"is_expired":{"type":"boolean","title":"Is Expired","default":false},"not_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not After"}},"type":"object","required":["id","name","source"],"title":"CaListItem","description":"Single CA entry from the unified list (Trusted CA + Internal CA + LDAP CA).\n\nUsed in the classification rule form when match_type=cert_issuer:\nadmin selects a CA from this list, its identifier becomes match_value.\n\nIdentifier format:\n  - Trusted/Internal CA: UUID string\n  - LDAP CA: \"ldap:{config_id}\" (e.g. \"ldap:taranac\")"},"CaListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaListItem"},"type":"array","title":"Items","default":[]},"total":{"type":"integer","title":"Total","default":0}},"type":"object","title":"CaListResponse","description":"Unified list of all CAs available for cert_issuer classification."},"CaUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"crl_distribution_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Crl Distribution Url"},"ocsp_responder_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Ocsp Responder Url"}},"additionalProperties":false,"type":"object","title":"CaUpdate","description":"Partial update for an Internal CA.\n\nextra=\"forbid\": admin-only (CreateCaForm edit branch submits name /\ndescription / enabled — a strict subset of these keys)."},"CapabilitiesSummary":{"properties":{"period":{"anyOf":[{"$ref":"#/components/schemas/PeriodCapabilitySummary"},{"type":"null"}]},"limit":{"anyOf":[{"$ref":"#/components/schemas/LimitCapabilitySummary"},{"type":"null"}]},"sort":{"anyOf":[{"$ref":"#/components/schemas/SortCapabilitySummary"},{"type":"null"}]},"aggregation":{"anyOf":[{"$ref":"#/components/schemas/AggregationCapabilitySummary"},{"type":"null"}]}},"type":"object","title":"CapabilitiesSummary","description":"What a dataset over this template may configure (§5.1). Each is optional."},"CaptivePortalConfigCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Description"},"enabled":{"type":"boolean","title":"Enabled","default":true},"slug":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z0-9][a-z0-9_-]*$","title":"Slug"},"is_default":{"type":"boolean","title":"Is Default","default":false},"deployment_mode":{"type":"string","pattern":"^(embedded|standalone)$","title":"Deployment Mode","default":"embedded"},"backend_api_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Backend Api Url"},"portal_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Portal Url"},"server_certificate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Server Certificate Id"},"dhcp_dns_config":{"anyOf":[{"$ref":"#/components/schemas/DhcpDnsConfig"},{"type":"null"}]},"redirect_mode":{"type":"string","pattern":"^(url_redirect|vlan_intercept|both)$","title":"Redirect Mode","default":"both"},"source_networks":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Source Networks"},"redirect_after_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Redirect After Url"},"default_flow":{"type":"string","pattern":"^(landing|guest|byod|aup|self_registration)$","title":"Default Flow","default":"landing"},"logo_data":{"anyOf":[{"type":"string","maxLength":5000000},{"type":"null"}],"title":"Logo Data"},"brand_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Brand Name"},"background_color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","title":"Background Color","default":"#FFFFFF"},"primary_color":{"type":"string","pattern":"^#[0-9A-Fa-f]{6}$","title":"Primary Color","default":"#2196F3"},"welcome_text":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Welcome Text"},"success_text":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Success Text"},"captcha_enabled":{"type":"boolean","title":"Captcha Enabled","default":true},"honeypot_enabled":{"type":"boolean","title":"Honeypot Enabled","default":true},"rate_limit_per_ip":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Rate Limit Per Ip","default":5},"allowed_email_domains":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Allowed Email Domains"},"blocked_email_domains":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Blocked Email Domains"},"flows":{"items":{"$ref":"#/components/schemas/CaptivePortalFlowCreate"},"type":"array","maxItems":16,"title":"Flows"}},"additionalProperties":false,"type":"object","required":["name","slug"],"title":"CaptivePortalConfigCreate","description":"Create a portal. Flows can be included inline."},"CaptivePortalConfigListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"enabled":{"type":"boolean","title":"Enabled"},"is_default":{"type":"boolean","title":"Is Default"},"deployment_mode":{"type":"string","title":"Deployment Mode"},"enabled_flows_count":{"type":"integer","title":"Enabled Flows Count","default":0},"active_sessions_count":{"type":"integer","title":"Active Sessions Count","default":0},"health_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Health Status"},"instance_count":{"type":"integer","title":"Instance Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","slug","enabled","is_default","deployment_mode","created_at","updated_at"],"title":"CaptivePortalConfigListResponse","description":"Lightweight portal for list views (no flows detail)."},"CaptivePortalConfigResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"enabled":{"type":"boolean","title":"Enabled"},"slug":{"type":"string","title":"Slug"},"is_default":{"type":"boolean","title":"Is Default"},"deployment_mode":{"type":"string","title":"Deployment Mode"},"backend_api_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Backend Api Url"},"api_token_prefix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Token Prefix"},"portal_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Portal Url"},"server_certificate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Server Certificate Id"},"server_certificate":{"anyOf":[{"$ref":"#/components/schemas/PortalServerCertPreview"},{"type":"null"}]},"dhcp_dns_config":{"anyOf":[{"$ref":"#/components/schemas/DhcpDnsConfig"},{"type":"null"}]},"redirect_mode":{"type":"string","title":"Redirect Mode"},"source_networks":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Source Networks"},"redirect_after_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect After Url"},"default_flow":{"type":"string","title":"Default Flow"},"logo_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Data"},"brand_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Name"},"background_color":{"type":"string","title":"Background Color"},"primary_color":{"type":"string","title":"Primary Color"},"welcome_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Welcome Text"},"success_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Text"},"captcha_enabled":{"type":"boolean","title":"Captcha Enabled"},"honeypot_enabled":{"type":"boolean","title":"Honeypot Enabled"},"rate_limit_per_ip":{"type":"integer","title":"Rate Limit Per Ip"},"allowed_email_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Allowed Email Domains"},"blocked_email_domains":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Blocked Email Domains"},"flows":{"items":{"$ref":"#/components/schemas/CaptivePortalFlowResponse"},"type":"array","title":"Flows","default":[]},"active_sessions_count":{"type":"integer","title":"Active Sessions Count","default":0},"health_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Health Status"},"instance_count":{"type":"integer","title":"Instance Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","description","enabled","slug","is_default","deployment_mode","backend_api_url","api_token_prefix","portal_url","server_certificate_id","redirect_mode","source_networks","redirect_after_url","default_flow","logo_data","brand_name","background_color","primary_color","welcome_text","success_text","captcha_enabled","honeypot_enabled","rate_limit_per_ip","allowed_email_domains","blocked_email_domains","created_at","updated_at"],"title":"CaptivePortalConfigResponse","description":"Portal data returned to the client (admin)."},"CaptivePortalConfigUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Description"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"slug":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Slug"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"},"deployment_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployment Mode"},"backend_api_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Backend Api Url"},"portal_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Portal Url"},"server_certificate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Server Certificate Id"},"dhcp_dns_config":{"anyOf":[{"$ref":"#/components/schemas/DhcpDnsConfig"},{"type":"null"}]},"redirect_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect Mode"},"source_networks":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Source Networks"},"redirect_after_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Redirect After Url"},"default_flow":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Flow"},"logo_data":{"anyOf":[{"type":"string","maxLength":5000000},{"type":"null"}],"title":"Logo Data"},"brand_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Brand Name"},"background_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Background Color"},"primary_color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Primary Color"},"welcome_text":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Welcome Text"},"success_text":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Success Text"},"captcha_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Captcha Enabled"},"honeypot_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Honeypot Enabled"},"rate_limit_per_ip":{"anyOf":[{"type":"integer","maximum":100.0,"minimum":1.0},{"type":"null"}],"title":"Rate Limit Per Ip"},"allowed_email_domains":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Allowed Email Domains"},"blocked_email_domains":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":200},{"type":"null"}],"title":"Blocked Email Domains"},"flows":{"anyOf":[{"items":{"$ref":"#/components/schemas/CaptivePortalFlowCreate"},"type":"array","maxItems":16},{"type":"null"}],"title":"Flows"}},"additionalProperties":false,"type":"object","title":"CaptivePortalConfigUpdate","description":"Update an existing portal. All fields optional.\n\nextra=\"forbid\": admin-only (same explicit dto as create, Partial-typed)."},"CaptivePortalFlowCreate":{"properties":{"flow_type":{"type":"string","pattern":"^(guest|self_registration|byod|aup)$","title":"Flow Type"},"enabled":{"type":"boolean","title":"Enabled","default":true},"display_order":{"type":"integer","title":"Display Order","default":0},"display_name":{"type":"string","maxLength":255,"minLength":1,"title":"Display Name"},"display_icon":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Display Icon"},"target_endpoint_group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Endpoint Group Id"},"settings":{"additionalProperties":true,"type":"object","maxProperties":200,"title":"Settings"}},"additionalProperties":false,"type":"object","required":["flow_type","display_name"],"title":"CaptivePortalFlowCreate","description":"Create a flow within a portal."},"CaptivePortalFlowResponse":{"properties":{"flow_type":{"type":"string","pattern":"^(guest|self_registration|byod|aup)$","title":"Flow Type"},"enabled":{"type":"boolean","title":"Enabled","default":true},"display_order":{"type":"integer","title":"Display Order","default":0},"display_name":{"type":"string","maxLength":255,"minLength":1,"title":"Display Name"},"display_icon":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Display Icon"},"target_endpoint_group_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Endpoint Group Id"},"settings":{"additionalProperties":true,"type":"object","maxProperties":200,"title":"Settings"},"id":{"type":"string","format":"uuid","title":"Id"},"portal_id":{"type":"string","format":"uuid","title":"Portal Id"},"target_endpoint_group_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Endpoint Group Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"additionalProperties":false,"type":"object","required":["flow_type","display_name","id","portal_id","created_at","updated_at"],"title":"CaptivePortalFlowResponse","description":"Flow data returned to the client."},"CaptivePortalInstanceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"portal_id":{"type":"string","format":"uuid","title":"Portal Id"},"instance_id":{"type":"string","title":"Instance Id"},"instance_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instance Name"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"last_heartbeat_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Heartbeat At"},"health_status":{"type":"string","title":"Health Status"},"health_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Health Data"},"first_seen_at":{"type":"string","format":"date-time","title":"First Seen At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","portal_id","instance_id","instance_name","ip_address","last_heartbeat_at","health_status","health_data","first_seen_at","created_at","updated_at"],"title":"CaptivePortalInstanceResponse","description":"Instance health data for admin UI."},"CertExpiryEntry":{"properties":{"kind":{"type":"string","title":"Kind","description":"internal_ca | server_cert | trusted_ca | issued"},"name":{"type":"string","title":"Name","description":"Admin label or CN/subject of the certificate"},"not_after":{"type":"string","format":"date-time","title":"Not After","description":"Certificate validity end (UTC)"},"days_left":{"type":"integer","title":"Days Left","description":"Whole days until expiry (negative = expired)"},"status":{"type":"string","title":"Status","description":"Lifecycle status of the certificate"}},"type":"object","required":["kind","name","not_after","days_left","status"],"title":"CertExpiryEntry","description":"One certificate nearing expiry (or already expired) across the PKI."},"CertExpiryResponse":{"properties":{"days":{"type":"integer","title":"Days","description":"Requested expiry horizon in days"},"items":{"items":{"$ref":"#/components/schemas/CertExpiryEntry"},"type":"array","title":"Items"},"summary":{"$ref":"#/components/schemas/CertExpirySummary"}},"type":"object","required":["days","items","summary"],"title":"CertExpiryResponse","description":"Flat list of soon-to-expire certificates plus headline counts.\n\nIncludes only certificates with ``days_left <= days`` (the requested\nhorizon) or already expired; revoked certificates are excluded. Sorted by\n``days_left`` ascending (most urgent first)."},"CertExpirySummary":{"properties":{"expired":{"type":"integer","title":"Expired","default":0},"critical_7d":{"type":"integer","title":"Critical 7D","description":"Not yet expired but within 7 days","default":0},"warning_30d":{"type":"integer","title":"Warning 30D","description":"Not yet expired but within 30 days","default":0}},"type":"object","title":"CertExpirySummary","description":"Headline counts for the cert-expiry widget."},"ChangePasswordRequest":{"properties":{"current_password":{"type":"string","maxLength":256,"minLength":1,"title":"Current Password"},"new_password":{"type":"string","maxLength":256,"minLength":1,"title":"New Password"}},"type":"object","required":["current_password","new_password"],"title":"ChangePasswordRequest","description":"POST /auth/change-password request body."},"ChartType":{"type":"string","enum":["table","bar","line","area","pie","donut","stat"],"title":"ChartType","description":"A chart's visual form (§5) — the shared chart vocabulary.\n\nThis enum is the full §5 catalog. The render layer authors the subset the\npilots need (``TABLE`` for raw, ``STAT``/``DONUT`` inside the preset Jinja);\nthe rest are declared for the roadmap (raw-table view picking — bar/line/pie —\nis wave 1b, over ``dataset.display_config``). Only ``ChartType`` is referenced\nby the composer today (the raw-table chart whitelist)."},"ClassificationRuleCreate":{"properties":{"match_type":{"type":"string","enum":["exact_mac","oui_prefix","mac_pattern","vendor_name","cert_issuer","cert_identity_pattern","hostname_pattern"],"title":"Match Type","description":"Type of match"},"match_value":{"type":"string","maxLength":255,"minLength":1,"title":"Match Value","description":"Value to match against"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"enabled":{"type":"boolean","title":"Enabled","default":true}},"additionalProperties":false,"type":"object","required":["match_type","match_value"],"title":"ClassificationRuleCreate","description":"Schema for creating a classification rule."},"ClassificationRuleResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"endpoint_group_id":{"type":"string","format":"uuid","title":"Endpoint Group Id"},"match_type":{"type":"string","title":"Match Type"},"match_value":{"type":"string","title":"Match Value"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"enabled":{"type":"boolean","title":"Enabled","default":true},"hit_count":{"type":"integer","title":"Hit Count","default":0},"last_hit_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Hit At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","endpoint_group_id","match_type","match_value","created_at","updated_at"],"title":"ClassificationRuleResponse","description":"Full classification rule response."},"ClassificationRuleTestMatch":{"properties":{"rules":{"items":{"$ref":"#/components/schemas/ClassificationRuleResponse"},"type":"array","title":"Rules"},"endpoint_group":{"$ref":"#/components/schemas/EndpointGroupBrief"}},"type":"object","required":["endpoint_group"],"title":"ClassificationRuleTestMatch","description":"A single group match in a classification test result.\n\nGroups rules by target group: one match per group, with every rule of\nthat group that fired listed in `rules`. This matches the domain\nmodel — an endpoint joins a group once, regardless of how many of\nthe group's rules matched — while still giving admins the full\nexplanation of why."},"ClassificationRuleTestRequest":{"properties":{"mac_address":{"type":"string","title":"Mac Address","description":"MAC address to test"},"vendor":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Vendor","description":"Optional vendor string — required to exercise vendor_name rules."},"cert_identity":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Cert Identity","description":"Optional certificate identity (CN or DNS SAN) — required to exercise cert_identity_pattern rules."},"cert_issuer":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Cert Issuer","description":"Optional certificate issuer DN — required to exercise cert_issuer rules. Accepts both OpenSSL oneline (/DC=pro/DC=taranac/CN=Root CA) and RFC 2253 (CN=Root CA,DC=taranac,DC=pro) formats."},"hostname":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Hostname","description":"Optional hostname — required to exercise hostname_pattern rules."}},"additionalProperties":false,"type":"object","required":["mac_address"],"title":"ClassificationRuleTestRequest","description":"Schema for testing classification.\n\nA MAC address is required. Additional fields are optional and enable\ntesting the three new certificate/hostname match types:\n\n- vendor: vendor string for vendor_name rules\n- cert_identity: CN/DNS SAN from certificate for cert_identity_pattern\n- cert_issuer: issuer DN from certificate for cert_issuer rules\n- hostname: endpoint hostname for hostname_pattern rules"},"ClassificationRuleTestResponse":{"properties":{"matched":{"type":"boolean","title":"Matched"},"matches":{"items":{"$ref":"#/components/schemas/ClassificationRuleTestMatch"},"type":"array","title":"Matches"}},"type":"object","required":["matched"],"title":"ClassificationRuleTestResponse","description":"Result of classification test.\n\nall-matches semantics: every rule whose condition is satisfied fires,\nand matches are grouped by target group. The endpoint would be\nassigned to every listed group simultaneously. When nothing matches,\n`matches` is an empty list (matched=False)."},"ClassificationRuleUpdate":{"properties":{"match_type":{"anyOf":[{"type":"string","enum":["exact_mac","oui_prefix","mac_pattern","vendor_name","cert_issuer","cert_identity_pattern","hostname_pattern"]},{"type":"null"}],"title":"Match Type"},"match_value":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Match Value"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"}},"additionalProperties":false,"type":"object","title":"ClassificationRuleUpdate","description":"Schema for updating a classification rule. All fields optional."},"ClusterNodeStatus":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id"},"name":{"type":"string","title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"is_self":{"type":"boolean","title":"Is Self","description":"True for the node serving this request."},"role":{"type":"string","enum":["primary","replica"],"title":"Role"},"sync_state":{"type":"string","enum":["in_sync","behind","unreachable"],"title":"Sync State","description":"Observed from pg_stat_replication on the primary, not a self-report."},"replay_lsn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replay Lsn","description":"The replica's last replayed WAL LSN."},"lag_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Lag Bytes","description":"Bytes behind the primary's current WAL."},"lag_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Lag Seconds","description":"Wall-clock replay lag in seconds."}},"type":"object","required":["node_id","name","is_self","role","sync_state"],"title":"ClusterNodeStatus","description":"One roster node with its observed replication health (from the primary)."},"ClusterServicesResponse":{"properties":{"nodes":{"items":{"$ref":"#/components/schemas/NodeServiceHealthResponse"},"type":"array","title":"Nodes"},"this_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"This Node Id"},"this_node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"This Node Name"},"status_source":{"type":"string","enum":["patroni","degraded"],"title":"Status Source","description":"patroni = per-node reachability cross-checked against Patroni; degraded = SQL-only (Patroni unreachable / standalone), freshness still enforced from row age."},"stale_after_seconds":{"type":"integer","title":"Stale After Seconds","description":"Age past which a cell is marked stale."}},"type":"object","required":["nodes","status_source","stale_after_seconds"],"title":"ClusterServicesResponse","description":"The per-node daemon-health matrix — every active node × {tacacs, radius, nac}."},"ClusterStatusResponse":{"properties":{"nodes":{"items":{"$ref":"#/components/schemas/ClusterNodeStatus"},"type":"array","title":"Nodes"},"this_node_id":{"type":"string","format":"uuid","title":"This Node Id"},"this_node_name":{"type":"string","title":"This Node Name"},"leader_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Leader Name","description":"The primary's node name (Patroni-authoritative from any node; null if no writable primary)."},"observed_from_leader":{"type":"boolean","title":"Observed From Leader","description":"True when the status is authoritative (Patroni topology, or this node is the leader); false only in the degraded HA fallback (replica + Patroni unreachable)."},"node_count":{"type":"integer","title":"Node Count"},"max_nodes":{"type":"integer","title":"Max Nodes","description":"Licensed node cap (1 for Community)."},"licensed_ha":{"type":"boolean","title":"Licensed Ha"},"over_cap":{"type":"boolean","title":"Over Cap","description":"More active nodes than the license permits."},"replication_lag_seconds":{"type":"number","title":"Replication Lag Seconds","description":"Worst-case replica replay lag."},"phantom_streamers":{"items":{"type":"string"},"type":"array","title":"Phantom Streamers","description":"application_names streaming from the primary with no active roster node (name drift, or a decommissioned-but-still-running replica). Empty when healthy."},"has_writable_primary":{"type":"boolean","title":"Has Writable Primary","description":"Is there a writable primary right now? False during a failover window / quorum loss (control plane frozen). Defaults true so an older backend reads as healthy.","default":true},"status_source":{"type":"string","enum":["patroni","local","degraded"],"title":"Status Source","description":"Where the topology came from: patroni (authoritative), local (standalone/this-is-leader), or degraded (HA replica, Patroni unreachable — peer health best-effort).","default":"local"},"slots":{"items":{"$ref":"#/components/schemas/ReplicationSlotStatus"},"type":"array","title":"Slots","description":"Physical replication slots on the primary (name/active/wal_status) — the WAL-retention health signal. Empty on a standalone node or when unread."}},"type":"object","required":["nodes","this_node_id","this_node_name","observed_from_leader","node_count","max_nodes","licensed_ha","over_cap","replication_lag_seconds"],"title":"ClusterStatusResponse","description":"The whole cluster: roster ⨝ observed health + license fit."},"CollectNowPendingResponse":{"properties":{"status":{"type":"string","enum":["pending","error"],"title":"Status"},"run":{"anyOf":[{"$ref":"#/components/schemas/CollectionRunResponse"},{"type":"null"}]},"collector":{"$ref":"#/components/schemas/CollectorRefResponse"},"collector_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Error"}},"type":"object","required":["status","collector"],"title":"CollectNowPendingResponse","description":"A standalone on-demand collect was routed to a dial-out collector — poll the run.\n\nCollect-now on a STANDALONE source can't collect in-process: the core opens an on-demand\nrun, enqueues a credential-free dispatch the target collector claims on its next ``/jobs``\npoll, and returns here. ``status='pending'`` carries the ``run`` to poll — the per-collector\nfan-in at ``GET /ncm/runs/{run_id}/progress`` is the true completion signal (the run itself\nreads ``completed`` the instant orchestration hands off). A fast-fail (the collector was\nalready offline) instead returns ``status='error'`` with ``collector_error='collector_offline'``\nand NO ``run`` (nothing was enqueued)."},"CollectNowRequest":{"properties":{"ingest_key":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Ingest Key"}},"type":"object","title":"CollectNowRequest","description":"Optional idempotency key for an on-demand collect (dedups a retried request)."},"CollectNowResponse":{"properties":{"run":{"$ref":"#/components/schemas/CollectionRunResponse"},"result":{"$ref":"#/components/schemas/CollectionResultResponse"}},"type":"object","required":["run","result"],"title":"CollectNowResponse","description":"The run + the single result produced by a SYNCHRONOUS (embedded) on-demand collect."},"CollectionRecipeClone":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name","description":"Name for the clone (defaults to '<orig> (copy)')"}},"additionalProperties":false,"type":"object","title":"CollectionRecipeClone","description":"Optional body for cloning a recipe — a new name for the copy."},"CollectionRecipeCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Recipe name"},"netmiko_device_type":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Netmiko Device Type","description":"Netmiko device_type the CLI driver drives this recipe as (e.g. 'cisco_ios')"},"scrub_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scrub Set Id","description":"Reusable scrub rule set applied to this recipe (optional)"},"kind":{"$ref":"#/components/schemas/RecipeKind","description":"cli | http | file","default":"cli"},"steps":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Steps","description":"Ordered CLI steps ({'command': ...}), a one-element HTTP request spec, or a one-element {'remote_path': ...}"},"trim":{"additionalProperties":true,"type":"object","title":"Trim","description":"Per-step trim directives"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CollectionRecipeCreate","description":"Schema for creating a recipe."},"CollectionRecipeListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"netmiko_device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Netmiko Device Type"},"scrub_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scrub Set Id"},"kind":{"$ref":"#/components/schemas/RecipeKind"},"is_system":{"type":"boolean","title":"Is System"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","kind","is_system","created_at"],"title":"CollectionRecipeListResponse","description":"Abbreviated recipe for list views."},"CollectionRecipeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"netmiko_device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Netmiko Device Type"},"scrub_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scrub Set Id"},"kind":{"$ref":"#/components/schemas/RecipeKind"},"steps":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Steps"},"trim":{"additionalProperties":true,"type":"object","title":"Trim"},"is_system":{"type":"boolean","title":"Is System"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","kind","steps","trim","is_system","created_at","updated_at"],"title":"CollectionRecipeResponse","description":"Full recipe response."},"CollectionRecipeUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"netmiko_device_type":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Netmiko Device Type"},"scrub_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scrub Set Id"},"kind":{"anyOf":[{"$ref":"#/components/schemas/RecipeKind"},{"type":"null"}]},"steps":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Steps"},"trim":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trim"}},"additionalProperties":false,"type":"object","title":"CollectionRecipeUpdate","description":"Schema for updating a recipe. All fields optional."},"CollectionResultResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"run_id":{"type":"string","format":"uuid","title":"Run Id"},"tracked_config_id":{"type":"string","format":"uuid","title":"Tracked Config Id"},"tracked_config_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tracked Config Name"},"collector_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Name"},"collector_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Mode"},"status":{"$ref":"#/components/schemas/ResultStatus"},"snapshot_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Snapshot Id"},"failure_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Class"},"attempts":{"type":"integer","title":"Attempts"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"trace_json":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Trace Json"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","run_id","tracked_config_id","status","snapshot_id","failure_class","attempts","error","created_at"],"title":"CollectionResultResponse","description":"One tracked-config outcome within a run."},"CollectionRunDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"trigger":{"$ref":"#/components/schemas/RunTrigger"},"status":{"$ref":"#/components/schemas/RunStatus"},"orchestrator_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Orchestrator Node Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"lease_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Lease Expires At"},"summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Summary"},"result_counts":{"anyOf":[{"$ref":"#/components/schemas/RunResultCounts"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","title":"Created At"},"results":{"items":{"$ref":"#/components/schemas/CollectionResultResponse"},"type":"array","title":"Results"}},"type":"object","required":["id","trigger","status","orchestrator_node_id","started_at","finished_at","lease_expires_at","summary","created_at"],"title":"CollectionRunDetailResponse","description":"A collection run with its per-target results."},"CollectionRunResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"trigger":{"$ref":"#/components/schemas/RunTrigger"},"status":{"$ref":"#/components/schemas/RunStatus"},"orchestrator_node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Orchestrator Node Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"lease_expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Lease Expires At"},"summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Summary"},"result_counts":{"anyOf":[{"$ref":"#/components/schemas/RunResultCounts"},{"type":"null"}]},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","trigger","status","orchestrator_node_id","started_at","finished_at","lease_expires_at","summary","created_at"],"title":"CollectionRunResponse","description":"A collection run (list form — no per-target results)."},"CollectionSourceCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique source name"},"transport_type":{"$ref":"#/components/schemas/TransportType","description":"Transport mechanism (fixes transport_settings shape)"},"network_object_id":{"type":"string","format":"uuid","title":"Network Object Id","description":"Network object (host|fqdn) this source reaches"},"port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Port","description":"Optional port; null → transport registry default"},"transport_settings":{"oneOf":[{"$ref":"#/components/schemas/SshSettings"},{"$ref":"#/components/schemas/TelnetSettings"},{"$ref":"#/components/schemas/ScpSettings"},{"$ref":"#/components/schemas/SftpSettings"},{"$ref":"#/components/schemas/HttpSettings"},{"$ref":"#/components/schemas/HttpsSettings"}],"title":"Transport Settings","description":"Per-transport settings (shape per transport_type)","discriminator":{"propertyName":"kind","mapping":{"http":"#/components/schemas/HttpSettings","https":"#/components/schemas/HttpsSettings","scp":"#/components/schemas/ScpSettings","sftp":"#/components/schemas/SftpSettings","ssh":"#/components/schemas/SshSettings","telnet":"#/components/schemas/TelnetSettings"}}},"credential_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Credential Id","description":"Credential to reach the source (if the transport needs one)"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id","description":"Owning collector; defaults to the default collector when omitted"}},"additionalProperties":false,"type":"object","required":["name","transport_type","network_object_id","transport_settings"],"title":"CollectionSourceCreate","description":"Create a collection source.\n\n``transport_settings`` is the discriminated :data:`TransportSettings` union: a\nbefore-validator injects ``kind`` from ``transport_type`` so the client sends\nonly the per-type fields, and a mismatch (ssh fields on an http source, etc.)\nis rejected at the boundary."},"CollectionSourceListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"transport_type":{"$ref":"#/components/schemas/TransportType"},"network_object_id":{"type":"string","format":"uuid","title":"Network Object Id"},"network_object":{"$ref":"#/components/schemas/NetworkObjectSummary"},"address":{"type":"string","title":"Address"},"effective_port":{"type":"integer","title":"Effective Port"},"credential_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Credential Id"},"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"collector_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","transport_type","network_object_id","network_object","address","effective_port","collector_id","created_at"],"title":"CollectionSourceListResponse","description":"Abbreviated source for list views."},"CollectionSourceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"transport_type":{"$ref":"#/components/schemas/TransportType"},"network_object_id":{"type":"string","format":"uuid","title":"Network Object Id"},"network_object":{"$ref":"#/components/schemas/NetworkObjectSummary","description":"Embedded read-only network-object preview"},"address":{"type":"string","title":"Address","description":"Derived reachability address (host IP / fqdn) — display continuity"},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port"},"effective_port":{"type":"integer","title":"Effective Port","description":"port, or the transport registry default when port is null"},"endpoint":{"type":"string","title":"Endpoint","description":"host:port, with a bare IPv6 host bracketed"},"transport_settings":{"additionalProperties":true,"type":"object","title":"Transport Settings"},"requires_credential":{"type":"boolean","title":"Requires Credential","description":"Whether this transport needs a credential (registry)."},"credential_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Credential Id"},"credential_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Credential Name"},"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"collector_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","transport_type","network_object_id","network_object","address","effective_port","endpoint","transport_settings","requires_credential","collector_id","created_at","updated_at"],"title":"CollectionSourceResponse","description":"Full source response, including the registry-resolved effective port/endpoint."},"CollectionSourceUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"transport_type":{"anyOf":[{"$ref":"#/components/schemas/TransportType"},{"type":"null"}]},"network_object_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Network Object Id"},"port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Port"},"transport_settings":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Transport Settings"},"credential_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Credential Id"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id"}},"additionalProperties":false,"type":"object","title":"CollectionSourceUpdate","description":"Update a collection source (partial).\n\n``transport_settings`` is a raw envelope here because the effective\n``transport_type`` may be the stored one; the service validates it through the\nsame discriminated :func:`parse_transport_settings`. Changing ``transport_type``\nrequires re-sending ``transport_settings`` (the old shape would no longer match)."},"CollectorCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique collector name"},"is_default":{"type":"boolean","title":"Is Default","description":"Make this the default collector (unsets any other default)","default":false},"mode":{"type":"string","enum":["embedded","standalone"],"title":"Mode","description":"Deployment mode","default":"embedded"},"endpoint":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Endpoint","description":"Internal API endpoint (standalone only)"},"status":{"type":"string","enum":["unknown","online","offline"],"title":"Status","description":"Heartbeat liveness","default":"unknown"},"version":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Version","description":"Reported collector build version"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CollectorCreate","description":"Schema for creating a collector."},"CollectorListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_default":{"type":"boolean","title":"Is Default"},"mode":{"type":"string","title":"Mode"},"endpoint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint"},"status":{"type":"string","title":"Status"},"last_seen":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Seen"},"last_seen_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen Ip"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"contract_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contract Version"},"compatibility":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Compatibility"},"core_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Core Version"},"core_contract_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Core Contract Version"},"identity_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identity Status"},"identity_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identity Fingerprint"},"identity_issued_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Identity Issued At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","is_default","mode","status","created_at"],"title":"CollectorListResponse","description":"Abbreviated collector for list views."},"CollectorProgressResponse":{"properties":{"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"name":{"type":"string","title":"Name"},"mode":{"type":"string","title":"Mode"},"effective_status":{"type":"string","title":"Effective Status"},"last_seen":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Seen"},"total":{"type":"integer","title":"Total"},"pending":{"type":"integer","title":"Pending"},"claimed":{"type":"integer","title":"Claimed"},"done":{"type":"integer","title":"Done"},"dead":{"type":"integer","title":"Dead"}},"type":"object","required":["collector_id","name","mode","effective_status","last_seen","total","pending","claimed","done","dead"],"title":"CollectorProgressResponse","description":"One collector's fan-in progress within a run (buckets + liveness).\n\n``effective_status`` is the READ-time collector liveness (``online|offline|unknown``),\nderived from ``last_seen`` — not the possibly-stale stored ``status`` column. An\n``embedded`` collector appears as a synthetic row folding this run's in-process results."},"CollectorRefResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"mode":{"type":"string","title":"Mode"},"effective_status":{"type":"string","title":"Effective Status"}},"type":"object","required":["id","name","mode","effective_status"],"title":"CollectorRefResponse","description":"A collector ref (id/name/mode/read-time liveness) — who executed / would execute a job.\n\n``mode`` is ``embedded`` (the in-process default — a synthetic ref) or ``standalone`` (a\ndial-out collector). ``effective_status`` is the READ-time liveness (``online|offline|\nunknown``) derived from ``last_seen`` — an embedded ref reports ``online`` (it runs\nin-process on the node serving the request)."},"CollectorResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_default":{"type":"boolean","title":"Is Default"},"mode":{"type":"string","title":"Mode"},"endpoint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint"},"status":{"type":"string","title":"Status"},"last_seen":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Seen"},"last_seen_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Seen Ip"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"contract_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contract Version"},"compatibility":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Compatibility"},"core_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Core Version"},"core_contract_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Core Contract Version"},"identity_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identity Status"},"identity_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identity Fingerprint"},"identity_issued_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Identity Issued At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","is_default","mode","status","created_at","updated_at"],"title":"CollectorResponse","description":"Full collector response.\n\n``status`` is the read-time overlaid liveness (``effective_status`` against the\nstaleness threshold), not the raw stored column. The ``identity_*`` fields are\nNULL for embedded / never-enrolled collectors and populated at enrollment for\nstandalone dial-out collectors — the operator health UI reads them to show the\nenrollment state without a second round-trip."},"CollectorUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"},"mode":{"anyOf":[{"type":"string","enum":["embedded","standalone"]},{"type":"null"}],"title":"Mode"},"endpoint":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Endpoint"},"status":{"anyOf":[{"type":"string","enum":["unknown","online","offline"]},{"type":"null"}],"title":"Status"},"version":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Version"}},"additionalProperties":false,"type":"object","title":"CollectorUpdate","description":"Schema for updating a collector. All fields optional."},"ColumnFormat":{"type":"string","enum":["text","integer","decimal","datetime","date","percent","duration","bytes"],"title":"ColumnFormat","description":"Display format hint for a result column (rendering + export)."},"ColumnRole":{"type":"string","enum":["dimension","measure"],"title":"ColumnRole","description":"Analytical role of a result column, for the view/mapping picker (§5).\n\n``DIMENSION`` — a categorical/temporal column to group or place on an axis\n(time, username, status). ``MEASURE`` — a numeric column to aggregate/plot as\na value. The role constrains which visual channel a column may map to; the SQL\nalready returns tidy data, so no aggregation happens on the client."},"ColumnSummary":{"properties":{"name":{"type":"string","title":"Name"},"role":{"$ref":"#/components/schemas/ColumnRole"},"label":{"type":"string","title":"Label"},"format":{"$ref":"#/components/schemas/ColumnFormat"},"default_hidden":{"type":"boolean","title":"Default Hidden","default":false}},"type":"object","required":["name","role","label","format"],"title":"ColumnSummary","description":"One declared result column with the metadata the view picker needs.\n\n``label`` is already resolved to the request language."},"CommandSetBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"CommandSetBrief","description":"Minimal command set info embedded in profile responses."},"CommandSetCommandArgCreate":{"properties":{"action":{"type":"string","enum":["permit","deny"],"title":"Action"},"args":{"type":"string","maxLength":256,"minLength":1,"title":"Args","description":"Regex pattern for argument matching"},"order":{"type":"integer","minimum":0.0,"title":"Order","description":"Evaluation order (first match wins)"}},"additionalProperties":false,"type":"object","required":["action","args","order"],"title":"CommandSetCommandArgCreate","description":"Schema for a single argument rule within a command."},"CommandSetCommandArgResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"action":{"type":"string","title":"Action"},"args":{"type":"string","title":"Args"},"order":{"type":"integer","title":"Order"}},"type":"object","required":["id","action","args","order"],"title":"CommandSetCommandArgResponse","description":"Argument rule response."},"CommandSetCommandCreate":{"properties":{"command":{"type":"string","maxLength":128,"minLength":1,"title":"Command","description":"Command name (show, configure, etc.)"},"default_action":{"type":"string","enum":["permit","deny"],"title":"Default Action","description":"Implicit action when no arg rule matches","default":"deny"},"permit_message":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Permit Message"},"deny_message":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Deny Message"},"order":{"type":"integer","minimum":0.0,"title":"Order","description":"Display order within the set"},"args":{"items":{"$ref":"#/components/schemas/CommandSetCommandArgCreate"},"type":"array","maxItems":256,"title":"Args","description":"Ordered argument rules"}},"additionalProperties":false,"type":"object","required":["command","order"],"title":"CommandSetCommandCreate","description":"Schema for a single command within a command set."},"CommandSetCommandResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"command":{"type":"string","title":"Command"},"default_action":{"type":"string","title":"Default Action"},"permit_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Permit Message"},"deny_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deny Message"},"order":{"type":"integer","title":"Order"},"args":{"items":{"$ref":"#/components/schemas/CommandSetCommandArgResponse"},"type":"array","title":"Args"}},"type":"object","required":["id","command","default_action","order"],"title":"CommandSetCommandResponse","description":"Command response with nested args."},"CommandSetCreate":{"properties":{"name":{"type":"string","maxLength":64,"minLength":1,"title":"Name","description":"Unique command set name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"commands":{"items":{"$ref":"#/components/schemas/CommandSetCommandCreate"},"type":"array","maxItems":1000,"title":"Commands","description":"Ordered list of commands"}},"additionalProperties":false,"type":"object","required":["name"],"title":"CommandSetCreate","description":"Schema for creating a command set with nested commands and args."},"CommandSetListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"command_count":{"type":"integer","title":"Command Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","created_at"],"title":"CommandSetListResponse","description":"Abbreviated command set for list views."},"CommandSetResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"commands":{"items":{"$ref":"#/components/schemas/CommandSetCommandResponse"},"type":"array","title":"Commands"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","created_at","updated_at"],"title":"CommandSetResponse","description":"Full command set response with nested commands and args."},"CommandSetUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"commands":{"anyOf":[{"items":{"$ref":"#/components/schemas/CommandSetCommandCreate"},"type":"array","maxItems":1000},{"type":"null"}],"title":"Commands"}},"additionalProperties":false,"type":"object","title":"CommandSetUpdate","description":"Schema for updating a command set.\n\nWhen commands are provided, the entire command list is replaced\n(delete-orphan cascade handles cleanup)."},"ComputerPreviewCreate":{"properties":{"dn":{"type":"string","title":"Dn"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"mac_address":{"type":"string","title":"Mac Address"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"}},"type":"object","required":["dn","mac_address"],"title":"ComputerPreviewCreate","description":"Computer endpoint that would be created during sync."},"ComputerPreviewDeactivate":{"properties":{"mac_address":{"type":"string","title":"Mac Address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["mac_address","reason"],"title":"ComputerPreviewDeactivate","description":"Computer endpoint that would be deactivated during sync."},"ComputerPreviewPending":{"properties":{"dn":{"type":"string","title":"Dn"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"status":{"type":"string","title":"Status","default":"pending"}},"type":"object","required":["dn"],"title":"ComputerPreviewPending","description":"AD computer without MAC that would be staged in pending table."},"ComputerPreviewSummary":{"properties":{"create":{"type":"integer","title":"Create","default":0},"update":{"type":"integer","title":"Update","default":0},"deactivate":{"type":"integer","title":"Deactivate","default":0},"pending_create":{"type":"integer","title":"Pending Create","default":0},"pending_update":{"type":"integer","title":"Pending Update","default":0}},"type":"object","title":"ComputerPreviewSummary","description":"Summary counts for computer preview."},"ComputerPreviewUpdate":{"properties":{"mac_address":{"type":"string","title":"Mac Address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"changes":{"additionalProperties":{"items":{},"type":"array"},"type":"object","title":"Changes"}},"type":"object","required":["mac_address"],"title":"ComputerPreviewUpdate","description":"Computer endpoint that would be updated during sync."},"ComputerSyncPreviewResponse":{"properties":{"endpoints_to_create":{"items":{"$ref":"#/components/schemas/ComputerPreviewCreate"},"type":"array","title":"Endpoints To Create"},"endpoints_to_update":{"items":{"$ref":"#/components/schemas/ComputerPreviewUpdate"},"type":"array","title":"Endpoints To Update"},"endpoints_to_deactivate":{"items":{"$ref":"#/components/schemas/ComputerPreviewDeactivate"},"type":"array","title":"Endpoints To Deactivate"},"pending_to_create":{"items":{"$ref":"#/components/schemas/ComputerPreviewPending"},"type":"array","title":"Pending To Create"},"pending_to_update":{"items":{"$ref":"#/components/schemas/ComputerPreviewPending"},"type":"array","title":"Pending To Update"},"total_computers_found":{"type":"integer","title":"Total Computers Found","default":0},"summary":{"$ref":"#/components/schemas/ComputerPreviewSummary"}},"type":"object","title":"ComputerSyncPreviewResponse","description":"Response from the LDAP computer preview (dry run) endpoint."},"ConditionResult":{"properties":{"matched":{"type":"boolean","title":"Matched"},"detail":{"type":"string","title":"Detail","description":"Human-readable explanation of the match/mismatch"}},"type":"object","required":["matched","detail"],"title":"ConditionResult","description":"Result of evaluating a single match condition."},"ConfigFileStatus":{"properties":{"file_exists":{"type":"boolean","title":"File Exists","default":false},"file_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"File Size"},"file_modified":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"File Modified"},"deployed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed At"},"config_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Config Hash"},"config_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Config Size"},"config_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Config Path"},"deployed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed By"},"last_validation":{"anyOf":[{"$ref":"#/components/schemas/ConfigValidationStatus"},{"type":"null"}]}},"type":"object","title":"ConfigFileStatus","description":"Config file metadata."},"ConfigPreviewResponse":{"properties":{"config":{"type":"string","title":"Config"},"size":{"type":"integer","title":"Size"}},"type":"object","required":["config","size"],"title":"ConfigPreviewResponse","description":"Response for config preview."},"ConfigReloadResponse":{"properties":{"status":{"type":"string","title":"Status"},"config_path":{"type":"string","title":"Config Path"},"config_size":{"type":"integer","title":"Config Size"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"timestamp":{"type":"string","title":"Timestamp"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["status","config_path","config_size","timestamp"],"title":"ConfigReloadResponse","description":"Response for config reload."},"ConfigSnippetLineSchema":{"properties":{"num":{"type":"integer","title":"Num"},"text":{"type":"string","title":"Text"},"error":{"type":"boolean","title":"Error","default":false}},"type":"object","required":["num","text"],"title":"ConfigSnippetLineSchema","description":"A single line in a config error snippet."},"ConfigStatusInfo":{"properties":{"deployed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed At"},"deployed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed By"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"config_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Config Size"},"rules_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rules Count"},"devices_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices Count"},"validation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Validation"}},"type":"object","title":"ConfigStatusInfo","description":"Config deploy and validation status."},"ConfigValidateResponse":{"properties":{"valid":{"type":"boolean","title":"Valid"},"config_size":{"type":"integer","title":"Config Size"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"rules_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rules Count"},"devices_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices Count"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_line":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Error Line"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"block_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Block Type"},"block_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Block Name"},"rule_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Id"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"rule_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Description"},"config_snippet":{"anyOf":[{"items":{"$ref":"#/components/schemas/ConfigSnippetLineSchema"},"type":"array"},{"type":"null"}],"title":"Config Snippet"}},"type":"object","required":["valid","config_size"],"title":"ConfigValidateResponse","description":"Response for config validation (dry-run).\n\nWhen valid=False, includes error details with rule mapping\nand a code snippet around the error line for UI highlighting."},"ConfigValidationStatus":{"properties":{"valid":{"type":"boolean","title":"Valid"},"validated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Validated At"},"config_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Config Size"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_line":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Error Line"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"block_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Block Type"},"block_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Block Name"},"rule_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Id"},"rule_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Description"}},"type":"object","required":["valid"],"title":"ConfigValidationStatus","description":"Last config validation result summary."},"ContentKind":{"type":"string","enum":["text","binary"],"title":"ContentKind","description":"Whether a snapshot body is diffable text or an opaque binary blob."},"CpuLoadAverage":{"properties":{"1min":{"type":"number","title":"1Min"},"5min":{"type":"number","title":"5Min"},"15min":{"type":"number","title":"15Min"}},"type":"object","required":["1min","5min","15min"],"title":"CpuLoadAverage","description":"CPU load averages."},"CpuMetrics":{"properties":{"percent":{"type":"number","title":"Percent"},"percent_per_core":{"items":{"type":"number"},"type":"array","title":"Percent Per Core"},"core_count_logical":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Core Count Logical"},"core_count_physical":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Core Count Physical"},"load_average":{"anyOf":[{"$ref":"#/components/schemas/CpuLoadAverage"},{"type":"null"}]},"user":{"type":"number","title":"User","default":0.0},"system":{"type":"number","title":"System","default":0.0},"idle":{"type":"number","title":"Idle","default":0.0},"iowait":{"type":"number","title":"Iowait","default":0.0}},"type":"object","required":["percent"],"title":"CpuMetrics","description":"CPU metric snapshot."},"CredentialBindingRecord":{"properties":{"address":{"type":"string","format":"ipvanyaddress","title":"Address","description":"Concrete v4/v6 address"},"credential_id":{"type":"string","format":"uuid","title":"Credential Id","description":"Credential that authenticated there"},"last_ok":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Ok","description":"When it was last confirmed (defaults to now)"}},"additionalProperties":false,"type":"object","required":["address","credential_id"],"title":"CredentialBindingRecord","description":"Record (upsert) that a credential worked at an address."},"CredentialBindingResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"address":{"type":"string","title":"Address"},"credential_id":{"type":"string","format":"uuid","title":"Credential Id"},"bound_at":{"type":"string","format":"date-time","title":"Bound At"},"last_ok":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Ok"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","address","credential_id","bound_at","created_at","updated_at"],"title":"CredentialBindingResponse","description":"A binding record."},"CredentialCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique credential name"},"type":{"$ref":"#/components/schemas/CredentialType","description":"Secret kind (fixes secret_fields shape)"},"mode":{"$ref":"#/components/schemas/CredentialMode","description":"stored | jit (external is a phase-2 seam)","default":"stored"},"secret_fields":{"additionalProperties":{"type":"string"},"type":"object","title":"Secret Fields","description":"Plaintext secret payload, shape per type (MUST be empty {} for jit — Taranac mints)"},"enable_ref":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Enable Ref","description":"Optional enable credential (type=enable)"},"provider_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Provider Id","description":"External provider (external mode only, phase-2)"},"external_ref":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"External Ref","description":"Provider-side reference (phase-2)"},"user_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Account Id","description":"Local user account to mint per-run (required for jit mode; NULL otherwise)"}},"additionalProperties":false,"type":"object","required":["name","type","secret_fields"],"title":"CredentialCreate","description":"Create a credential.\n\n``secret_fields`` is only structurally typed here (``dict[str, str]``); the\nper-``type`` shape check happens in the service (``create_credential``), which\ncatches the Pydantic error and raises a clean i18n ``ValidationError``. It is\ndeliberately **not** validated in a raising model-validator: Pydantic's\n``errors()`` embeds the offending ``input`` value, and that would leak the\nsubmitted plaintext secret into the 422 response body. This mirrors the update\npath (``_apply_secret_sentinel``)."},"CredentialListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"type":{"$ref":"#/components/schemas/CredentialType"},"mode":{"$ref":"#/components/schemas/CredentialMode"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","type","mode","created_at"],"title":"CredentialListResponse","description":"Abbreviated credential for list views."},"CredentialMode":{"type":"string","enum":["stored","jit","external"],"title":"CredentialMode","description":"How the secret is acquired at collection time."},"CredentialProviderCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique provider name"},"kind":{"type":"string","maxLength":64,"minLength":1,"title":"Kind","description":"Provider kind (hashicorp_vault, cyberark, …)"},"endpoint":{"type":"string","maxLength":512,"minLength":1,"title":"Endpoint","description":"Provider base URL / endpoint"},"auth_config":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Auth Config","description":"Provider auth material (encrypted at rest)"}},"additionalProperties":false,"type":"object","required":["name","kind","endpoint"],"title":"CredentialProviderCreate","description":"Create a provider."},"CredentialProviderListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"kind":{"type":"string","title":"Kind"},"endpoint":{"type":"string","title":"Endpoint"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","kind","endpoint","created_at"],"title":"CredentialProviderListResponse","description":"Abbreviated provider for list views."},"CredentialProviderResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"kind":{"type":"string","title":"Kind"},"endpoint":{"type":"string","title":"Endpoint"},"has_auth_config":{"type":"boolean","title":"Has Auth Config","description":"Whether encrypted auth material is stored"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","kind","endpoint","has_auth_config","created_at","updated_at"],"title":"CredentialProviderResponse","description":"Provider response — never echoes auth material."},"CredentialProviderUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"kind":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Kind"},"endpoint":{"anyOf":[{"type":"string","maxLength":512,"minLength":1},{"type":"null"}],"title":"Endpoint"},"auth_config":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Auth Config"}},"additionalProperties":false,"type":"object","title":"CredentialProviderUpdate","description":"Update a provider. ``auth_config`` follows keep-if-omitted semantics."},"CredentialResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"type":{"$ref":"#/components/schemas/CredentialType"},"mode":{"$ref":"#/components/schemas/CredentialMode"},"secret_fields":{"additionalProperties":{"type":"string"},"type":"object","title":"Secret Fields","description":"Field names -> masked sentinel for secrets, plaintext for non-secret fields (username)"},"enable_ref":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Enable Ref"},"enable_ref_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enable Ref Name","description":"Denormalized name of the linked enable credential (read-only display)"},"provider_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Provider Id"},"external_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Ref"},"user_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Account Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","type","mode","secret_fields","created_at","updated_at"],"title":"CredentialResponse","description":"Full credential response.\n\nSecret values are masked with the sentinel; the non-secret ``username`` is\nreturned in plaintext (see ``service.NON_SECRET_FIELDS``)."},"CredentialSecretRevealResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"type":{"$ref":"#/components/schemas/CredentialType"},"secret_fields":{"additionalProperties":{"type":"string"},"type":"object","title":"Secret Fields","description":"Decrypted field -> plaintext"}},"type":"object","required":["id","name","type","secret_fields"],"title":"CredentialSecretRevealResponse","description":"Decrypted secret payload — returned only by the audited reveal endpoint."},"CredentialType":{"type":"string","enum":["password","ssh_key","ssh_cert","tls_cert","token","enable","bag"],"title":"CredentialType","description":"The kind of secret material a credential holds (fixes the payload shape)."},"CredentialUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"mode":{"anyOf":[{"$ref":"#/components/schemas/CredentialMode"},{"type":"null"}]},"secret_fields":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Secret Fields"},"enable_ref":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Enable Ref"},"provider_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Provider Id"},"external_ref":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"External Ref"},"user_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Account Id","description":"Local user to mint per-run (jit mode); NULL clears/unbinds"}},"additionalProperties":false,"type":"object","title":"CredentialUpdate","description":"Update a credential. ``type`` is immutable (it fixes the secret shape).\n\n``secret_fields`` here carries the sentinel convention **per secret field**: a\nvalue equal to the sentinel keeps the stored value, an empty string clears that\nfield, any other value re-encrypts. Non-secret fields (``username``) are exempt\nfrom the sentinel — the submitted value is always taken verbatim (there is\nnothing hidden to \"keep\"). The merged result is validated in the service (it\nneeds the stored values the sentinel refers to)."},"CrlStatusEntry":{"properties":{"ca_subject_dn":{"type":"string","title":"Ca Subject Dn"},"ca_file":{"type":"string","title":"Ca File"},"hash":{"type":"string","title":"Hash"},"crl_symlink":{"type":"string","title":"Crl Symlink"},"crl_present":{"type":"boolean","title":"Crl Present"},"crl_last_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Crl Last Update"},"crl_next_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Crl Next Update"},"crl_is_expired":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Crl Is Expired"},"revoked_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revoked Count"},"source":{"type":"string","title":"Source"}},"type":"object","required":["ca_subject_dn","ca_file","hash","crl_symlink","crl_present","source"],"title":"CrlStatusEntry","description":"CRL status for a single CA in the crl/ directory."},"CrlStatusResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/CrlStatusEntry"},"type":"array","title":"Entries","default":[]},"total_cas":{"type":"integer","title":"Total Cas","default":0},"total_crls_present":{"type":"integer","title":"Total Crls Present","default":0},"total_crls_missing":{"type":"integer","title":"Total Crls Missing","default":0},"crl_dir_exists":{"type":"boolean","title":"Crl Dir Exists","default":false}},"type":"object","title":"CrlStatusResponse","description":"CRL deployment status for all CAs in the crl/ directory."},"CsrParseData":{"properties":{"csr_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Csr Pem"}},"type":"object","required":["csr_pem"],"title":"CsrParseData","description":"Parse/preview an externally generated CSR before signing."},"CsrParseResult":{"properties":{"subject_dn":{"type":"string","title":"Subject Dn"},"subject_cn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Cn"},"subject_o":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject O"},"key_algorithm":{"type":"string","title":"Key Algorithm"},"san_entries":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array","title":"San Entries"},"is_weak_key":{"type":"boolean","title":"Is Weak Key","default":false},"signature_valid":{"type":"boolean","title":"Signature Valid","default":true}},"type":"object","required":["subject_dn","key_algorithm"],"title":"CsrParseResult","description":"Decoded contents of a CSR, for preview before signing."},"CsrResult":{"properties":{"csr_pem":{"type":"string","title":"Csr Pem"},"private_key_id":{"type":"string","format":"uuid","title":"Private Key Id","description":"Reference to stored private key for later cert import"}},"type":"object","required":["csr_pem","private_key_id"],"title":"CsrResult","description":"Response from CSR generation."},"DaemonLogFileSchema":{"properties":{"group":{"type":"string","title":"Group"},"name":{"type":"string","title":"Name"},"rel_path":{"type":"string","title":"Rel Path"},"size_bytes":{"type":"integer","title":"Size Bytes"},"modified_at":{"type":"string","format":"date-time","title":"Modified At"}},"type":"object","required":["group","name","rel_path","size_bytes","modified_at"],"title":"DaemonLogFileSchema","description":"One live daemon log file available for download."},"DaemonLogsResponse":{"properties":{"max_lines":{"type":"integer","title":"Max Lines"},"default_max_lines":{"type":"integer","title":"Default Max Lines"},"live_files":{"items":{"$ref":"#/components/schemas/DaemonLogFileSchema"},"type":"array","title":"Live Files"},"live_total_bytes":{"type":"integer","title":"Live Total Bytes"},"forensic_groups":{"items":{"$ref":"#/components/schemas/ForensicGroup"},"type":"array","title":"Forensic Groups"},"forensic_total_bytes":{"type":"integer","title":"Forensic Total Bytes"}},"type":"object","required":["max_lines","default_max_lines","live_files","live_total_bytes","forensic_groups","forensic_total_bytes"],"title":"DaemonLogsResponse","description":"Daemon log rotation state: line cap + live logs + forensic archive."},"DaemonMaxLinesResponse":{"properties":{"max_lines":{"type":"integer","title":"Max Lines"}},"type":"object","required":["max_lines"],"title":"DaemonMaxLinesResponse","description":"Echo of the stored line cap after an update."},"DaemonMaxLinesUpdate":{"properties":{"max_lines":{"type":"integer","maximum":10000000.0,"minimum":0.0,"title":"Max Lines","description":"Lines kept per daemon *.log file (0 disables trimming)."}},"additionalProperties":false,"type":"object","required":["max_lines"],"title":"DaemonMaxLinesUpdate","description":"Set the per-file line cap applied by the daemon-side trimmer."},"DashboardPref":{"properties":{"widgets":{"items":{"$ref":"#/components/schemas/DashboardWidgetPref"},"type":"array","maxItems":50,"title":"Widgets"}},"additionalProperties":false,"type":"object","required":["widgets"],"title":"DashboardPref","description":"Dashboard section of the UI preferences blob."},"DashboardWidgetPref":{"properties":{"id":{"type":"string","maxLength":64,"minLength":1,"title":"Id"},"enabled":{"type":"boolean","title":"Enabled"},"size":{"anyOf":[{"type":"string","enum":["third","half","full"]},{"type":"null"}],"title":"Size"}},"additionalProperties":false,"type":"object","required":["id","enabled"],"title":"DashboardWidgetPref","description":"One dashboard widget entry in a user's saved layout.\n\nArray order = display order. Unknown ids are tolerated on read (a widget may\nhave been removed), but the shape is validated strictly on write.\n\n``size`` is an optional per-widget width override (``third`` / ``half`` /\n``full``, mapping to the bootstrap col footprint). Absent means \"use the\nwidget's registry-declared default size\" — existing saved layouts that\npredate this field stay valid (backward compatible). Any other value is\nrejected with 422 by the literal enum."},"DatasetCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique dataset name"},"template_id":{"type":"string","title":"Template Id","description":"Stable id of the in-code template this dataset presets"},"filter_values":{"additionalProperties":true,"type":"object","title":"Filter Values","description":"Relative filter values"},"display_config":{"additionalProperties":true,"type":"object","title":"Display Config","description":"Kind-specific display config (§5.1)"}},"additionalProperties":false,"type":"object","required":["name","template_id"],"title":"DatasetCreate","description":"Create a dataset over a template, with its relative config."},"DatasetExportRequest":{"properties":{"format":{"$ref":"#/components/schemas/app__modules__reports__contract__ExportFormat"},"period_override":{"anyOf":[{"$ref":"#/components/schemas/PeriodOverride"},{"type":"null"}]},"limit":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Limit","description":"Row cap (None → server ceiling)"}},"additionalProperties":false,"type":"object","required":["format"],"title":"DatasetExportRequest","description":"Export a dataset to a flat file (§6). Format-agnostic so PDF (wave 2) reuses it.\n\n``limit`` caps the exported rows (``None`` → the server ceiling\n``reports_max_export_rows``); it is clamped server-side to\n``1..reports_max_export_rows`` and is independent of the dataset's readability\nrow limit. ``period_override`` optionally replaces the stored window for this\nexport only."},"DatasetResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"template_id":{"type":"string","title":"Template Id"},"filter_values":{"additionalProperties":true,"type":"object","title":"Filter Values"},"display_config":{"additionalProperties":true,"type":"object","title":"Display Config"},"template_available":{"type":"boolean","title":"Template Available","description":"False when the referenced template was dropped by a release"},"export_formats":{"items":{"type":"string"},"type":"array","title":"Export Formats","description":"Formats this dataset may be delivered/exported as (raw table → csv/xlsx/pdf, preset → pdf)."},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","template_id","filter_values","display_config","template_available","created_at","updated_at"],"title":"DatasetResponse","description":"A dataset's stored shape plus whether its template still exists."},"DatasetRunRequest":{"properties":{},"additionalProperties":false,"type":"object","title":"DatasetRunRequest","description":"Run a saved dataset. No body fields in wave 1a — the config is stored;\nthe relative period is resolved to bounds at this moment. (The absolute-period\nexport override is a later wave; the engine seam already exists.)"},"DatasetRunResponse":{"properties":{"template_id":{"type":"string","title":"Template Id"},"results":{"items":{"$ref":"#/components/schemas/QueryResultResponse"},"type":"array","title":"Results"}},"type":"object","required":["template_id","results"],"title":"DatasetRunResponse","description":"A dataset run's tidy results — same shape as a template run."},"DatasetUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name","description":"New unique dataset name"},"filter_values":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Filter Values","description":"Replacement relative filter values"},"display_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Display Config","description":"Replacement display config"}},"additionalProperties":false,"type":"object","title":"DatasetUpdate","description":"Update a dataset. ``template_id`` is immutable and therefore omitted."},"DecommissionedNodeResponse":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id"},"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"}},"type":"object","required":["node_id","name","status"],"title":"DecommissionedNodeResponse"},"DeviceBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"network_object":{"$ref":"#/components/schemas/NetworkObjectBrief"},"is_enabled":{"type":"boolean","title":"Is Enabled"}},"type":"object","required":["id","name","network_object","is_enabled"],"title":"DeviceBrief","description":"Minimal device info embedded in DeviceGroupDetailResponse."},"DeviceCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique device name"},"hostname":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Hostname","description":"DNS hostname"},"network_object_id":{"type":"string","format":"uuid","title":"Network Object Id","description":"FK to NetworkObject providing the device IP/subnet"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Tacacs Key","description":"TACACS+ shared secret. NULL = inherit from group/global."},"radius_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Radius Secret","description":"RADIUS shared secret. NULL = inherit from group/global."},"protocol_flags":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Protocol Flags","description":"AAA protocol flags: {tacacs, radius, nac}"},"vendor":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Vendor"},"vendor_dict_key":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Vendor Dict Key","description":"Optional NAC vendor dictionary key for CoA. NULL = auto-detect/default."},"platform":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Platform"},"location":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Location"},"notes":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Notes"},"tags":{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":64,"title":"Tags"},"single_connection":{"type":"boolean","title":"Single Connection","description":"tac_plus-ng single-connection mode","default":false},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true},"coa_port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Coa Port","description":"CoA port override. NULL = inherit from group/global."},"coa_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Coa Secret","description":"CoA shared secret. NULL = inherit from group/global."},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id","description":"Optional NCM collector. NULL = not tracked."}},"additionalProperties":false,"type":"object","required":["name","network_object_id"],"title":"DeviceCreate","description":"Schema for creating a new device."},"DeviceGroupCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique group name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Tacacs Key","description":"TACACS+ shared secret for group. NULL = inherit from global."},"radius_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Radius Secret","description":"RADIUS shared secret for group. NULL = inherit from global."},"coa_port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Coa Port","description":"CoA port override for group. NULL = inherit from global nac.coa_port."},"coa_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Coa Secret","description":"CoA shared secret for group. NULL = inherit from global nac.coa_secret."},"tags":{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":64,"title":"Tags"}},"additionalProperties":false,"type":"object","required":["name"],"title":"DeviceGroupCreate","description":"Schema for creating a new device group."},"DeviceGroupDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tacacs Key"},"radius_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Radius Secret"},"coa_port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Coa Port"},"coa_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coa Secret"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"device_count":{"type":"integer","title":"Device Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"devices":{"items":{"$ref":"#/components/schemas/DeviceBrief"},"type":"array","title":"Devices"}},"type":"object","required":["id","name","created_at","updated_at"],"title":"DeviceGroupDetailResponse","description":"Extended device group response with member list."},"DeviceGroupListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"device_count":{"type":"integer","title":"Device Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","created_at"],"title":"DeviceGroupListResponse","description":"Abbreviated device group for list views."},"DeviceGroupMemberAction":{"properties":{"device_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"minItems":1,"title":"Device Ids","description":"Device IDs to add or remove"}},"additionalProperties":false,"type":"object","required":["device_ids"],"title":"DeviceGroupMemberAction","description":"Schema for adding/removing devices from a group."},"DeviceGroupRefItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"device_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Device Count"}},"type":"object","required":["id","name"],"title":"DeviceGroupRefItem","description":"Device-group reference enriched with its device count (detail view only)."},"DeviceGroupResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tacacs Key"},"radius_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Radius Secret"},"coa_port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Coa Port"},"coa_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coa Secret"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"device_count":{"type":"integer","title":"Device Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","created_at","updated_at"],"title":"DeviceGroupResponse","description":"Full device group response."},"DeviceGroupUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Tacacs Key"},"radius_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Radius Secret"},"coa_port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Coa Port"},"coa_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Coa Secret"},"tags":{"anyOf":[{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":64},{"type":"null"}],"title":"Tags"}},"additionalProperties":false,"type":"object","title":"DeviceGroupUpdate","description":"Schema for updating a device group.\n\nEncrypted field handling (same as Device):\n- sentinel = keep, empty = clear, other = encrypt and save."},"DeviceInheritanceResponse":{"properties":{"tacacs_key":{"$ref":"#/components/schemas/FieldInheritance"},"radius_secret":{"$ref":"#/components/schemas/FieldInheritance"},"coa_secret":{"$ref":"#/components/schemas/FieldInheritance"},"coa_port":{"$ref":"#/components/schemas/FieldInheritance"}},"type":"object","required":["tacacs_key","radius_secret","coa_secret","coa_port"],"title":"DeviceInheritanceResponse","description":"Inheritance source per inheritable device field (tacacs/radius/coa)."},"DeviceListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"network_object":{"$ref":"#/components/schemas/NetworkObjectBrief"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"vendor_dict_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Dict Key"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"protocol_flags":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Protocol Flags"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"group_count":{"type":"integer","title":"Group Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","network_object","protocol_flags","is_enabled","created_at"],"title":"DeviceListResponse","description":"Abbreviated device for list views."},"DeviceNetworkRef":{"properties":{"entry_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entry Type"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start"},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End"}},"type":"object","title":"DeviceNetworkRef","description":"A device's underlying network object — address + type for display."},"DeviceRefItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"network_object":{"anyOf":[{"$ref":"#/components/schemas/DeviceNetworkRef"},{"type":"null"}]}},"type":"object","required":["id","name"],"title":"DeviceRefItem","description":"Device reference enriched with its address + type (detail view only)."},"DeviceResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"network_object_id":{"type":"string","format":"uuid","title":"Network Object Id"},"network_object":{"$ref":"#/components/schemas/NetworkObjectBrief"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tacacs Key"},"radius_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Radius Secret"},"protocol_flags":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Protocol Flags"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"vendor_dict_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Dict Key"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"single_connection":{"type":"boolean","title":"Single Connection"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"coa_port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Coa Port"},"coa_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coa Secret"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id"},"group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Group Ids"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","network_object_id","network_object","protocol_flags","single_connection","is_enabled","created_at","updated_at"],"title":"DeviceResponse","description":"Full device response. Encrypted fields show sentinel if set."},"DeviceUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"hostname":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Hostname"},"network_object_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Network Object Id"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"tacacs_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Tacacs Key"},"radius_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Radius Secret"},"protocol_flags":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Protocol Flags"},"vendor":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Vendor"},"vendor_dict_key":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Vendor Dict Key"},"platform":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Platform"},"location":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Location"},"notes":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Notes"},"tags":{"anyOf":[{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":64},{"type":"null"}],"title":"Tags"},"single_connection":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Single Connection"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"},"coa_port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Coa Port"},"coa_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Coa Secret"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id"}},"additionalProperties":false,"type":"object","title":"DeviceUpdate","description":"Schema for updating a device.\n\nEncrypted field handling:\n- sentinel (\"••••••••\") = keep current value (no change)\n- empty string (\"\") = clear the field (set to NULL)\n- any other value = encrypt and save"},"DhcpDnsConfig":{"properties":{"dhcp_enabled":{"type":"boolean","title":"Dhcp Enabled","default":false},"dhcp_interface":{"type":"string","maxLength":32,"title":"Dhcp Interface","default":"eth0"},"dhcp_range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dhcp Range Start"},"dhcp_range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dhcp Range End"},"dhcp_subnet_mask":{"type":"string","title":"Dhcp Subnet Mask","default":"255.255.255.0"},"dhcp_gateway":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dhcp Gateway"},"dns_enabled":{"type":"boolean","title":"Dns Enabled","default":false},"dns_intercept_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dns Intercept Ip"},"dns_upstream":{"type":"string","title":"Dns Upstream","default":"8.8.8.8"}},"type":"object","title":"DhcpDnsConfig","description":"Standalone DHCP / DNS settings for a portal.\n\nRendered into the bundle .env. Empty IP fields are allowed — the container\nfalls back to its own interface IP (``hostname -i``) at runtime for\ngateway / DNS-intercept. The DHCP lease time is intentionally NOT exposed\nhere: it is fixed short (30s) in the dnsmasq generator so a client quickly\nre-requests an address after a VLAN switch (and can be overridden on the\nserver side if ever needed).\n\nAll address fields are validated as IPv4. Empty string / None disables the\nrespective default."},"DirectoryTypeResponse":{"properties":{"key":{"type":"string","title":"Key"},"supports_mschapv2":{"type":"boolean","title":"Supports Mschapv2"},"supports_computer_sync":{"type":"boolean","title":"Supports Computer Sync"},"requires_domain_suffix":{"type":"boolean","title":"Requires Domain Suffix"},"requires_netbios":{"type":"boolean","title":"Requires Netbios"},"defaults":{"additionalProperties":true,"type":"object","title":"Defaults","description":"Prefill for an empty create form: search filters and attribute maps."}},"type":"object","required":["key","supports_mschapv2","supports_computer_sync","requires_domain_suffix","requires_netbios"],"title":"DirectoryTypeResponse","description":"One selectable directory type, as the create flow sees it.\n\nCarries no prose: labels and explanations are UI strings and live in the\nfrontend locales, keyed by ``key``. What travels is what the frontend cannot\ninvent — the capabilities that decide which tabs exist, and the defaults\nthat prefill the form. Serving the defaults from here rather than repeating\nthem in the form is the point: they were duplicated as literals on both\nsides, one copy of which was bound to drift."},"DiskMetrics":{"properties":{"device":{"type":"string","title":"Device"},"mountpoint":{"type":"string","title":"Mountpoint"},"fstype":{"type":"string","title":"Fstype"},"total_bytes":{"type":"integer","title":"Total Bytes"},"used_bytes":{"type":"integer","title":"Used Bytes"},"free_bytes":{"type":"integer","title":"Free Bytes"},"percent":{"type":"number","title":"Percent"},"total_human":{"type":"string","title":"Total Human"},"used_human":{"type":"string","title":"Used Human"},"free_human":{"type":"string","title":"Free Human"}},"type":"object","required":["device","mountpoint","fstype","total_bytes","used_bytes","free_bytes","percent","total_human","used_human","free_human"],"title":"DiskMetrics","description":"Disk metric snapshot for a single partition."},"DomainJoinRequest":{"properties":{"use_configured_account":{"type":"boolean","title":"Use Configured Account","description":"Join with this configuration's own LDAP account instead of typed credentials. Possible because Active Directory's machine-account quota lets any authenticated account create computer objects in the domain's DEFAULT container — no delegation.","default":false},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username","description":"A domain account allowed to create computer objects — Domain Admin is not required."},"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"machine_name":{"anyOf":[{"type":"string","maxLength":15},{"type":"null"}],"title":"Machine Name","description":"Name of this node's computer object in Active Directory (NetBIOS limit: 15 characters)."},"organizational_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Organizational Unit","description":"Samba createcomputer path — from the domain root DOWNWARDS, like a filesystem path: OU=Servers,OU=Taranac,DC=lab,DC=taranac,DC=pro is written 'Taranac/Servers'. Empty uses the domain's default computer container (a CN container, not an OU)."}},"additionalProperties":false,"type":"object","title":"DomainJoinRequest","description":"One join: what to create, where, and who may create it.\n\nThe machine name and the OU live here rather than in the settings form\nbecause they are used at exactly one moment. Left on a settings page they are\nfields that silently do nothing: after a join the name lives in the machine\naccount and in Active Directory, and editing it changes neither until the\nnext join.\n\nThe credentials are never stored, logged, or echoed back."},"DomainJoinResponse":{"properties":{"state":{"type":"string","title":"State","description":"joined | failed | joining (still running — poll the status endpoint)"},"joined":{"type":"boolean","title":"Joined"},"detail":{"type":"string","title":"Detail","default":""},"node":{"$ref":"#/components/schemas/NodeMembershipResponse"},"timed_out":{"type":"boolean","title":"Timed Out","description":"The join outlived the request budget and is still running on the sidecar.","default":false},"unclaimed":{"type":"boolean","title":"Unclaimed","description":"Nobody picked the request up — the winbind service is not processing requests.","default":false}},"type":"object","required":["state","joined","node"],"title":"DomainJoinResponse"},"DomainSettingsResponse":{"properties":{"config_id":{"type":"string","title":"Config Id"},"enabled":{"type":"boolean","title":"Enabled"},"machine_ou":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Machine Ou"},"machine_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Machine Name"},"effective_machine_name":{"type":"string","title":"Effective Machine Name","description":"The name THIS node would actually join under — the explicit one when set, otherwise the derived TARANAC-NN. Computed by the same code the join uses, so the form cannot show one name while the product uses another.","default":""},"ldap_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Account"},"ldap_account_usable":{"type":"boolean","title":"Ldap Account Usable","description":"Whether that account can be used for a join. A distinguished-name bind DN cannot: `net ads join` accepts DOMAIN\\user or user@realm, not a DN.","default":false}},"type":"object","required":["config_id","enabled"],"title":"DomainSettingsResponse","description":"The MS-CHAPv2 section of one LDAP configuration."},"DomainSettingsUpdate":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"machine_ou":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Machine Ou","description":"Samba createcomputer path — the OU path from the domain root DOWNWARDS, like a filesystem path. OU=Servers,OU=Taranac,DC=lab,DC=taranac,DC=pro is written 'Taranac/Servers'."},"machine_name":{"anyOf":[{"type":"string","maxLength":15},{"type":"null"}],"title":"Machine Name","description":"Machine account name in Active Directory (NetBIOS limit: 15 characters)."}},"type":"object","title":"DomainSettingsUpdate"},"DomainStatusResponse":{"properties":{"nodes":{"items":{"$ref":"#/components/schemas/NodeMembershipResponse"},"type":"array","title":"Nodes"},"owner_config_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Config Id","description":"Which LDAP configuration currently has MS-CHAPv2 enabled, if any."},"enabled":{"type":"boolean","title":"Enabled","description":"Whether MS-CHAPv2 is enabled on THIS configuration."}},"type":"object","required":["nodes","enabled"],"title":"DomainStatusResponse","description":"Membership across the installation.\n\nA LIST of nodes even on a single node: a machine account is node-local, so\nthe shape must not imply one shared membership."},"EapTlsCaCertInfo":{"properties":{"subject_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Dn"},"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"not_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not Before"},"not_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not After"},"serial_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial Number"},"key_algorithm":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Key Algorithm"},"is_ca":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Ca"}},"type":"object","title":"EapTlsCaCertInfo","description":"The same metadata under the name the EAP-TLS response field already used."},"EapTlsCrlInfo":{"properties":{"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"last_update":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Update"},"next_update":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Update"},"revoked_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revoked Count"}},"type":"object","title":"EapTlsCrlInfo","description":"Parsed CRL metadata returned in LDAP config responses."},"EffectivePermissionsResponse":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"username":{"type":"string","title":"Username"},"is_admin":{"type":"boolean","title":"Is Admin","default":false},"permissions":{"additionalProperties":true,"type":"object","title":"Permissions"}},"type":"object","required":["user_id","username","permissions"],"title":"EffectivePermissionsResponse","description":"Schema for a user's effective (merged) permissions."},"EmailLayoutPreviewResponse":{"properties":{"body_html":{"type":"string","title":"Body Html"}},"type":"object","required":["body_html"],"title":"EmailLayoutPreviewResponse","description":"POST /email/layout/preview response — rendered layout with sample content."},"EmailLayoutResponse":{"properties":{"header_html":{"type":"string","title":"Header Html"},"footer_html":{"type":"string","title":"Footer Html"},"subject_prefix":{"type":"string","title":"Subject Prefix"}},"type":"object","required":["header_html","footer_html","subject_prefix"],"title":"EmailLayoutResponse","description":"GET /email/layout response — current header, footer, and subject prefix."},"EmailLayoutUpdateRequest":{"properties":{"header_html":{"type":"string","maxLength":10000,"title":"Header Html"},"footer_html":{"type":"string","maxLength":10000,"title":"Footer Html"},"subject_prefix":{"type":"string","maxLength":50,"title":"Subject Prefix","default":""}},"additionalProperties":false,"type":"object","required":["header_html","footer_html"],"title":"EmailLayoutUpdateRequest","description":"PUT /email/layout request body."},"EmailSendTestRequest":{"properties":{"to_email":{"type":"string","maxLength":254,"format":"email","title":"To Email","description":"Recipient address for the test email"}},"additionalProperties":false,"type":"object","required":["to_email"],"title":"EmailSendTestRequest","description":"POST /email/smtp/send-test request body."},"EmailSendTestResponse":{"properties":{"status":{"type":"string","title":"Status"},"to":{"type":"string","title":"To"}},"type":"object","required":["status","to"],"title":"EmailSendTestResponse","description":"POST /email/smtp/send-test response."},"EmailTemplateListResponse":{"properties":{"templates":{"items":{"$ref":"#/components/schemas/EmailTemplateResponse"},"type":"array","title":"Templates"}},"type":"object","required":["templates"],"title":"EmailTemplateListResponse","description":"GET /email/templates response."},"EmailTemplatePreviewRequest":{"properties":{"context":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":200},{"type":"null"}],"title":"Context","description":"Sample render variables"}},"additionalProperties":false,"type":"object","title":"EmailTemplatePreviewRequest","description":"POST /email/templates/{type}/{lang}/preview request body."},"EmailTemplatePreviewResponse":{"properties":{"subject":{"type":"string","title":"Subject"},"body_html":{"type":"string","title":"Body Html"}},"type":"object","required":["subject","body_html"],"title":"EmailTemplatePreviewResponse","description":"POST /email/templates/{type}/{lang}/preview response."},"EmailTemplateResetResponse":{"properties":{"message":{"type":"string","title":"Message"},"template_type":{"type":"string","title":"Template Type"},"lang":{"type":"string","title":"Lang"}},"type":"object","required":["message","template_type","lang"],"title":"EmailTemplateResetResponse","description":"POST /email/templates/{type}/{lang}/reset response."},"EmailTemplateResponse":{"properties":{"id":{"type":"string","title":"Id"},"template_type":{"type":"string","title":"Template Type"},"lang":{"type":"string","title":"Lang"},"subject":{"type":"string","title":"Subject"},"body_html":{"type":"string","title":"Body Html"},"body_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Text"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_custom":{"type":"boolean","title":"Is Custom"}},"type":"object","required":["id","template_type","lang","subject","body_html","is_custom"],"title":"EmailTemplateResponse","description":"Single email template in list/detail responses."},"EmailTemplateUpdateRequest":{"properties":{"subject":{"type":"string","maxLength":500,"minLength":1,"title":"Subject","description":"Email subject line"},"body_html":{"type":"string","maxLength":100000,"minLength":1,"title":"Body Html","description":"HTML body"},"body_text":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Body Text","description":"Optional plain-text body"}},"additionalProperties":false,"type":"object","required":["subject","body_html"],"title":"EmailTemplateUpdateRequest","description":"PUT /email/templates/{type}/{lang} request body."},"EmailTestConnectionResponse":{"properties":{"status":{"type":"string","title":"Status"},"host":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host"},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port"}},"type":"object","required":["status"],"title":"EmailTestConnectionResponse","description":"POST /email/smtp/test-connection response."},"EnableConfig":{"properties":{"mode":{"type":"string","enum":["inherit","login_password","custom","deny","permit"],"title":"Mode","default":"inherit"},"password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Password","description":"Enable password. Sentinel = keep, empty = clear, other = encrypt."}},"additionalProperties":false,"type":"object","title":"EnableConfig","description":"Enable configuration within a profile.\n\nModes:\n- inherit: resolve from User → Group → Global (default)\n- login_password: use the user's login credentials for enable\n- custom: separate password (password field required)\n- deny: block enable access\n- permit: always allow enable without password (tac_plus-ng default)"},"EnableResolved":{"properties":{"mode":{"type":"string","title":"Mode","description":"Resolved enable mode: login_password | custom | deny | permit | inherit"},"level":{"type":"string","title":"Level","description":"Where the mode was resolved from: 'user', 'group:<name>', 'profile:<name>', 'global'"},"has_password":{"type":"boolean","title":"Has Password","description":"True if a custom enable password is configured at this level","default":false}},"type":"object","required":["mode","level"],"title":"EnableResolved","description":"Resolved enable password mode from inheritance chain.\n\nShows which level of the chain won and the resulting mode."},"EnabledUpdateRequest":{"properties":{"enabled":{"type":"boolean","title":"Enabled","description":"Desired persistent enabled state"}},"type":"object","required":["enabled"],"title":"EnabledUpdateRequest","description":"Request body for enabling/disabling a job."},"EndpointBriefResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"mac_address":{"type":"string","title":"Mac Address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"status":{"type":"string","title":"Status"},"assigned_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned By"}},"type":"object","required":["id","mac_address","status"],"title":"EndpointBriefResponse","description":"Abbreviated endpoint for inline embedding in other resources.\n\nIntentionally narrower than EndpointListResponse:\n- no nested endpoint_group (callers embedding this already know the group)\n- no timestamps (not needed for preview UI)"},"EndpointBulkAction":{"properties":{"ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":5000,"minItems":1,"title":"Ids","description":"Endpoint IDs to act on"}},"additionalProperties":false,"type":"object","required":["ids"],"title":"EndpointBulkAction","description":"Schema for bulk operations on endpoints."},"EndpointBulkReassign":{"properties":{"ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":5000,"minItems":1,"title":"Ids"},"endpoint_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":200,"title":"Endpoint Group Ids","description":"Groups each selected endpoint should belong to after this call (replace-set). An empty list removes from all groups."}},"additionalProperties":false,"type":"object","required":["ids"],"title":"EndpointBulkReassign","description":"Schema for bulk group membership replacement."},"EndpointCreate":{"properties":{"mac_address":{"type":"string","title":"Mac Address","description":"MAC address (any common format accepted)"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Optional display name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description","description":"Optional description"},"status":{"type":"string","enum":["known","unknown","blocked"],"title":"Status","description":"Initial status (inactive not allowed on create)","default":"known"},"notes":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Notes","description":"Administrator notes"},"endpoint_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":200,"title":"Endpoint Group Ids","description":"Groups to assign on creation. Endpoints may belong to multiple groups."}},"additionalProperties":false,"type":"object","required":["mac_address"],"title":"EndpointCreate","description":"Schema for creating an endpoint manually."},"EndpointDiscoveryBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source_type":{"type":"string","title":"Source Type"},"discovered_at":{"type":"string","format":"date-time","title":"Discovered At"},"last_updated_at":{"type":"string","format":"date-time","title":"Last Updated At"},"data":{"additionalProperties":true,"type":"object","title":"Data"}},"type":"object","required":["id","source_type","discovered_at","last_updated_at"],"title":"EndpointDiscoveryBrief","description":"Discovery record for inline display in endpoint detail."},"EndpointGroupBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"},"assigned_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned By"}},"type":"object","required":["id","name"],"title":"EndpointGroupBrief","description":"Abbreviated endpoint group for inline display."},"EndpointGroupCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"Unique group name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"color":{"anyOf":[{"type":"string","maxLength":7},{"type":"null"}],"title":"Color","description":"HEX color (#FF5733)"},"icon":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Icon","description":"Icon name"}},"additionalProperties":false,"type":"object","required":["name"],"title":"EndpointGroupCreate","description":"Schema for creating a new endpoint group."},"EndpointGroupDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_system":{"type":"boolean","title":"Is System","default":false},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"classification_rules":{"items":{"$ref":"#/components/schemas/ClassificationRuleResponse"},"type":"array","title":"Classification Rules","description":"Full list of classification rules, ordered by created_at asc."},"members_preview":{"items":{"$ref":"#/components/schemas/EndpointBriefResponse"},"type":"array","title":"Members Preview","description":"Up to 10 most recently assigned members (by assigned_at desc). For the full paginated list use GET /endpoint-groups/{id}/members."},"members_total":{"type":"integer","title":"Members Total","description":"Total member count in this group.","default":0}},"type":"object","required":["id","name","created_at","updated_at"],"title":"EndpointGroupDetailResponse","description":"Detail response for GET /endpoint-groups/{id}.\n\nExtends the base fields with classification rules (full list, ordered\nby created_at asc — stable, deterministic order) and a members preview\n(up to MEMBERS_PREVIEW_LIMIT most recently assigned endpoints).\n\nNote: field name is `members_total` (not `endpoint_count`) to live\nalongside `members_preview` and make the \"N total, showing 10\" UX\nself-documenting. The underlying value comes from the same cached\nEndpointGroup.endpoint_count column."},"EndpointGroupListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_system":{"type":"boolean","title":"Is System","default":false},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"},"endpoint_count":{"type":"integer","title":"Endpoint Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","created_at"],"title":"EndpointGroupListResponse","description":"Abbreviated endpoint group for list views."},"EndpointGroupMemberAction":{"properties":{"endpoint_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":5000,"minItems":1,"title":"Endpoint Ids","description":"Endpoint IDs to add"}},"additionalProperties":false,"type":"object","required":["endpoint_ids"],"title":"EndpointGroupMemberAction","description":"Schema for adding an endpoint to a group."},"EndpointGroupResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_system":{"type":"boolean","title":"Is System","default":false},"color":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Color"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"},"endpoint_count":{"type":"integer","title":"Endpoint Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","created_at","updated_at"],"title":"EndpointGroupResponse","description":"Full endpoint group response.\n\nUsed by mutating endpoints (POST, PUT, members add/remove) that return the\nupdated group. For the GET detail endpoint — which also inlines rules and\na members preview — see EndpointGroupDetailResponse."},"EndpointGroupUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"color":{"anyOf":[{"type":"string","maxLength":7},{"type":"null"}],"title":"Color"},"icon":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Icon"}},"additionalProperties":false,"type":"object","title":"EndpointGroupUpdate","description":"Schema for updating an endpoint group. All fields optional."},"EndpointListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"mac_address":{"type":"string","title":"Mac Address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"status":{"type":"string","title":"Status"},"persistence_type":{"type":"string","title":"Persistence Type"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Seen At"},"auth_type_last":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Type Last"},"endpoint_groups":{"items":{"$ref":"#/components/schemas/EndpointGroupBrief"},"type":"array","title":"Endpoint Groups","description":"All groups this endpoint currently belongs to."},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","mac_address","status","persistence_type","created_at"],"title":"EndpointListResponse","description":"Abbreviated endpoint for list views."},"EndpointReassign":{"properties":{"endpoint_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":200,"title":"Endpoint Group Ids","description":"Groups the endpoint should belong to after this call (replace-set)."}},"additionalProperties":false,"type":"object","title":"EndpointReassign","description":"Schema for replacing an endpoint's group memberships.\n\nThe provided list fully replaces the endpoint's current memberships.\nAn empty list removes the endpoint from all groups."},"EndpointResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"mac_address":{"type":"string","title":"Mac Address"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"persistence_type":{"type":"string","title":"Persistence Type"},"discovery_type":{"type":"string","title":"Discovery Type"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"oui_prefix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oui Prefix"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"os_hint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os Hint"},"first_discovered_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Discovered By"},"first_discovered_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Discovered At"},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Seen At"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"cert_identity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cert Identity"},"cert_issuer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cert Issuer"},"auth_type_last":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Type Last"},"registered_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Registered By User Id"},"endpoint_groups":{"items":{"$ref":"#/components/schemas/EndpointGroupBrief"},"type":"array","title":"Endpoint Groups","description":"All groups this endpoint currently belongs to."},"discoveries":{"items":{"$ref":"#/components/schemas/EndpointDiscoveryBrief"},"type":"array","title":"Discoveries","description":"Discovery records from all sources (radius, certificate, ldap, etc.)."},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","mac_address","status","persistence_type","discovery_type","created_at","updated_at"],"title":"EndpointResponse","description":"Full endpoint response for detail views."},"EndpointUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"status":{"anyOf":[{"type":"string","enum":["known","unknown","blocked"]},{"type":"null"}],"title":"Status"},"notes":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Notes"}},"additionalProperties":false,"type":"object","title":"EndpointUpdate","description":"Schema for updating an endpoint. All fields optional.\n\n``mac_address`` and ``endpoint_group_ids`` are intentionally absent — the\nMAC is immutable (identity) and group membership is changed via the\ndedicated reassign action; extra=\"forbid\" makes the client send neither."},"EnrollRequest":{"properties":{"token":{"type":"string","minLength":1,"title":"Token","description":"The one-time enrollment secret."},"cert_pem":{"type":"string","minLength":1,"title":"Cert Pem","description":"The collector's self-signed X.509 cert (PEM) carrying its Ed25519 public key."},"release_version":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Release Version","description":"Collector RELEASE (build) version — recorded for the compat display."},"contract_version":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Contract Version","description":"Collector CONTRACT version (= SNAPSHOT_IDENTITY_VERSION) — compat token."}},"additionalProperties":false,"type":"object","required":["token","cert_pem"],"title":"EnrollRequest","description":"Collector's enrollment redemption — token + its self-signed cert PEM.\n\nToken-authenticated (no user session): the one-time secret is the credential."},"EnrollResponse":{"properties":{"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"collector_name":{"type":"string","title":"Collector Name"},"identity_fingerprint":{"type":"string","title":"Identity Fingerprint","description":"SHA-256 hex of the pinned cert (the collector's key-id)."},"identity_issued_at":{"type":"string","format":"date-time","title":"Identity Issued At"}},"type":"object","required":["collector_id","collector_name","identity_fingerprint","identity_issued_at"],"title":"EnrollResponse","description":"Minimal success acknowledgement — the collector's pinned identity."},"EnrollmentTokenIssueRequest":{"properties":{"ttl_minutes":{"type":"integer","maximum":10080.0,"minimum":1.0,"title":"Ttl Minutes","description":"Token lifetime in minutes (max 7 days).","default":60}},"additionalProperties":false,"type":"object","title":"EnrollmentTokenIssueRequest","description":"Operator request to mint a one-time enrollment token for a collector."},"EntityCountsResponse":{"properties":{"users":{"type":"integer","title":"Users","default":0},"groups":{"type":"integer","title":"Groups","default":0},"devices":{"type":"integer","title":"Devices","default":0},"device_groups":{"type":"integer","title":"Device Groups","default":0},"network_objects":{"type":"integer","title":"Network Objects","default":0},"aaa_policy_rules":{"type":"integer","title":"Aaa Policy Rules","default":0},"nac_policy_rules":{"type":"integer","title":"Nac Policy Rules","default":0}},"type":"object","title":"EntityCountsResponse","description":"Aggregated entity counters for the dashboard.\n\n``aaa_policy_rules`` / ``nac_policy_rules`` count rows in the respective\nfirst-match-wins policy tables (``aaa_policy_rules`` / ``nac_policy_rules``)\n— the same lists the AAA Policy / NAC Policy pages display."},"EstApprovalLinkDecision":{"properties":{"action":{"type":"string","enum":["approve","reject"],"title":"Action"},"reason":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Reason"}},"type":"object","required":["action"],"title":"EstApprovalLinkDecision","description":"The decision a recipient posts from the link page."},"EstEnrollmentRequestReject":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Reason"}},"type":"object","title":"EstEnrollmentRequestReject","description":"Why the request is being refused — recorded, not shown to the client."},"EstEnrollmentRequestResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"ca_id":{"type":"string","format":"uuid","title":"Ca Id"},"subject_dn":{"type":"string","title":"Subject Dn"},"auth_identity":{"type":"string","title":"Auth Identity"},"auth_method":{"type":"string","title":"Auth Method"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"user_agent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Agent"},"status":{"type":"string","title":"Status"},"reject_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Reason"},"decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Decided At"},"decided_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Decided By"},"issued_certificate_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Issued Certificate Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","ca_id","subject_dn","auth_identity","auth_method","status","created_at","updated_at"],"title":"EstEnrollmentRequestResponse","description":"One enrollment waiting on, or already given, a human decision."},"ExportFormat-Output":{"type":"string","enum":["pdf","csv","xlsx"],"title":"ExportFormat","description":"A file format a report can be exported to (§6)."},"FailedAuthEntry":{"properties":{"username":{"type":"string","title":"Username"},"source_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Ip"},"device_ip":{"type":"string","title":"Device Ip"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"protocol":{"type":"string","title":"Protocol","description":"tacacs | radius"},"fail_count":{"type":"integer","title":"Fail Count"},"last_attempt":{"type":"string","format":"date-time","title":"Last Attempt"},"reasons":{"items":{"type":"string"},"type":"array","title":"Reasons"}},"type":"object","required":["username","device_ip","protocol","fail_count","last_attempt"],"title":"FailedAuthEntry","description":"Single entry in top-failed-auth list."},"FieldInheritance":{"properties":{"source":{"type":"string","enum":["device","group","global","none"],"title":"Source"},"group_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Name"},"value":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value"}},"type":"object","required":["source"],"title":"FieldInheritance","description":"Where an inheritable field resolves from — view-only metadata, no secrets.\n\n``source``: ``device`` (own value), ``group`` (inherited from ``group_name``,\nthe oldest group with a value), ``global`` (a SystemSetting default), or\n``none`` (unset at every level). ``value`` carries the resolved value only\nfor non-secret fields (currently coa_port)."},"FilterSummary":{"properties":{"name":{"type":"string","title":"Name"},"type":{"$ref":"#/components/schemas/FilterType"},"label":{"type":"string","title":"Label"},"required":{"type":"boolean","title":"Required"},"default":{"anyOf":[{"type":"string"},{"type":"integer"},{"type":"boolean"},{"type":"null"}],"title":"Default"},"choices":{"items":{"type":"string"},"type":"array","title":"Choices","default":[]}},"type":"object","required":["name","type","label","required"],"title":"FilterSummary","description":"One declared filter, as exposed by the templates listing.\n\n``label`` is already resolved to the request language (§ module docstring)."},"FilterType":{"type":"string","enum":["datetime","string","int","bool","enum"],"title":"FilterType","description":"Value type of a template filter, driving validation and the UI control."},"ForensicFileSchema":{"properties":{"log_type":{"type":"string","title":"Log Type"},"name":{"type":"string","title":"Name"},"rel_path":{"type":"string","title":"Rel Path"},"size_bytes":{"type":"integer","title":"Size Bytes"},"modified_at":{"type":"string","format":"date-time","title":"Modified At"}},"type":"object","required":["log_type","name","rel_path","size_bytes","modified_at"],"title":"ForensicFileSchema","description":"One file inside a forensic month-bucket (lazy per-month listing)."},"ForensicGroup":{"properties":{"group":{"type":"string","title":"Group"},"months":{"items":{"$ref":"#/components/schemas/MonthBucket"},"type":"array","title":"Months"},"total_bytes":{"type":"integer","title":"Total Bytes"}},"type":"object","required":["group","months","total_bytes"],"title":"ForensicGroup","description":"The forensic archive of one daemon group, grouped into month buckets."},"ForensicMonthDeleteResponse":{"properties":{"group":{"type":"string","title":"Group"},"year_month":{"type":"string","title":"Year Month"},"files_deleted":{"type":"integer","title":"Files Deleted"},"bytes_deleted":{"type":"integer","title":"Bytes Deleted"}},"type":"object","required":["group","year_month","files_deleted","bytes_deleted"],"title":"ForensicMonthDeleteResponse","description":"Result of a manual per-month forensic delete."},"ForensicMonthFilesResponse":{"properties":{"files":{"items":{"$ref":"#/components/schemas/ForensicFileSchema"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"ForensicMonthFilesResponse","description":"Lazy per-month file listing across every ``log_type``."},"ForgotPasswordRequest":{"properties":{"username":{"type":"string","maxLength":150,"minLength":1,"title":"Username"},"captcha_token":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Captcha Token","description":"ALTCHA solution — only required after repeated requests (see captcha_required)."},"website":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Website","description":"Honeypot — must stay empty; a filled value flags an automated submission."}},"type":"object","required":["username"],"title":"ForgotPasswordRequest","description":"POST /auth/forgot-password request body."},"ForgotPasswordResponse":{"properties":{"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"captcha_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Captcha Required"}},"type":"object","title":"ForgotPasswordResponse","description":"POST /auth/forgot-password response (always 200).\n\n``captcha_required`` is set instead of ``message`` when the caller must\nsolve a captcha and resubmit; the reset itself is not attempted in that case."},"GenerateSelfSigned":{"properties":{"common_name":{"type":"string","maxLength":255,"minLength":1,"title":"Common Name","default":"taranac-nac"},"organization":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organization","default":"taranac"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Country"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"San Dns"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa2048"},"validity_days":{"type":"integer","maximum":7300.0,"minimum":1.0,"title":"Validity Days","default":3650}},"type":"object","title":"GenerateSelfSigned","description":"Generate a new self-signed server certificate."},"GenerateTokenResponse":{"properties":{"token":{"type":"string","title":"Token"},"prefix":{"type":"string","title":"Prefix"}},"type":"object","required":["token","prefix"],"title":"GenerateTokenResponse","description":"Response with the generated API token (shown once)."},"Granularity":{"type":"string","enum":["hour","day","week","month"],"title":"Granularity","description":"A time bucket a line (time-series) chart may group by (wave 1b.2).\n\nEach value is deliberately a Postgres ``date_trunc`` field name, so the composer\nbinds it as a **parameter** (``date_trunc(:gran, col)``, never interpolated) yet\nit is still constrained to this closed set — a bound value that could only ever\nbe one of these keywords."},"GroupCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Unique group name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description","description":"Group description"},"is_admins":{"type":"boolean","title":"Is Admins","description":"Grant full admin access to members","default":false},"mfa_required":{"type":"boolean","title":"Mfa Required","description":"Require MFA for group members","default":false},"rbac_model_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rbac Model Id","description":"RBAC permission model ID"},"enable_mode":{"type":"string","enum":["inherit","login_password","custom","deny"],"title":"Enable Mode","description":"TACACS+ enable password mode for group members","default":"inherit"},"enable_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Enable Password","description":"Enable password (required when enable_mode='custom')"}},"additionalProperties":false,"type":"object","required":["name"],"title":"GroupCreate","description":"Schema for creating a new local group."},"GroupDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"source":{"type":"string","title":"Source"},"is_admins":{"type":"boolean","title":"Is Admins"},"mfa_required":{"type":"boolean","title":"Mfa Required"},"rbac_model_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rbac Model Id"},"ldap_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Dn"},"ldap_config_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Config Id"},"ldap_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ldap Synced At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"member_count":{"type":"integer","title":"Member Count","description":"Number of members in the group","default":0},"enable_mode":{"type":"string","title":"Enable Mode","default":"inherit"},"enable_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enable Password"},"members":{"items":{"$ref":"#/components/schemas/GroupMemberBrief"},"type":"array","title":"Members"},"rbac_model_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rbac Model Name","description":"Denormalized name of the linked RBAC model (read-only display)"}},"type":"object","required":["id","name","source","is_admins","mfa_required","created_at","updated_at"],"title":"GroupDetailResponse","description":"Extended group response with member list."},"GroupInfoResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"GroupInfoResponse","description":"Group information for user list response."},"GroupListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"source":{"type":"string","title":"Source"},"is_admins":{"type":"boolean","title":"Is Admins"},"mfa_required":{"type":"boolean","title":"Mfa Required"},"member_count":{"type":"integer","title":"Member Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"enable_mode":{"type":"string","title":"Enable Mode","default":"inherit"}},"type":"object","required":["id","name","source","is_admins","mfa_required","created_at"],"title":"GroupListResponse","description":"Schema for a single group in list view (abbreviated)."},"GroupMemberAction":{"properties":{"user_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"minItems":1,"title":"User Ids","description":"User IDs to add or remove"}},"additionalProperties":false,"type":"object","required":["user_ids"],"title":"GroupMemberAction","description":"Schema for adding/removing users from a group."},"GroupMemberBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"username":{"type":"string","title":"Username"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"email":{"type":"string","title":"Email"}},"type":"object","required":["id","username","email"],"title":"GroupMemberBrief","description":"Brief user info embedded in GroupDetailResponse."},"GroupRefItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"member_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Member Count"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","required":["id","name"],"title":"GroupRefItem","description":"User-group reference enriched with member count + source (detail view only)."},"GroupResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"source":{"type":"string","title":"Source"},"is_admins":{"type":"boolean","title":"Is Admins"},"mfa_required":{"type":"boolean","title":"Mfa Required"},"rbac_model_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rbac Model Id"},"ldap_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Dn"},"ldap_config_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Config Id"},"ldap_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ldap Synced At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"member_count":{"type":"integer","title":"Member Count","description":"Number of members in the group","default":0},"enable_mode":{"type":"string","title":"Enable Mode","default":"inherit"},"enable_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enable Password"}},"type":"object","required":["id","name","source","is_admins","mfa_required","created_at","updated_at"],"title":"GroupResponse","description":"Schema for a single group in API responses."},"GroupUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"is_admins":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Admins"},"mfa_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Required"},"rbac_model_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rbac Model Id"},"enable_mode":{"anyOf":[{"type":"string","enum":["inherit","login_password","custom","deny"]},{"type":"null"}],"title":"Enable Mode","description":"TACACS+ enable password mode"},"enable_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Enable Password","description":"Enable password. Sentinel = keep, empty = clear, other = encrypt."}},"additionalProperties":false,"type":"object","title":"GroupUpdate","description":"Schema for updating a group.\n\nFor LDAP groups, only is_admins, mfa_required,\nrbac_model_id, enable_mode, and enable_password can be changed.\nAll other fields are managed by LDAP sync.\n\nEnable password sentinel logic:\n- sentinel (\"••••••••\") = keep current password\n- empty string (\"\") = clear the password\n- any other value = encrypt and save"},"GuestRegisterRequest":{"properties":{"portal_slug":{"type":"string","maxLength":100,"title":"Portal Slug"},"flow_type":{"type":"string","pattern":"^(guest|self_registration)$","title":"Flow Type"},"guest_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Guest Name"},"email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone"},"company":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Company"},"reason":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Reason"},"sponsor_email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Sponsor Email"},"captcha_token":{"anyOf":[{"type":"string","maxLength":8192},{"type":"null"}],"title":"Captcha Token"},"website":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Website"},"terms_accepted":{"type":"boolean","title":"Terms Accepted","default":false},"custom_data":{"anyOf":[{"additionalProperties":true,"type":"object","maxProperties":200},{"type":"null"}],"title":"Custom Data"}},"type":"object","required":["portal_slug","flow_type"],"title":"GuestRegisterRequest","description":"Registration request from guest / self_registration flow.\n\nPUBLIC endpoint — posted by the guest's browser (and the standalone DMZ\nportal). No extra=\"forbid\": a stray key must never 422 a guest, and the\nregistration form may carry admin-configured custom fields in ``custom_data``\n(free-form — only its SIZE is bounded, not its keys). Bounds only; values are\nnot charset-checked or stripped (free-form registration input)."},"GuestRegisterResponse":{"properties":{"status":{"type":"string","title":"Status"},"token":{"type":"string","title":"Token"},"message":{"type":"string","title":"Message"},"verification_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verification Method"},"verification_destination":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verification Destination"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"status_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Url"}},"type":"object","required":["status","token","message"],"title":"GuestRegisterResponse","description":"Response after successful registration."},"GuestSessionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"portal_id":{"type":"string","format":"uuid","title":"Portal Id"},"flow_type":{"type":"string","title":"Flow Type"},"token":{"type":"string","title":"Token"},"guest_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Guest Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"custom_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Custom Data"},"endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Endpoint Id"},"mac_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mac Address"},"verification_method_used":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Verification Method Used"},"verification_attempts":{"type":"integer","title":"Verification Attempts"},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verified At"},"sponsor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Sponsor Id"},"sponsor_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sponsor Email"},"sponsor_status":{"type":"string","title":"Sponsor Status"},"sponsor_responded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sponsor Responded At"},"status":{"type":"string","title":"Status"},"activated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Activated At"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"revoke_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revoke Reason"},"registered_from_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Registered From Ip"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"portal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Portal Name"},"sponsor_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sponsor Username"}},"type":"object","required":["id","portal_id","flow_type","token","guest_name","email","phone","company","reason","custom_data","endpoint_id","mac_address","verification_method_used","verification_attempts","verified_at","sponsor_id","sponsor_email","sponsor_status","sponsor_responded_at","status","activated_at","expires_at","revoked_at","revoke_reason","registered_from_ip","created_at"],"title":"GuestSessionResponse","description":"Guest session data for admin view."},"GuestStatusResponse":{"properties":{"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["status","message"],"title":"GuestStatusResponse","description":"Status polling response."},"GuestSummaryResponse":{"properties":{"active":{"type":"integer","title":"Active","default":0},"pending_approval":{"type":"integer","title":"Pending Approval","description":"Sessions awaiting verification or sponsor/admin approval","default":0},"expiring_24h":{"type":"integer","title":"Expiring 24H","description":"Active sessions whose expires_at falls within the next 24h","default":0}},"type":"object","title":"GuestSummaryResponse","description":"Captive-portal guest-session counters for the guest-portal widget.\n\nNot cached. Returns zeros (never an error) when no captive portal is\nconfigured / no guest sessions exist."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeartbeatRequest":{"properties":{"instance_id":{"type":"string","maxLength":64,"title":"Instance Id"},"instance_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Instance Name"},"uptime_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Uptime Seconds"},"nginx_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nginx Status"},"dnsmasq_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dnsmasq Status"},"dhcp_leases_active":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Dhcp Leases Active"},"disk_free_mb":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Disk Free Mb"},"memory_usage_percent":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Memory Usage Percent"},"portal_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Portal Version"}},"type":"object","required":["instance_id"],"title":"HeartbeatRequest","description":"Heartbeat payload from standalone portal container.\n\nPUBLIC endpoint — posted by the standalone portal container, NOT the admin\nSPA. No extra=\"forbid\": a future portal-side field must never 422 a heartbeat.\nBounds only."},"HistoryResponse":{"properties":{"points":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Points"},"total_points":{"type":"integer","title":"Total Points","default":0},"interval_seconds":{"type":"integer","title":"Interval Seconds","default":60}},"type":"object","title":"HistoryResponse","description":"Response for metric history endpoint."},"HostKeyActionResponse":{"properties":{"message":{"type":"string","title":"Message","description":"Localised outcome note (makes the host-scope explicit)."},"pin":{"anyOf":[{"$ref":"#/components/schemas/HostKeyPinRead"},{"type":"null"}],"description":"The resulting pinned key (accept), or null (reset)."}},"type":"object","required":["message"],"title":"HostKeyActionResponse","description":"Result of an accept/reset re-trust action on a source's pinned host key.\n\n``message`` is a localised, host-scoping-explicit note (the pin is shared by\n*every* source reaching this address via this collector — re-trust/reset is not\nper-source). ``pin`` carries the resulting pinned key after an accept (so the UI\ncan show the newly-trusted fingerprint); it is ``null`` after a reset."},"HostKeyPinRead":{"properties":{"key_type":{"type":"string","title":"Key Type"},"fingerprint":{"type":"string","title":"Fingerprint"},"first_seen":{"type":"string","format":"date-time","title":"First Seen"},"candidate_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Candidate Fingerprint"},"candidate_seen":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Candidate Seen"}},"type":"object","required":["key_type","fingerprint","first_seen"],"title":"HostKeyPinRead","description":"The pinned key (and any awaiting candidate) for one endpoint — read-only view."},"HostKeyPolicy":{"type":"string","enum":["trust_on_first_use","trust_always","strict"],"title":"HostKeyPolicy","description":"How an SSH-family transport treats an unknown/changed host key (TOFU pinning).\n\nThe Taranac pin store (``ncm_host_key_pins``) — NOT the OpenSSH ``known_hosts``\nfile — is the source of truth. See :mod:`app.modules.ncm.collector.hostkey` for the\npure verify layer and :class:`app.modules.ncm.hostkeys.service.HostKeyPinService`."},"HostKeyStatusResponse":{"properties":{"enforced":{"type":"boolean","title":"Enforced","description":"Whether host-key pinning is enforced on the source's effective collection path."},"pin":{"anyOf":[{"$ref":"#/components/schemas/HostKeyPinRead"},{"type":"null"}],"description":"The pinned key (and any awaiting candidate), or null if none is pinned yet."}},"type":"object","required":["enforced"],"title":"HostKeyStatusResponse","description":"A source's host-key pin status: the pin (if any) + whether pinning is ENFORCED.\n\n``enforced`` is ``False`` when the source's effective collection path cannot enforce a\npin — the NAPALM ``get_config`` fast-path does not drive paramiko's host-key check, so\nit neither pins nor verifies. The UI shows a note when ``enforced`` is false so an\noperator is not misled into thinking a key will be pinned/verified when it will not.\nThe pin is host-scoped (shared by every source reaching this collector+address+port)."},"HttpMethod":{"type":"string","enum":["GET","POST"],"title":"HttpMethod"},"HttpSettings":{"properties":{"base_path":{"type":"string","maxLength":2048,"title":"Base Path","description":"Optional path prefix (e.g. /restconf); host+port come from the source.","default":""},"method":{"$ref":"#/components/schemas/HttpMethod","default":"GET"},"headers":{"additionalProperties":{"type":"string"},"type":"object","title":"Headers","description":"Request headers (may carry {{cred.*}})."},"body_template":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Body Template","description":"Request body template."},"kind":{"type":"string","const":"http","title":"Kind","default":"http"}},"additionalProperties":false,"type":"object","title":"HttpSettings","description":"Plain HTTP transport settings (no TLS); default port 80."},"HttpsSettings":{"properties":{"base_path":{"type":"string","maxLength":2048,"title":"Base Path","description":"Optional path prefix (e.g. /restconf); host+port come from the source.","default":""},"method":{"$ref":"#/components/schemas/HttpMethod","default":"GET"},"headers":{"additionalProperties":{"type":"string"},"type":"object","title":"Headers","description":"Request headers (may carry {{cred.*}})."},"body_template":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Body Template","description":"Request body template."},"kind":{"type":"string","const":"https","title":"Kind","default":"https"},"tls_verify":{"type":"boolean","title":"Tls Verify","default":false}},"additionalProperties":false,"type":"object","title":"HttpsSettings","description":"HTTPS transport settings; default port 443.\n\n``tls_verify`` defaults to ``False`` — device APIs are commonly self-signed, so\ncertificate verification is opt-in rather than the (broken-by-default) norm."},"ImportCaData":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"ca_type":{"type":"string","enum":["root","intermediate"],"title":"Ca Type"},"ca_cert_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Ca Cert Pem"},"private_key_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Private Key Pem"},"private_key_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Private Key Password"},"parent_ca_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Ca Id"}},"additionalProperties":false,"type":"object","required":["name","ca_type","ca_cert_pem","private_key_pem"],"title":"ImportCaData","description":"Import an existing CA (cert + key).\n\nextra=\"forbid\": admin-only (CreateCaForm import branch submits an explicit\nobject with exactly these keys). PEM blobs are LENGTH-bounded only and NOT\nwhitespace-stripped (newlines are significant)."},"ImportItemResult":{"properties":{"row":{"type":"integer","title":"Row","description":"Row number (1-based) or object index"},"name":{"type":"string","title":"Name","description":"Name/identifier of the processed item","default":""},"status":{"type":"string","enum":["created","updated","skipped","error"],"title":"Status","description":"Outcome for this item"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Error or info message"}},"type":"object","required":["row","status"],"title":"ImportItemResult","description":"Result of importing a single row/object."},"ImportMode":{"type":"string","enum":["create_only","update_existing","fail_on_conflict"],"title":"ImportMode","description":"Import conflict resolution strategy."},"ImportResult":{"properties":{"entity_type":{"type":"string","title":"Entity Type","description":"Type of entity imported"},"total_rows":{"type":"integer","title":"Total Rows","description":"Total rows processed","default":0},"created":{"type":"integer","title":"Created","description":"Items successfully created","default":0},"updated":{"type":"integer","title":"Updated","description":"Items successfully updated","default":0},"skipped":{"type":"integer","title":"Skipped","description":"Items skipped (already exist in create_only mode)","default":0},"errors":{"type":"integer","title":"Errors","description":"Items that failed validation","default":0},"dry_run":{"type":"boolean","title":"Dry Run","description":"Whether this was a dry-run (no DB writes)","default":false},"items":{"items":{"$ref":"#/components/schemas/ImportItemResult"},"type":"array","title":"Items","description":"Per-item results"}},"type":"object","required":["entity_type"],"title":"ImportResult","description":"Summary result of an import operation."},"IngestPayload":{"properties":{"capability":{"type":"string","title":"Capability","description":"Self-describing capability tag (informational; the core routes by the dispatch row's capability).","default":"ncm_config"},"ingest_key":{"type":"string","format":"uuid","title":"Ingest Key","description":"The dispatch's core-minted ingest key — locates the dispatch row."},"version":{"type":"string","title":"Version","description":"Snapshot-identity version the collector ran (version-gated first)."},"payload":{"$ref":"#/components/schemas/NcmIngestPayload"}},"additionalProperties":false,"type":"object","required":["ingest_key","version","payload"],"title":"IngestPayload","description":"A collector's collection outcome for one claimed target — the generic ingest envelope.\n\nTop-level is capability-BLIND: ``ingest_key`` LOCATES the dispatch row (the UNIQUE\nidempotency anchor), ``version`` GATES it, ``capability`` is self-describing metadata\n(the core routes by the dispatch ROW's capability, NEVER this field). The capability's\nresult data lives in ``payload`` (:class:`NcmIngestPayload` for NCM). The core re-derives\n``tracked_config_id`` / ``run_id`` from the located dispatch row — nothing authoritative\nis carried here."},"IngestResult":{"properties":{"ingest_key":{"type":"string","format":"uuid","title":"Ingest Key"},"result_status":{"type":"string","title":"Result Status","description":"ok|changed|unchanged|failed — the recorded result status."},"snapshot_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Snapshot Id","description":"The snapshot produced (NULL on failure / dedup-only)."},"dispatch_state":{"type":"string","title":"Dispatch State","description":"The dispatch state after ingest (always 'done')."}},"type":"object","required":["ingest_key","result_status","dispatch_state"],"title":"IngestResult","description":"The core's acknowledgement of an ingest — enough for the collector to reconcile.\n\n``result_status`` is the durable ``CollectionResult`` outcome (ok|changed|unchanged|\nfailed); ``snapshot_id`` is present only when a snapshot landed. ``dispatch_state`` is\nalways ``done`` after a processed ingest (the lease is released)."},"InstallationIdResponse":{"properties":{"installation_id":{"type":"string","title":"Installation Id","description":"Immutable per-install UUID. Bind the Pro license to this value."}},"type":"object","required":["installation_id"],"title":"InstallationIdResponse","description":"This installation's immutable identifier, shown on the license page.\n\nThe admin copies it and sends it to TaranacLabs to have a ``.lic`` issued\n(``bound_to`` this id). See ``docs/guide/licensing.md`` §5."},"InstalledCaInfo":{"properties":{"subject_dn":{"type":"string","title":"Subject Dn"},"issuer_dn":{"type":"string","title":"Issuer Dn"},"serial_number":{"type":"string","title":"Serial Number"},"not_before":{"type":"string","format":"date-time","title":"Not Before"},"not_after":{"type":"string","format":"date-time","title":"Not After"},"is_expired":{"type":"boolean","title":"Is Expired"},"key_algorithm":{"type":"string","title":"Key Algorithm"},"is_self_signed":{"type":"boolean","title":"Is Self Signed"}},"type":"object","required":["subject_dn","issuer_dn","serial_number","not_before","not_after","is_expired","key_algorithm","is_self_signed"],"title":"InstalledCaInfo","description":"Single CA certificate parsed from ca_clients.pem."},"InstalledCasResponse":{"properties":{"certificates":{"items":{"$ref":"#/components/schemas/InstalledCaInfo"},"type":"array","title":"Certificates","default":[]},"total":{"type":"integer","title":"Total","default":0},"bundle_file_exists":{"type":"boolean","title":"Bundle File Exists","default":false},"bundle_size_bytes":{"type":"integer","title":"Bundle Size Bytes","default":0},"bundle_last_modified":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Bundle Last Modified"}},"type":"object","title":"InstalledCasResponse","description":"All CA certificates currently deployed in ca_clients.pem."},"IntermediateCaCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"parent_ca_id":{"type":"string","format":"uuid","title":"Parent Ca Id"},"subject_cn":{"type":"string","maxLength":255,"minLength":1,"title":"Subject Cn"},"subject_o":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Subject O"},"subject_ou":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Subject Ou"},"subject_c":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Subject C"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa4096"},"validity_years":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Validity Years","default":5},"crl_distribution_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Crl Distribution Url"},"ocsp_responder_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Ocsp Responder Url"}},"additionalProperties":false,"type":"object","required":["name","parent_ca_id","subject_cn"],"title":"IntermediateCaCreate","description":"Create a new intermediate CA signed by a parent CA.\n\nextra=\"forbid\": admin-only (CreateCaForm submits an explicit object with\nexactly these keys)."},"InternalCaResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"ca_type":{"type":"string","title":"Ca Type"},"status":{"type":"string","title":"Status"},"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"subject_dn":{"type":"string","title":"Subject Dn"},"not_before":{"type":"string","format":"date-time","title":"Not Before"},"not_after":{"type":"string","format":"date-time","title":"Not After"},"serial_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial Number"},"next_serial":{"type":"integer","title":"Next Serial"},"key_algorithm":{"type":"string","title":"Key Algorithm"},"max_path_length":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Path Length"},"parent_ca_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Ca Id"},"crl_distribution_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crl Distribution Url"},"ocsp_responder_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ocsp Responder Url"},"enabled":{"type":"boolean","title":"Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"children_count":{"type":"integer","title":"Children Count","default":0},"issued_count":{"type":"integer","title":"Issued Count","default":0}},"type":"object","required":["id","name","ca_type","status","subject_dn","not_before","not_after","next_serial","key_algorithm","enabled","created_at","updated_at"],"title":"InternalCaResponse","description":"Response schema for an Internal CA."},"IntervalUpdateRequest":{"properties":{"seconds":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":5.0},{"type":"null"}],"title":"Seconds","description":"Interval in seconds"},"minutes":{"anyOf":[{"type":"integer","maximum":1440.0,"minimum":1.0},{"type":"null"}],"title":"Minutes","description":"Interval in minutes"},"hours":{"anyOf":[{"type":"integer","maximum":168.0,"minimum":1.0},{"type":"null"}],"title":"Hours","description":"Interval in hours"}},"type":"object","title":"IntervalUpdateRequest","description":"Request body for changing a job's interval."},"IssueCertData":{"properties":{"ca_id":{"type":"string","format":"uuid","title":"Ca Id"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"cert_type":{"type":"string","enum":["user","device","server"],"title":"Cert Type"},"subject_cn":{"type":"string","maxLength":255,"minLength":1,"title":"Subject Cn"},"subject_o":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Subject O"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"ec256"},"validity_days":{"type":"integer","maximum":3650.0,"minimum":1.0,"title":"Validity Days","default":365},"san_upn":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"San Upn"},"san_email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"San Email"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Dns"},"san_ip":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Ip"},"linked_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked User Id"},"linked_endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked Endpoint Id"}},"type":"object","required":["ca_id","name","cert_type","subject_cn"],"title":"IssueCertData","description":"Issue a new certificate (generates key + signed cert)."},"IssueCsrData":{"properties":{"ca_id":{"type":"string","format":"uuid","title":"Ca Id"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"cert_type":{"type":"string","enum":["user","device","server"],"title":"Cert Type"},"csr_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Csr Pem"},"validity_days":{"type":"integer","maximum":3650.0,"minimum":1.0,"title":"Validity Days","default":365},"san_upn":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"San Upn"},"san_email":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"San Email"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Dns"},"san_ip":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Ip"},"linked_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked User Id"},"linked_endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked Endpoint Id"}},"type":"object","required":["ca_id","name","cert_type","csr_pem"],"title":"IssueCsrData","description":"Issue a certificate from an externally generated CSR."},"IssueServerCert":{"properties":{"ca_id":{"type":"string","format":"uuid","title":"Ca Id","description":"Internal CA to issue from"},"common_name":{"type":"string","maxLength":255,"minLength":1,"title":"Common Name"},"organization":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organization"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Country"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Dns"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa2048"},"validity_days":{"type":"integer","maximum":3650.0,"minimum":1.0,"title":"Validity Days","default":730}},"type":"object","required":["ca_id","common_name"],"title":"IssueServerCert","description":"Issue a server certificate from an internal CA."},"IssuedCertResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"ca_id":{"type":"string","format":"uuid","title":"Ca Id"},"name":{"type":"string","title":"Name"},"cert_type":{"type":"string","title":"Cert Type"},"subject_dn":{"type":"string","title":"Subject Dn"},"serial_number":{"type":"string","title":"Serial Number"},"not_before":{"type":"string","format":"date-time","title":"Not Before"},"not_after":{"type":"string","format":"date-time","title":"Not After"},"key_algorithm":{"type":"string","title":"Key Algorithm"},"san_entries":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"San Entries"},"key_usage":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Key Usage"},"extended_key_usage":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"Extended Key Usage"},"status":{"type":"string","title":"Status"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"revocation_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Revocation Reason"},"linked_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked User Id"},"linked_endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked Endpoint Id"},"download_count":{"type":"integer","title":"Download Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"has_private_key":{"type":"boolean","title":"Has Private Key","default":true},"from_csr":{"type":"boolean","title":"From Csr","default":false}},"type":"object","required":["id","ca_id","name","cert_type","subject_dn","serial_number","not_before","not_after","key_algorithm","status","created_at","updated_at"],"title":"IssuedCertResponse","description":"Response schema for an issued certificate."},"IssuedEnrollmentTokenResponse":{"properties":{"token":{"type":"string","title":"Token","description":"The one-time enrollment secret. Shown once, never recoverable."},"token_id":{"type":"string","format":"uuid","title":"Token Id"},"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"collector_name":{"type":"string","title":"Collector Name"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["token","token_id","collector_id","collector_name","expires_at"],"title":"IssuedEnrollmentTokenResponse","description":"Reveal-once response — the plaintext ``token`` is present here exactly once."},"IssuedJoinTokenResponse":{"properties":{"token":{"type":"string","title":"Token","description":"The one-time join secret. Store it now; it is never recoverable."},"token_id":{"type":"string","format":"uuid","title":"Token Id"},"node_name":{"type":"string","title":"Node Name"},"node_address":{"type":"string","title":"Node Address"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["token","token_id","node_name","node_address","expires_at"],"title":"IssuedJoinTokenResponse","description":"A freshly issued join token — the secret appears here exactly once."},"IssuedTo":{"properties":{"org":{"type":"string","title":"Org"},"contact_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Email"}},"type":"object","required":["org"],"title":"IssuedTo"},"JobPayload":{"properties":{"capability":{"type":"string","title":"Capability","description":"The capability this job serves — the daemon routes it to the matching capability worker and the ingest-gateway routes the reported outcome by the dispatch ROW's capability. Defaulted to 'ncm_config' so hand-built job payloads stay valid; the claim path sets it from the dispatch's own capability.","default":"ncm_config"},"trigger":{"type":"string","title":"Trigger","description":"The dispatch trigger (scheduled|on_demand|preview) — the daemon forks a trigger='preview' job to /preview-result (a routed dry-run that NEVER ingests) and everything else through the collect→ingest path.","default":"scheduled"},"ingest_key":{"type":"string","format":"uuid","title":"Ingest Key","description":"The single generic transport handle: the collect ingest anchor AND the preview poll-handle. Non-null for every dispatched job; the collector threads it back verbatim on the reported outcome and the lease-renew request."},"version":{"type":"string","title":"Version","description":"Snapshot-identity version this job was dispatched under."},"lease_ttl_s":{"type":"integer","title":"Lease Ttl S","description":"The lease TTL (seconds) the core resolved for this claim — the SAME value used to set lease_expires_at. The collector drives its lease-renew cadence from this so a lowered operator setting (ncm.run_lease_ttl_seconds) speeds renews and a slow collect never loses its lease mid-flight. Defaults to the system default so existing constructions/tests stay valid.","default":300},"payload":{"$ref":"#/components/schemas/NcmJobPayload"}},"additionalProperties":false,"type":"object","required":["ingest_key","version","payload"],"title":"JobPayload","description":"One dispatched job — the frozen generic wire envelope for the dial-out plane.\n\nTop-level is capability-BLIND: ``capability`` (the daemon's registry lookup + the core's\nrouting key — sourced from the dispatch ROW), ``trigger`` (the daemon forks preview-vs-\ncollect on it), ``ingest_key`` (the single generic transport handle — the collect ingest\nanchor AND the preview poll-handle), ``version`` (the per-capability negotiation echo of\n:data:`~app.modules.ncm.collector_gateway.versioning.SNAPSHOT_IDENTITY_VERSION`), and\n``lease_ttl_s`` (a transport pacing field the generic lease loop reads). The\ncapability-specific collect inputs live in ``payload`` (:class:`NcmJobPayload` for NCM)."},"JobRecipeSpec":{"properties":{"kind":{"type":"string","title":"Kind","description":"'cli' (ordered terminal commands) | 'http' (single request spec) | 'file' (scp/sftp remote_path)."},"steps":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Steps","description":"Ordered CLI steps, a 1-elem HTTP spec, or a 1-elem file remote_path spec."},"trim":{"additionalProperties":true,"type":"object","title":"Trim","description":"Per-step trim directives."},"netmiko_device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Netmiko Device Type","description":"CLI driver session platform; NULL → engine default."}},"type":"object","required":["kind"],"title":"JobRecipeSpec","description":"The minimal recipe fields the engine's request builder consumes.\n\nMirrors :class:`~app.modules.ncm.recipes.models.CollectionRecipe` down to what\n``collect_one`` reads: ``kind`` selects CLI vs HTTP vs file, ``steps`` are the ordered\ncommands / the single HTTP spec / the file's ``remote_path`` spec, ``trim`` the\nper-step trim map, and ``netmiko_device_type`` the CLI driver's session platform."},"JobScrubRuleSpec":{"properties":{"order":{"type":"integer","title":"Order"},"stage":{"type":"string","title":"Stage","description":"drop_volatile | mask_secret | keep."},"pattern":{"type":"string","title":"Pattern"},"replacement":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replacement"}},"type":"object","required":["order","stage","pattern"],"title":"JobScrubRuleSpec","description":"One scrub rule, serialised from the engine's ``ScrubRule`` dataclass.\n\nField-for-field with :class:`app.shared.scrub.engine.ScrubRule` so the collector\nreconstructs the exact same ordered rule set (the version gate guarantees the\nengine that consumes them is byte-compatible)."},"JobSourceSpec":{"properties":{"transport_type":{"type":"string","title":"Transport Type","description":"ssh|telnet|scp|sftp|http|https — the transport registry key."},"address":{"type":"string","title":"Address","description":"IPv4/IPv6 literal or FQDN; DNS resolved by the collector's transport."},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port","description":"Optional port; NULL → transport registry default at use time."},"transport_settings":{"additionalProperties":true,"type":"object","title":"Transport Settings","description":"Per-transport settings bag."}},"type":"object","required":["transport_type","address"],"title":"JobSourceSpec","description":"The serialisable ``CollectionSource`` fields the engine builds a request from.\n\n``port`` is left as-supplied (``None`` → the collector applies the transport\nregistry default at use time, exactly as the embedded engine does)."},"JoinConfigRequest":{"properties":{"token":{"type":"string","minLength":1,"title":"Token","description":"The join secret issued for this node."}},"type":"object","required":["token"],"title":"JoinConfigRequest","description":"A joining node fetching the cluster-wide config it must adopt (token-authenticated)."},"JoinConfigResponse":{"properties":{"cluster_name":{"type":"string","title":"Cluster Name"},"db_hosts":{"type":"string","title":"Db Hosts"},"etcd_hosts":{"type":"string","title":"Etcd Hosts"},"etcd_initial_cluster":{"type":"string","title":"Etcd Initial Cluster"},"pg_allow_cidr":{"type":"string","title":"Pg Allow Cidr"},"db_connect_timeout":{"type":"string","title":"Db Connect Timeout"},"version":{"type":"string","title":"Version"},"etcd_client_scheme":{"type":"string","title":"Etcd Client Scheme"},"postgres_password":{"type":"string","title":"Postgres Password"},"postgres_replication_password":{"type":"string","title":"Postgres Replication Password"},"secret_key":{"type":"string","title":"Secret Key"},"taranac_mfa_api_key":{"type":"string","title":"Taranac Mfa Api Key","default":""}},"type":"object","required":["cluster_name","db_hosts","etcd_hosts","etcd_initial_cluster","pg_allow_cidr","db_connect_timeout","version","etcd_client_scheme","postgres_password","postgres_replication_password","secret_key"],"title":"JoinConfigResponse","description":"The cluster-wide settings a joining node adopts — everything shared EXCEPT\n``MASTER_KEY`` (the KEK stays strictly out-of-band). Read from the primary's own\nenvironment so a joining node need not hand-copy them."},"JoinTokenIssueRequest":{"properties":{"node_name":{"type":"string","maxLength":128,"minLength":1,"title":"Node Name","description":"Intended TARANAC_NODE_NAME of the new node."},"node_address":{"type":"string","maxLength":255,"minLength":1,"title":"Node Address","description":"Advertised host/IP of the new node."},"ttl_minutes":{"type":"integer","maximum":1440.0,"minimum":1.0,"title":"Ttl Minutes","description":"How long the token stays redeemable.","default":60}},"type":"object","required":["node_name","node_address"],"title":"JoinTokenIssueRequest","description":"Operator-declared identity of the node about to join (the license gate keys off this)."},"JoinTokenListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/JoinTokenResponse"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"JoinTokenListResponse"},"JoinTokenResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"node_name":{"type":"string","title":"Node Name"},"node_address":{"type":"string","title":"Node Address"},"status":{"type":"string","title":"Status"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"consumed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Consumed At"}},"type":"object","required":["id","node_name","node_address","status","expires_at","created_at"],"title":"JoinTokenResponse","description":"A join token as listed for operators — never carries the secret."},"LDAPAdhocBrowseRequest":{"properties":{"connection":{"$ref":"#/components/schemas/LDAPAdhocConnectionParams"},"base_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Base Dn","description":"Starting DN. If NULL, auto-detect from RootDSE."},"scope":{"type":"string","enum":["one_level","subtree_one"],"title":"Scope","default":"one_level"},"object_types":{"items":{"type":"string","maxLength":255},"type":"array","maxItems":50,"title":"Object Types"},"include_users":{"type":"boolean","title":"Include Users","default":false},"page_size":{"type":"integer","maximum":1000.0,"minimum":50.0,"title":"Page Size","default":500}},"additionalProperties":false,"type":"object","required":["connection"],"title":"LDAPAdhocBrowseRequest","description":"Browse LDAP directory with inline connection parameters (no saved config needed)."},"LDAPAdhocConnectionParams":{"properties":{"servers":{"type":"string","maxLength":1024,"minLength":1,"title":"Servers","description":"Space-separated LDAP server URIs"},"bind_dn":{"type":"string","maxLength":1024,"minLength":1,"title":"Bind Dn","description":"Bind DN"},"bind_password":{"type":"string","maxLength":1024,"minLength":1,"title":"Bind Password","description":"Bind password (not stored)"},"use_start_tls":{"type":"boolean","title":"Use Start Tls","description":"Use STARTTLS","default":false},"tls_validate":{"type":"boolean","title":"Tls Validate","description":"Validate TLS certificates","default":true},"tls_ca_cert":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Tls Ca Cert","description":"PEM of the CA that issued the directory server's certificate."},"connection_timeout":{"type":"integer","maximum":120.0,"minimum":1.0,"title":"Connection Timeout","description":"Connection timeout in seconds","default":10}},"additionalProperties":false,"type":"object","required":["servers","bind_dn","bind_password"],"title":"LDAPAdhocConnectionParams","description":"Connection parameters for ad-hoc LDAP operations (without saved config)."},"LDAPAdhocSearchRequest":{"properties":{"connection":{"$ref":"#/components/schemas/LDAPAdhocConnectionParams"},"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query","description":"Search term"},"base_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Base Dn","description":"Scope search under this DN."},"object_types":{"items":{"type":"string","maxLength":255},"type":"array","maxItems":50,"title":"Object Types"},"max_results":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Max Results","default":100}},"additionalProperties":false,"type":"object","required":["connection","query"],"title":"LDAPAdhocSearchRequest","description":"Search LDAP directory with inline connection parameters (no saved config needed)."},"LDAPBrowseEntry":{"properties":{"dn":{"type":"string","title":"Dn"},"name":{"type":"string","title":"Name"},"object_type":{"type":"string","title":"Object Type","description":"organizational_unit | container | group | user | builtin_domain | other"},"has_children":{"type":"boolean","title":"Has Children","description":"True if this node can be expanded"},"member_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Member Count","description":"Only for groups: number of members"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"attributes":{"additionalProperties":true,"type":"object","title":"Attributes"}},"type":"object","required":["dn","name","object_type","has_children"],"title":"LDAPBrowseEntry","description":"Single entry in the LDAP directory browser response."},"LDAPBrowseRequest":{"properties":{"base_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Base Dn","description":"Starting DN. If NULL, starts from auto-detected root DN."},"scope":{"type":"string","enum":["one_level","subtree_one"],"title":"Scope","description":"one_level = direct children only (for lazy tree loading)","default":"one_level"},"object_types":{"items":{"type":"string","maxLength":255},"type":"array","maxItems":50,"title":"Object Types","description":"Which object types to return"},"include_users":{"type":"boolean","title":"Include Users","description":"If True, also return user objects (can be slow for large OUs)","default":false},"page_size":{"type":"integer","maximum":1000.0,"minimum":50.0,"title":"Page Size","description":"LDAP paged results size","default":500}},"additionalProperties":false,"type":"object","title":"LDAPBrowseRequest","description":"Request for browsing the LDAP directory tree."},"LDAPBrowseResponse":{"properties":{"base_dn":{"type":"string","title":"Base Dn"},"entries":{"items":{"$ref":"#/components/schemas/LDAPBrowseEntry"},"type":"array","title":"Entries"},"total_entries":{"type":"integer","title":"Total Entries"},"root_dns":{"items":{"type":"string"},"type":"array","title":"Root Dns","description":"Available root naming contexts"},"truncated":{"type":"boolean","title":"Truncated","default":false}},"type":"object","required":["base_dn","entries","total_entries"],"title":"LDAPBrowseResponse","description":"Response from the LDAP directory browser."},"LDAPComputerBrowseRequest":{"properties":{"base_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Base Dn","description":"Starting DN. If NULL, starts from auto-detected root DN."},"page_size":{"type":"integer","maximum":1000.0,"minimum":50.0,"title":"Page Size","description":"LDAP paged results size","default":500}},"additionalProperties":false,"type":"object","title":"LDAPComputerBrowseRequest","description":"Request for browsing OU structure + computer objects."},"LDAPComputerSearchRequest":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query","description":"Search term"},"base_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Base Dn","description":"Scope search under this DN. NULL = search from root."},"max_results":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Max Results","default":100}},"additionalProperties":false,"type":"object","required":["query"],"title":"LDAPComputerSearchRequest","description":"Request for searching computers by name."},"LDAPConfigCreate":{"properties":{"config_id":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z0-9_-]+$","title":"Config Id","description":"Unique config identifier (slug): a-z, 0-9, _, -"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name","description":"Human-readable name"},"directory_type":{"type":"string","maxLength":255,"title":"Directory Type","description":"Kind of directory this configuration talks to: active_directory, openldap, google_workspace or generic. Chosen once, at creation — it decides which features are even possible. Defaulted rather than required so a client that predates directory profiles keeps creating the Active Directory it means.","default":"active_directory"},"servers":{"type":"string","maxLength":1024,"minLength":1,"title":"Servers","description":"Space-separated LDAP server URIs, e.g. 'ldap://10.0.0.1 ldaps://10.0.0.2:636'"},"bind_dn":{"type":"string","maxLength":1024,"minLength":1,"title":"Bind Dn","description":"Bind DN for LDAP authentication"},"bind_password":{"type":"string","maxLength":1024,"minLength":1,"title":"Bind Password","description":"Bind password (will be encrypted)"},"domain_suffix":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Domain Suffix","description":"DNS domain suffix / realm, e.g. 'buh.local'. Routes user@domain logins. Required for Active Directory, optional elsewhere."},"netbios_name":{"anyOf":[{"type":"string","maxLength":15},{"type":"null"}],"title":"Netbios Name","description":"NetBIOS domain name, e.g. 'BUH'. Routes DOMAIN\\user logins. Active Directory only — no other directory type has one."},"priority":{"type":"integer","maximum":999.0,"minimum":1.0,"title":"Priority","description":"Authentication priority. Lower = checked first when bare username is used.","default":100},"user_search_bases":{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100,"minItems":1,"title":"User Search Bases","description":"JSON array of user search base DNs"},"user_search_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"User Search Filter","description":"LDAP search filter for user lookup. {username} is replaced at query time. Empty = take the chosen directory type's default."},"group_search_bases":{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100,"title":"Group Search Bases","description":"JSON array of group search base DNs"},"group_search_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Group Search Filter","description":"LDAP search filter for group lookup. Empty = the directory type's default."},"sync_group_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Sync Group Filter","description":"LDAP filter for groups during synchronization. Empty = the directory type's default."},"sync_user_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Sync User Filter","description":"LDAP filter for users during users_only sync. Empty = the directory type's default."},"sync_group_dns":{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100,"title":"Sync Group Dns","description":"Explicit list of group DNs to sync. If non-empty, overrides sync_group_filter."},"user_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":100},{"type":"null"}],"title":"User Attr Map","description":"Mapping of local fields to LDAP attributes. Empty = the directory type's map."},"group_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":100},{"type":"null"}],"title":"Group Attr Map","description":"Mapping of local group fields to LDAP attributes. Empty = the directory type's map."},"sync_mode":{"type":"string","enum":["groups_with_users","users_only","groups_and_users"],"title":"Sync Mode","description":"Sync mode: groups_with_users, users_only, or groups_and_users","default":"groups_with_users"},"sync_enabled":{"type":"boolean","title":"Sync Enabled","description":"Enable periodic synchronization","default":false},"sync_interval_minutes":{"type":"integer","maximum":10080.0,"minimum":5.0,"title":"Sync Interval Minutes","description":"Sync interval in minutes","default":60},"sync_create_users":{"type":"boolean","title":"Sync Create Users","description":"Create new users found in LDAP","default":true},"sync_disable_missing":{"type":"boolean","title":"Sync Disable Missing","description":"Deactivate users not found in LDAP","default":false},"sync_remove_stale_users":{"type":"boolean","title":"Sync Remove Stale Users","description":"Hard-delete users from DB that were not found during sync","default":false},"sync_remove_stale_groups":{"type":"boolean","title":"Sync Remove Stale Groups","description":"Delete groups from DB that were not found during sync","default":false},"default_rbac_model_id":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Default Rbac Model Id","description":"UUID of default RBAC model for newly imported groups. Applied on creation only."},"group_rbac_mapping":{"additionalProperties":{"type":"string"},"type":"object","maxProperties":1000,"title":"Group Rbac Mapping","description":"Per-group RBAC override. Key = group DN or CN, value = RBAC model UUID. Takes priority over default_rbac_model_id."},"is_enabled":{"type":"boolean","title":"Is Enabled","description":"Enable this LDAP configuration","default":true},"use_start_tls":{"type":"boolean","title":"Use Start Tls","description":"Use STARTTLS for LDAP connections","default":false},"tls_validate":{"type":"boolean","title":"Tls Validate","description":"Validate TLS certificates","default":true},"tls_ca_cert":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Tls Ca Cert","description":"PEM of the CA that issued the DIRECTORY SERVER's certificate — the trust anchor for LDAPS/StartTLS. Not the same thing as eap_tls_ca_cert, which is the CA that issues CLIENT certificates for 802.1X; the two are often but not always the same CA. Empty means the system trust store."},"connection_timeout":{"type":"integer","maximum":300.0,"minimum":1.0,"title":"Connection Timeout","description":"Connection timeout in seconds","default":10},"pool_strategy":{"type":"string","enum":["ROUND_ROBIN","FIRST","RANDOM"],"title":"Pool Strategy","description":"Server pool strategy: ROUND_ROBIN, FIRST, RANDOM","default":"ROUND_ROBIN"},"pool_active":{"type":"boolean","title":"Pool Active","description":"Active probing of server pool","default":true},"pool_exhaust":{"type":"integer","maximum":3600.0,"minimum":0.0,"title":"Pool Exhaust","description":"Pool exhaust timeout in seconds","default":5},"computer_sync_enabled":{"type":"boolean","title":"Computer Sync Enabled","description":"Enable computer synchronization for NAC endpoints","default":false},"computer_search_bases":{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100,"title":"Computer Search Bases","description":"Base DNs for computer search, e.g. [\"OU=Computers,DC=corp,DC=local\"]"},"computer_search_filter":{"type":"string","maxLength":1024,"title":"Computer Search Filter","description":"LDAP filter for computer objects","default":"(objectClass=computer)"},"computer_mac_attr":{"type":"string","maxLength":255,"title":"Computer Mac Attr","description":"AD attribute containing MAC address (empty = don't extract MAC, no Endpoint created)","default":""},"computer_attr_map":{"additionalProperties":{"type":"string"},"type":"object","maxProperties":100,"title":"Computer Attr Map","description":"Mapping of endpoint fields to AD computer attributes"},"computer_sync_create":{"type":"boolean","title":"Computer Sync Create","description":"Create new endpoints from AD computers","default":true},"computer_sync_update":{"type":"boolean","title":"Computer Sync Update","description":"Update existing endpoints from AD computers","default":true},"computer_sync_deactivate_missing":{"type":"boolean","title":"Computer Sync Deactivate Missing","description":"Set status=inactive for endpoints not found in AD during sync","default":false},"computer_sync_delete_missing":{"type":"boolean","title":"Computer Sync Delete Missing","description":"Hard-delete endpoints not found in AD during sync","default":false},"eap_tls_enabled":{"type":"boolean","title":"Eap Tls Enabled","description":"Enable EAP-TLS authentication for this LDAP domain","default":false},"eap_tls_cert_type":{"type":"string","enum":["user","computer","both"],"title":"Eap Tls Cert Type","description":"Certificate type to accept: user, computer, both","default":"both"},"eap_tls_identity_match":{"type":"string","enum":["san_upn","san_email","cn"],"title":"Eap Tls Identity Match","description":"How to match certificate identity to LDAP user: san_upn, san_email, cn","default":"san_upn"},"eap_tls_check_crl":{"type":"boolean","title":"Eap Tls Check Crl","description":"Check CRL for certificate revocation","default":false},"eap_tls_ocsp_enabled":{"type":"boolean","title":"Eap Tls Ocsp Enabled","description":"Enable OCSP for certificate validation","default":false},"eap_tls_ca_cert":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Eap Tls Ca Cert","description":"CA certificate in PEM format for EAP-TLS client certificate validation"},"eap_tls_crl_pem":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Eap Tls Crl Pem","description":"CRL in PEM or DER (base64) format"},"eap_tls_crl_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Eap Tls Crl Url","description":"CRL distribution point URL"}},"additionalProperties":false,"type":"object","required":["config_id","display_name","servers","bind_dn","bind_password","user_search_bases"],"title":"LDAPConfigCreate","description":"Schema for creating a new LDAP configuration."},"LDAPConfigDeleteRequest":{"properties":{"cascade":{"type":"string","enum":["none","disable_users","delete_users_and_groups"],"title":"Cascade","description":"Cascade behavior: 'none' = orphan users/groups (clear ldap_config_id), 'disable_users' = deactivate all domain users, 'delete_users_and_groups' = hard delete all domain users and groups","default":"none"},"confirm":{"type":"boolean","title":"Confirm","description":"Must be True for 'delete_users_and_groups' cascade","default":false}},"additionalProperties":false,"type":"object","title":"LDAPConfigDeleteRequest","description":"Request body for deleting an LDAP configuration with cascade options."},"LDAPConfigDeleteResponse":{"properties":{"config_id":{"type":"string","title":"Config Id"},"cascade":{"type":"string","title":"Cascade"},"users_affected":{"type":"integer","title":"Users Affected","default":0},"groups_affected":{"type":"integer","title":"Groups Affected","default":0}},"type":"object","required":["config_id","cascade"],"title":"LDAPConfigDeleteResponse","description":"Response after deleting an LDAP configuration."},"LDAPConfigResponse":{"properties":{"config_id":{"type":"string","title":"Config Id"},"display_name":{"type":"string","title":"Display Name"},"directory_type":{"type":"string","title":"Directory Type","default":"active_directory"},"servers":{"type":"string","title":"Servers"},"bind_dn":{"type":"string","title":"Bind Dn"},"bind_password":{"type":"string","title":"Bind Password","default":"***"},"domain_suffix":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain Suffix"},"netbios_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Netbios Name"},"priority":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priority","default":100},"user_search_bases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"User Search Bases"},"user_search_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Search Filter","default":""},"group_search_bases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Group Search Bases"},"group_search_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Group Search Filter","default":""},"sync_group_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sync Group Filter","default":""},"sync_user_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sync User Filter","default":""},"sync_group_dns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Sync Group Dns"},"user_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"User Attr Map"},"group_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Group Attr Map"},"sync_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sync Mode","default":"groups_with_users"},"sync_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Enabled","default":false},"sync_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sync Interval Minutes","default":60},"sync_create_users":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Create Users","default":true},"sync_disable_missing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Disable Missing","default":false},"sync_remove_stale_users":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Remove Stale Users","default":false},"sync_remove_stale_groups":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Remove Stale Groups","default":false},"default_rbac_model_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Rbac Model Id"},"group_rbac_mapping":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Group Rbac Mapping"},"rbac_model_names":{"additionalProperties":{"type":"string"},"type":"object","title":"Rbac Model Names"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled","default":true},"use_start_tls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Start Tls","default":false},"tls_validate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Tls Validate","default":true},"tls_ca_cert":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tls Ca Cert"},"tls_ca_cert_info":{"anyOf":[{"$ref":"#/components/schemas/CaCertInfo"},{"type":"null"}]},"connection_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Connection Timeout","default":10},"pool_strategy":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pool Strategy","default":"ROUND_ROBIN"},"pool_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pool Active","default":true},"pool_exhaust":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pool Exhaust","default":5},"computer_sync_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Enabled","default":false},"computer_search_bases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Computer Search Bases"},"computer_search_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computer Search Filter","default":"(objectClass=computer)"},"computer_mac_attr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Computer Mac Attr","default":""},"computer_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Computer Attr Map"},"computer_sync_create":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Create","default":true},"computer_sync_update":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Update","default":true},"computer_sync_deactivate_missing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Deactivate Missing","default":false},"computer_sync_delete_missing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Delete Missing","default":false},"eap_tls_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Eap Tls Enabled","default":false},"eap_tls_cert_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Cert Type","default":"both"},"eap_tls_identity_match":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Identity Match","default":"san_upn"},"eap_tls_check_crl":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Eap Tls Check Crl","default":false},"eap_tls_ocsp_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Eap Tls Ocsp Enabled","default":false},"eap_tls_ca_cert":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Ca Cert"},"eap_tls_ca_cert_info":{"anyOf":[{"$ref":"#/components/schemas/EapTlsCaCertInfo"},{"type":"null"}]},"eap_tls_crl_pem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Crl Pem"},"eap_tls_crl_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Crl Url"},"eap_tls_crl_last_fetched_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Crl Last Fetched At"},"eap_tls_crl_fetch_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eap Tls Crl Fetch Error"},"eap_tls_crl_info":{"anyOf":[{"$ref":"#/components/schemas/EapTlsCrlInfo"},{"type":"null"}]}},"type":"object","required":["config_id","display_name","servers","bind_dn"],"title":"LDAPConfigResponse","description":"Schema for an LDAP configuration in API responses.\n\nFields use Optional with defaults to handle existing configs\nthat were created before new fields were added."},"LDAPConfigUpdate":{"properties":{"display_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Display Name"},"directory_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Directory Type"},"servers":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Servers"},"bind_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Bind Dn"},"bind_password":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Bind Password"},"domain_suffix":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Domain Suffix"},"netbios_name":{"anyOf":[{"type":"string","maxLength":15},{"type":"null"}],"title":"Netbios Name"},"priority":{"anyOf":[{"type":"integer","maximum":999.0,"minimum":1.0},{"type":"null"}],"title":"Priority"},"user_search_bases":{"anyOf":[{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100},{"type":"null"}],"title":"User Search Bases"},"user_search_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"User Search Filter"},"group_search_bases":{"anyOf":[{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100},{"type":"null"}],"title":"Group Search Bases"},"group_search_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Group Search Filter"},"sync_group_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Sync Group Filter"},"sync_user_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Sync User Filter"},"sync_group_dns":{"anyOf":[{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100},{"type":"null"}],"title":"Sync Group Dns"},"user_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":100},{"type":"null"}],"title":"User Attr Map"},"group_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":100},{"type":"null"}],"title":"Group Attr Map"},"sync_mode":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Sync Mode"},"sync_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Enabled"},"sync_interval_minutes":{"anyOf":[{"type":"integer","maximum":10080.0,"minimum":5.0},{"type":"null"}],"title":"Sync Interval Minutes"},"sync_create_users":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Create Users"},"sync_disable_missing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Disable Missing"},"sync_remove_stale_users":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Remove Stale Users"},"sync_remove_stale_groups":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Sync Remove Stale Groups"},"default_rbac_model_id":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Default Rbac Model Id"},"group_rbac_mapping":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":1000},{"type":"null"}],"title":"Group Rbac Mapping"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"},"use_start_tls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Start Tls"},"tls_validate":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Tls Validate"},"tls_ca_cert":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Tls Ca Cert"},"connection_timeout":{"anyOf":[{"type":"integer","maximum":300.0,"minimum":1.0},{"type":"null"}],"title":"Connection Timeout"},"pool_strategy":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Pool Strategy"},"pool_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Pool Active"},"pool_exhaust":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":0.0},{"type":"null"}],"title":"Pool Exhaust"},"computer_sync_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Enabled"},"computer_search_bases":{"anyOf":[{"items":{"type":"string","maxLength":1024},"type":"array","maxItems":100},{"type":"null"}],"title":"Computer Search Bases"},"computer_search_filter":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Computer Search Filter"},"computer_mac_attr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Computer Mac Attr"},"computer_attr_map":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object","maxProperties":100},{"type":"null"}],"title":"Computer Attr Map"},"computer_sync_create":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Create"},"computer_sync_update":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Update"},"computer_sync_deactivate_missing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Deactivate Missing"},"computer_sync_delete_missing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Computer Sync Delete Missing"},"eap_tls_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Eap Tls Enabled"},"eap_tls_cert_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Eap Tls Cert Type"},"eap_tls_identity_match":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Eap Tls Identity Match"},"eap_tls_check_crl":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Eap Tls Check Crl"},"eap_tls_ocsp_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Eap Tls Ocsp Enabled"},"eap_tls_ca_cert":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Eap Tls Ca Cert"},"eap_tls_crl_pem":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Eap Tls Crl Pem"},"eap_tls_crl_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Eap Tls Crl Url"}},"type":"object","title":"LDAPConfigUpdate","description":"Schema for updating an LDAP configuration. All fields optional.\n\nDELIBERATELY no ``extra=\"forbid\"``: the edit / computer-sync / eap-tls admin\nforms each post the FULL create-shaped body (including ``config_id``, which\ntravels in the URL path and has no field here), so forbidding extras would\n422 every save. We add length bounds + whitespace strip only — and keep the\nenum-ish fields (sync_mode, pool_strategy, eap_tls_*) as bounded free strings\nrather than ``Literal`` so a previously-stored value re-submitted unchanged\ncan never be rejected. No charset/format regex on DNs / filters / attrs."},"LDAPGroupMember":{"properties":{"dn":{"type":"string","title":"Dn"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"object_type":{"type":"string","title":"Object Type","description":"user | group | other"},"already_synced":{"type":"boolean","title":"Already Synced","description":"True if this user already exists in taranac DB","default":false}},"type":"object","required":["dn","object_type"],"title":"LDAPGroupMember","description":"Single member of an LDAP group."},"LDAPGroupMembersRequest":{"properties":{"group_dn":{"type":"string","maxLength":1024,"minLength":1,"title":"Group Dn","description":"DN of the group to inspect"},"page":{"type":"integer","maximum":100000.0,"minimum":1.0,"title":"Page","default":1},"per_page":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"Per Page","default":50}},"additionalProperties":false,"type":"object","required":["group_dn"],"title":"LDAPGroupMembersRequest","description":"Request for previewing group members from LDAP."},"LDAPGroupMembersResponse":{"properties":{"group_dn":{"type":"string","title":"Group Dn"},"group_name":{"type":"string","title":"Group Name"},"members":{"items":{"$ref":"#/components/schemas/LDAPGroupMember"},"type":"array","title":"Members"},"total_members":{"type":"integer","title":"Total Members"},"page":{"type":"integer","title":"Page"},"per_page":{"type":"integer","title":"Per Page"}},"type":"object","required":["group_dn","group_name","members","total_members","page","per_page"],"title":"LDAPGroupMembersResponse","description":"Response from the LDAP group members preview."},"LDAPSearchDirectoryRequest":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query","description":"Search term"},"base_dn":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Base Dn","description":"Scope search under this DN. NULL = search from root."},"object_types":{"items":{"type":"string","maxLength":255},"type":"array","maxItems":50,"title":"Object Types","description":"Object types to search"},"max_results":{"type":"integer","maximum":500.0,"minimum":1.0,"title":"Max Results","default":100}},"additionalProperties":false,"type":"object","required":["query"],"title":"LDAPSearchDirectoryRequest","description":"Request for searching the LDAP directory."},"LabelKind":{"type":"string","enum":["pin","baseline","golden","approved","tag"],"title":"LabelKind","description":"The role a version label assigns to a snapshot.\n\n``pin`` is the retention anchor (chunk L must never prune a pinned snapshot);\n``baseline``/``golden``/``approved`` are diff anchors. Applying any of the\nlatter auto-materialises a ``pin`` (see the service invariant).\n\n``tag`` is a purely user-facing label (a free ``title`` + optional ``note``) with\n**no anchor semantics** — no auto-pin, no baseline touch. It is managed through a\ndedicated ``set_tag``/``clear_tag`` path (never ``apply_label``), so the anchor\ninvariants that drift-detection + retention depend on stay untouched."},"LeaseRenewRequest":{"properties":{"ingest_keys":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Ingest Keys","description":"The ingest_keys (the generic transport handle) the collector still holds and is working."}},"additionalProperties":false,"type":"object","required":["ingest_keys"],"title":"LeaseRenewRequest","description":"A collector's mid-collect request to extend the lease on its claimed targets."},"LeaseRenewResponse":{"properties":{"renewed":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Renewed"}},"type":"object","title":"LeaseRenewResponse","description":"The subset of requested ingest_keys whose lease was actually extended.\n\nAn ingest_key not in ``renewed`` is no longer the collector's to renew (done,\nre-dispatched to another collector after its lease lapsed, or unknown) — the\ncollector should stop working it."},"LicenseStatusResponse":{"properties":{"edition":{"type":"string","enum":["community","pro"],"title":"Edition"},"installation_id":{"type":"string","title":"Installation Id"},"licensed":{"type":"boolean","title":"Licensed","description":"True when a valid, correctly-bound license is active."},"problem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Problem"},"license_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"License Id"},"issued_to":{"anyOf":[{"$ref":"#/components/schemas/IssuedTo"},{"type":"null"}]},"issued_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Issued At"},"features":{"items":{"type":"string"},"type":"array","title":"Features"},"max_nodes":{"type":"integer","title":"Max Nodes","default":1},"support":{"anyOf":[{"$ref":"#/components/schemas/SupportStatus"},{"type":"null"}]}},"type":"object","required":["edition","installation_id","licensed"],"title":"LicenseStatusResponse","description":"Current licensing state for the UI.\n\n``problem`` is set only when a license blob IS stored but cannot be honoured\n(bad signature, wrong installation, …); the product then runs as Community.\nIt is a stable machine code the frontend localizes."},"LicenseUploadRequest":{"properties":{"license":{"type":"string","minLength":1,"title":"License","description":"Raw .lic file contents (signed JSON)."}},"type":"object","required":["license"],"title":"LicenseUploadRequest","description":"A `.lic` file's contents, pasted or read from the uploaded file."},"LimitCapabilitySummary":{"properties":{"default":{"type":"integer","title":"Default"},"max":{"type":"integer","title":"Max"}},"type":"object","required":["default","max"],"title":"LimitCapabilitySummary","description":"Row-cap control (raw table only)."},"LogBindingCreate":{"properties":{"syslog_destination_id":{"type":"string","format":"uuid","title":"Syslog Destination Id"},"module":{"type":"string","enum":["tacacs","radius","nac","system"],"title":"Module"},"log_type":{"type":"string","maxLength":16,"minLength":1,"title":"Log Type"},"facility_override":{"anyOf":[{"type":"string","enum":["kern","user","mail","daemon","auth","syslog","lpr","news","local0","local1","local2","local3","local4","local5","local6","local7"]},{"type":"null"}],"title":"Facility Override"},"severity_override":{"anyOf":[{"type":"string","enum":["emerg","alert","crit","err","warning","notice","info","debug"]},{"type":"null"}],"title":"Severity Override"}},"additionalProperties":false,"type":"object","required":["syslog_destination_id","module","log_type"],"title":"LogBindingCreate","description":"Schema for creating a log binding."},"LogBindingResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"module":{"type":"string","title":"Module"},"log_type":{"type":"string","title":"Log Type"},"facility_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facility Override"},"severity_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Severity Override"}},"type":"object","required":["id","module","log_type"],"title":"LogBindingResponse","description":"Log binding within a destination response."},"LogExclusionCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"match_type":{"type":"string","enum":["username","username_pattern","user_group"],"title":"Match Type"},"match_value":{"type":"string","maxLength":256,"minLength":1,"title":"Match Value"},"nas_filter":{"type":"string","enum":["any","network_object","device_group"],"title":"Nas Filter","default":"any"},"nas_value":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Nas Value"},"exclude_authn":{"type":"boolean","title":"Exclude Authn","default":true},"exclude_authz":{"type":"boolean","title":"Exclude Authz","default":true},"exclude_acct":{"type":"boolean","title":"Exclude Acct","default":true},"protocol":{"type":"string","enum":["all","tacacs","radius"],"title":"Protocol","default":"all"},"exclude_from_db":{"type":"boolean","title":"Exclude From Db","default":true},"exclude_from_syslog":{"type":"boolean","title":"Exclude From Syslog","default":false},"exclude_from_alerts":{"type":"boolean","title":"Exclude From Alerts","default":true},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true}},"additionalProperties":false,"type":"object","required":["name","match_type","match_value"],"title":"LogExclusionCreate","description":"Schema for creating a new log exclusion rule."},"LogExclusionListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"match_type":{"type":"string","title":"Match Type"},"match_value":{"type":"string","title":"Match Value"},"protocol":{"type":"string","title":"Protocol"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","match_type","match_value","protocol","is_enabled","created_at"],"title":"LogExclusionListResponse","description":"Abbreviated log exclusion for list views."},"LogExclusionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"match_type":{"type":"string","title":"Match Type"},"match_value":{"type":"string","title":"Match Value"},"nas_filter":{"type":"string","title":"Nas Filter"},"nas_value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nas Value"},"exclude_authn":{"type":"boolean","title":"Exclude Authn"},"exclude_authz":{"type":"boolean","title":"Exclude Authz"},"exclude_acct":{"type":"boolean","title":"Exclude Acct"},"protocol":{"type":"string","title":"Protocol"},"exclude_from_db":{"type":"boolean","title":"Exclude From Db"},"exclude_from_syslog":{"type":"boolean","title":"Exclude From Syslog"},"exclude_from_alerts":{"type":"boolean","title":"Exclude From Alerts"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","match_type","match_value","nas_filter","exclude_authn","exclude_authz","exclude_acct","protocol","exclude_from_db","exclude_from_syslog","exclude_from_alerts","is_enabled","created_at","updated_at"],"title":"LogExclusionResponse","description":"Full log exclusion response."},"LogExclusionUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"match_type":{"anyOf":[{"type":"string","enum":["username","username_pattern","user_group"]},{"type":"null"}],"title":"Match Type"},"match_value":{"anyOf":[{"type":"string","maxLength":256,"minLength":1},{"type":"null"}],"title":"Match Value"},"nas_filter":{"anyOf":[{"type":"string","enum":["any","network_object","device_group"]},{"type":"null"}],"title":"Nas Filter"},"nas_value":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Nas Value"},"exclude_authn":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Exclude Authn"},"exclude_authz":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Exclude Authz"},"exclude_acct":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Exclude Acct"},"protocol":{"anyOf":[{"type":"string","enum":["all","tacacs","radius"]},{"type":"null"}],"title":"Protocol"},"exclude_from_db":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Exclude From Db"},"exclude_from_syslog":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Exclude From Syslog"},"exclude_from_alerts":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Exclude From Alerts"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"}},"additionalProperties":false,"type":"object","title":"LogExclusionUpdate","description":"Schema for updating a log exclusion rule. All fields optional."},"LogRotationStatusResponse":{"properties":{"generated_at":{"type":"string","format":"date-time","title":"Generated At"},"tables":{"items":{"$ref":"#/components/schemas/RotatedTableStatus"},"type":"array","title":"Tables"}},"type":"object","required":["generated_at","tables"],"title":"LogRotationStatusResponse","description":"Full rotation status across every rotated table."},"LoginHint":{"properties":{"username":{"type":"string","title":"Username","description":"Username to pre-fill on the login form"},"password":{"type":"string","title":"Password","description":"Password to pre-fill on the login form"}},"type":"object","required":["username","password"],"title":"LoginHint","description":"Pre-fill credentials advertised by /auth/bootstrap for non-prod stands."},"LoginRequest":{"properties":{"username":{"type":"string","maxLength":150,"minLength":1,"title":"Username"},"password":{"type":"string","maxLength":256,"minLength":1,"title":"Password"},"client_ip":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Client Ip","description":"Forwarded client IP (set by middleware if absent)"},"captcha_token":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Captcha Token","description":"ALTCHA solution — only required after repeated failures (see captcha_required)."},"website":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Website","description":"Honeypot — must stay empty; a filled value flags an automated submission."}},"type":"object","required":["username","password"],"title":"LoginRequest","description":"POST /auth/login request body."},"LoginResponse":{"properties":{"access_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Access Token"},"refresh_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Refresh Token"},"token_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Token Type"},"mfa_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Required"},"mfa_setup_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Setup Required"},"mfa_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mfa Token"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"must_change_password":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Must Change Password"},"password_expired":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Password Expired"},"captcha_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Captcha Required"}},"type":"object","title":"LoginResponse","description":"Union-style login response.\n\nThe router returns one of the concrete sub-types above; this model is\nused only for OpenAPI documentation via ``response_model``."},"LogoutRequest":{"properties":{"refresh_token":{"type":"string","maxLength":4096,"minLength":1,"title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"LogoutRequest","description":"POST /auth/logout request body."},"MemoryMetrics":{"properties":{"total_bytes":{"type":"integer","title":"Total Bytes"},"available_bytes":{"type":"integer","title":"Available Bytes"},"used_bytes":{"type":"integer","title":"Used Bytes"},"percent":{"type":"number","title":"Percent"},"total_human":{"type":"string","title":"Total Human"},"available_human":{"type":"string","title":"Available Human"},"used_human":{"type":"string","title":"Used Human"}},"type":"object","required":["total_bytes","available_bytes","used_bytes","percent","total_human","available_human","used_human"],"title":"MemoryMetrics","description":"Memory metric snapshot."},"MessageResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"MessageResponse","description":"Generic message response used by logout, change-password, etc."},"MetricsSnapshot":{"properties":{"timestamp":{"type":"string","title":"Timestamp"},"cpu":{"$ref":"#/components/schemas/CpuMetrics"},"memory":{"$ref":"#/components/schemas/MemoryMetrics"},"swap":{"$ref":"#/components/schemas/SwapMetrics"},"disks":{"items":{"$ref":"#/components/schemas/DiskMetrics"},"type":"array","title":"Disks"},"network":{"$ref":"#/components/schemas/NetworkMetrics"},"uptime":{"$ref":"#/components/schemas/UptimeMetrics"}},"type":"object","required":["timestamp","cpu","memory","swap","network","uptime"],"title":"MetricsSnapshot","description":"Complete system metrics snapshot."},"MfaActivateRequest":{"properties":{"user_mfa_id":{"type":"string","format":"uuid","title":"User Mfa Id"},"code":{"type":"string","maxLength":64,"title":"Code","default":""}},"type":"object","required":["user_mfa_id"],"title":"MfaActivateRequest","description":"POST /mfa/activate request body."},"MfaActivateResponse":{"properties":{"status":{"type":"string","title":"Status","default":"activated"},"backup_codes":{"items":{"type":"string"},"type":"array","title":"Backup Codes"}},"type":"object","title":"MfaActivateResponse","description":"POST /mfa/activate response."},"MfaAdminResetResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"MfaAdminResetResponse","description":"DELETE /mfa/users/{id}/reset response."},"MfaBackupCodesResponse":{"properties":{"backup_codes":{"items":{"type":"string"},"type":"array","title":"Backup Codes"}},"type":"object","required":["backup_codes"],"title":"MfaBackupCodesResponse","description":"POST /mfa/users/{id}/backup-codes response."},"MfaChallengeRequest":{"properties":{"mfa_token":{"type":"string","maxLength":4096,"minLength":1,"title":"Mfa Token"}},"type":"object","required":["mfa_token"],"title":"MfaChallengeRequest","description":"POST /mfa/challenge request body."},"MfaChallengeResponse":{"properties":{"challenge_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Challenge Id"},"prompt_type":{"type":"string","title":"Prompt Type"},"prompt_data":{"additionalProperties":true,"type":"object","title":"Prompt Data"},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"},"provider":{"type":"string","title":"Provider"},"mode":{"type":"string","title":"Mode"}},"type":"object","required":["prompt_type","provider","mode"],"title":"MfaChallengeResponse","description":"POST /mfa/challenge response."},"MfaChallengeStatusResponse":{"properties":{"status":{"type":"string","title":"Status"},"resolved_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved At"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["status"],"title":"MfaChallengeStatusResponse","description":"GET /mfa/challenge/{id}/status response."},"MfaEnrollRequest":{"properties":{"provider":{"type":"string","maxLength":64,"title":"Provider","description":"MFA provider to enroll: totp, telegram, multifactor, email_push"}},"type":"object","required":["provider"],"title":"MfaEnrollRequest","description":"POST /mfa/enroll request body."},"MfaEnrollResponse":{"properties":{"user_mfa_id":{"type":"string","title":"User Mfa Id"},"provider":{"type":"string","title":"Provider"},"requires_activation":{"type":"boolean","title":"Requires Activation"},"qr_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qr Code"},"secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret"},"issuer":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"deep_link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deep Link"},"expires_in":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Expires In"},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode"},"serial":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial"},"otpauth_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Otpauth Url"},"pushurl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pushurl"}},"type":"object","required":["user_mfa_id","provider","requires_activation"],"title":"MfaEnrollResponse","description":"POST /mfa/enroll response — provider-specific enrollment data."},"MfaEnrolledProvider":{"properties":{"id":{"type":"string","title":"Id"},"provider":{"type":"string","title":"Provider"},"mode":{"type":"string","title":"Mode"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"last_used_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Used At"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","provider","mode","is_enabled"],"title":"MfaEnrolledProvider","description":"Single enrolled provider in status response."},"MfaHealthResponse":{"properties":{"providers":{"items":{"$ref":"#/components/schemas/MfaProviderInfo"},"type":"array","title":"Providers"}},"type":"object","required":["providers"],"title":"MfaHealthResponse","description":"GET /mfa/health response (admin)."},"MfaInternalChallengeRequest":{"properties":{"user_id":{"type":"string","maxLength":64,"minLength":1,"title":"User Id","description":"User UUID from users table"},"ip_address":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ip Address","description":"Client IP for push context"},"user_agent":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"User Agent","description":"Calling service identifier","default":"MAVIS/TACACS"},"auth_context":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Auth Context","description":"tacacs, radius, or nac"},"nas_ip":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nas Ip","description":"NAS device IP for push context"},"username":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Username","description":"Username for push notification display"},"target":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Target","description":"Target device name/hostname for push notification"}},"type":"object","required":["user_id"],"title":"MfaInternalChallengeRequest","description":"POST /mfa/internal/challenge — create push challenge.\n\nCalled by the RADIUS/NAC daemons + MAVIS during live auth (NOT the frontend),\nso NO extra=\"forbid\" — bounds only, to never 422 an in-flight authentication."},"MfaInternalChallengeResponse":{"properties":{"challenge_id":{"type":"string","title":"Challenge Id"},"prompt_type":{"type":"string","title":"Prompt Type"},"prompt_data":{"additionalProperties":true,"type":"object","title":"Prompt Data"},"expires_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expires At"},"provider":{"type":"string","title":"Provider"},"mode":{"type":"string","title":"Mode"}},"type":"object","required":["challenge_id","prompt_type","provider","mode"],"title":"MfaInternalChallengeResponse","description":"POST /mfa/internal/challenge response."},"MfaInternalVerifyRequest":{"properties":{"user_id":{"type":"string","maxLength":64,"minLength":1,"title":"User Id","description":"User UUID from users table"},"code":{"type":"string","maxLength":64,"minLength":1,"title":"Code","description":"OTP code entered by user"},"auth_context":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Auth Context","description":"tacacs, radius, or nac"}},"type":"object","required":["user_id","code"],"title":"MfaInternalVerifyRequest","description":"POST /mfa/internal/verify — verify OTP code.\n\nCalled by the RADIUS/NAC daemons + MAVIS during live auth (NOT the frontend),\nso NO extra=\"forbid\" — bounds only."},"MfaInternalVerifyResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode"}},"type":"object","required":["success"],"title":"MfaInternalVerifyResponse","description":"POST /mfa/internal/verify response."},"MfaProviderInfo":{"properties":{"name":{"type":"string","title":"Name"},"mode":{"type":"string","title":"Mode"},"enabled":{"type":"boolean","title":"Enabled","default":true},"available":{"type":"boolean","title":"Available"},"status_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Message"},"status_details":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Status Details"}},"type":"object","required":["name","mode","available"],"title":"MfaProviderInfo","description":"Single provider info in providers list."},"MfaProviderResolved":{"properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider","description":"Active MFA provider name (totp, telegram, multifactor, email_push, taranac_mfa) or null"},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode","description":"Provider mode: totp, push, combined — or null if no provider"},"source":{"type":"string","title":"Source","description":"Resolution source: 'user' (enrolled), 'group:<name>' (required), 'none'"},"is_required":{"type":"boolean","title":"Is Required","description":"True if MFA is required by group membership (mfa_required=true)","default":false},"has_provider":{"type":"boolean","title":"Has Provider","description":"True if user has an active (enabled) MFA enrollment","default":false}},"type":"object","required":["source"],"title":"MfaProviderResolved","description":"Resolved MFA provider for the tested user.\n\nShows which provider the user has enrolled, whether MFA is required\nby their group membership, and whether there is a gap (required but\nno provider enrolled)."},"MfaProvidersResponse":{"properties":{"providers":{"items":{"$ref":"#/components/schemas/MfaProviderInfo"},"type":"array","title":"Providers"}},"type":"object","required":["providers"],"title":"MfaProvidersResponse","description":"GET /mfa/providers response."},"MfaPushCallbackResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"MfaPushCallbackResponse","description":"Response for push callback endpoints."},"MfaResendResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"MfaResendResponse","description":"POST /mfa/enroll/resend response."},"MfaStatusResponse":{"properties":{"is_required":{"type":"boolean","title":"Is Required"},"resolved_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved Provider"},"resolved_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved Mode"},"resolution_source":{"type":"string","title":"Resolution Source"},"enrolled":{"items":{"$ref":"#/components/schemas/MfaEnrolledProvider"},"type":"array","title":"Enrolled"}},"type":"object","required":["is_required","resolution_source","enrolled"],"title":"MfaStatusResponse","description":"GET /mfa/status response."},"MfaUnenrollResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"MfaUnenrollResponse","description":"DELETE /mfa/unenroll/{id} response."},"MfaVerifyRequest":{"properties":{"mfa_token":{"type":"string","maxLength":4096,"minLength":1,"title":"Mfa Token"},"code":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Code"},"challenge_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Challenge Id"}},"type":"object","required":["mfa_token"],"title":"MfaVerifyRequest","description":"POST /mfa/verify request body."},"MfaVerifyResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"MfaVerifyResponse","description":"POST /mfa/verify response — full auth tokens."},"MonthBucket":{"properties":{"year_month":{"type":"string","title":"Year Month"},"month":{"type":"string","title":"Month"},"file_count":{"type":"integer","title":"File Count"},"total_bytes":{"type":"integer","title":"Total Bytes"},"is_current":{"type":"boolean","title":"Is Current"},"retained_until":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Retained Until"}},"type":"object","required":["year_month","month","file_count","total_bytes","is_current"],"title":"MonthBucket","description":"One forensic month-bucket (summed across every ``log_type``).\n\nFiles are *not* listed here — they are lazy-loaded per month via\n``GET /daemon-logs/forensic/{group}/{year_month}/files``."},"NacActivityBucket":{"properties":{"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"accept":{"type":"integer","title":"Accept","default":0},"reject":{"type":"integer","title":"Reject","default":0}},"type":"object","required":["timestamp"],"title":"NacActivityBucket","description":"Single time-bucket with NAC accept/reject counts."},"NacActivityResponse":{"properties":{"period":{"type":"string","title":"Period"},"interval":{"type":"string","title":"Interval"},"buckets":{"items":{"$ref":"#/components/schemas/NacActivityBucket"},"type":"array","title":"Buckets"},"totals":{"$ref":"#/components/schemas/NacActivityTotals"}},"type":"object","required":["period","interval","buckets","totals"],"title":"NacActivityResponse","description":"Response for the nac-activity chart widget."},"NacActivityTotals":{"properties":{"accept":{"type":"integer","title":"Accept","default":0},"reject":{"type":"integer","title":"Reject","default":0}},"type":"object","title":"NacActivityTotals","description":"Period totals across all NAC buckets."},"NacAuthLogListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"nas_port_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nas Port Id"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"called_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Called Station Id"},"acct_session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acct Session Id"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"auth_method":{"type":"string","title":"Auth Method"},"inner_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inner Method"},"status":{"type":"string","title":"Status"},"reject_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Reason"},"reject_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Message"},"endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Endpoint Id"},"endpoint_mac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Mac"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"rule_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rule Id"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"rule_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Name"},"profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Profile Id"},"profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Name"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"},"auth_duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Auth Duration Ms"},"mfa_enforced":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Enforced"},"mfa_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mfa Status"},"detected_vendor_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Key"},"detected_vendor_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Source"},"endpoint_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Name"},"endpoint_vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Vendor"},"endpoint_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Status"},"device_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Location"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","auth_method","status"],"title":"NacAuthLogListResponse","description":"Compact NAC auth log item for list endpoints.\n\nIncludes enrichment fields resolved from joined endpoint/device\ntables for human-readable display in the UI."},"NacAuthLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"nas_port_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nas Port Id"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"called_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Called Station Id"},"acct_session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acct Session Id"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"auth_method":{"type":"string","title":"Auth Method"},"inner_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inner Method"},"status":{"type":"string","title":"Status"},"reject_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Reason"},"reject_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Message"},"endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Endpoint Id"},"endpoint_mac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Mac"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"rule_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Rule Id"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"rule_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Name"},"profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Profile Id"},"profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Name"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"},"auth_duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Auth Duration Ms"},"mfa_enforced":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Enforced"},"mfa_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mfa Status"},"detected_vendor_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Key"},"detected_vendor_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Source"},"endpoint_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Name"},"endpoint_vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Vendor"},"endpoint_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Status"},"device_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Location"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"},"raw_request":{"additionalProperties":true,"type":"object","title":"Raw Request"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","timestamp","nas_ip","auth_method","status","raw_request","created_at"],"title":"NacAuthLogResponse","description":"Full NAC auth log entry with sanitized raw_request payload."},"NacAuthorizationProfileCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"vlan_id":{"anyOf":[{"type":"integer","maximum":4094.0,"minimum":1.0},{"type":"null"}],"title":"Vlan Id"},"vlan_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Vlan Name"},"acl_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Acl Name"},"acl_lines":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":256},{"type":"null"}],"title":"Acl Lines"},"session_timeout":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Session Timeout"},"reauth_timer":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Reauth Timer"},"url_redirect":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Url Redirect"},"url_redirect_acl":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Url Redirect Acl"},"extra_attributes":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":256},{"type":"null"}],"title":"Extra Attributes"}},"additionalProperties":false,"type":"object","required":["name"],"title":"NacAuthorizationProfileCreate","description":"Schema for creating a new authorization profile."},"NacAuthorizationProfilePreviewResponse":{"properties":{"profile_id":{"type":"string","format":"uuid","title":"Profile Id"},"profile_name":{"type":"string","title":"Profile Name"},"vendors":{"items":{"$ref":"#/components/schemas/VendorPreviewEntry"},"type":"array","title":"Vendors"}},"type":"object","required":["profile_id","profile_name"],"title":"NacAuthorizationProfilePreviewResponse","description":"Preview of RADIUS attributes that a profile would return.\n\nContains per-vendor preview showing how each vendor would receive\nthe profile's intent as RADIUS attributes."},"NacAuthorizationProfileResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"},"vlan_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vlan Name"},"acl_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acl Name"},"acl_lines":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Acl Lines"},"session_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Timeout"},"reauth_timer":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Reauth Timer"},"url_redirect":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url Redirect"},"url_redirect_acl":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url Redirect Acl"},"extra_attributes":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Extra Attributes"},"usage_count":{"type":"integer","title":"Usage Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","usage_count","created_at","updated_at"],"title":"NacAuthorizationProfileResponse","description":"Full authorization profile response."},"NacAuthorizationProfileUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"vlan_id":{"anyOf":[{"type":"integer","maximum":4094.0,"minimum":1.0},{"type":"null"}],"title":"Vlan Id"},"vlan_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Vlan Name"},"acl_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Acl Name"},"acl_lines":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":256},{"type":"null"}],"title":"Acl Lines"},"session_timeout":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Session Timeout"},"reauth_timer":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Reauth Timer"},"url_redirect":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Url Redirect"},"url_redirect_acl":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Url Redirect Acl"},"extra_attributes":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":256},{"type":"null"}],"title":"Extra Attributes"}},"additionalProperties":false,"type":"object","title":"NacAuthorizationProfileUpdate","description":"Schema for updating an authorization profile. All fields optional."},"NacCoaResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"session_id":{"type":"string","title":"Session Id"},"nas_ip":{"type":"string","title":"Nas Ip"},"action":{"type":"string","title":"Action"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["success","session_id","nas_ip","action"],"title":"NacCoaResponse","description":"Result of a CoA action (disconnect, reauth, vlan-change, bounce-port)."},"NacCoaVlanChangeRequest":{"properties":{"vlan_id":{"type":"integer","maximum":4094.0,"minimum":1.0,"title":"Vlan Id","description":"Target VLAN ID (1-4094)"}},"additionalProperties":false,"type":"object","required":["vlan_id"],"title":"NacCoaVlanChangeRequest","description":"Request body for CoA VLAN Change.\n\nextra=\"forbid\": admin-only (the UI posts exactly ``{vlan_id}``)."},"NacConfigPreviewResponse":{"properties":{"files":{"additionalProperties":{"type":"string"},"type":"object","title":"Files"},"total_size":{"type":"integer","title":"Total Size"}},"type":"object","required":["files","total_size"],"title":"NacConfigPreviewResponse","description":"Response for config preview (multi-file)."},"NacConfigReloadResponse":{"properties":{"status":{"type":"string","title":"Status"},"config_dir":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Config Dir"},"files":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Files"},"total_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Size"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"timestamp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timestamp"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["status"],"title":"NacConfigReloadResponse","description":"Response for config reload."},"NacConfigSnippetLineSchema":{"properties":{"num":{"type":"integer","title":"Num"},"text":{"type":"string","title":"Text"},"error":{"type":"boolean","title":"Error","default":false}},"type":"object","required":["num","text"],"title":"NacConfigSnippetLineSchema","description":"A single line in a config error snippet."},"NacConfigStatusInfo":{"properties":{"deployed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed At"},"deployed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed By"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"files":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Files"},"total_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Size"},"validation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Validation"}},"type":"object","title":"NacConfigStatusInfo","description":"Config deploy and validation status."},"NacConfigValidateResponse":{"properties":{"valid":{"type":"boolean","title":"Valid"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"files":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Files"},"total_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Size"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error File"},"error_line":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Error Line"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"config_snippet":{"anyOf":[{"items":{"$ref":"#/components/schemas/NacConfigSnippetLineSchema"},"type":"array"},{"type":"null"}],"title":"Config Snippet"},"raw_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Error"}},"type":"object","required":["valid"],"title":"NacConfigValidateResponse","description":"Response for config validation (dry-run)."},"NacPkiSettingsResponse":{"properties":{"pki_public_base_url":{"type":"string","title":"Pki Public Base Url","default":""},"est_enabled":{"type":"boolean","title":"Est Enabled","default":false},"est_ca_id":{"type":"string","title":"Est Ca Id","default":""},"est_cert_validity_days":{"type":"integer","title":"Est Cert Validity Days","default":365},"est_require_approval":{"type":"boolean","title":"Est Require Approval","default":false},"est_approval_group_id":{"type":"string","title":"Est Approval Group Id","default":""},"est_request_ttl_days":{"type":"integer","title":"Est Request Ttl Days","default":30},"est_approval_link_ttl_days":{"type":"integer","title":"Est Approval Link Ttl Days","default":7},"est_allowed_auth":{"type":"string","title":"Est Allowed Auth","default":"basic,tls"},"est_identity_binding":{"type":"string","title":"Est Identity Binding","default":"strict"},"est_mtls_proxy_secret":{"type":"string","title":"Est Mtls Proxy Secret","default":""},"cert_default_ca_id":{"type":"string","title":"Cert Default Ca Id","default":""},"cert_default_key_algorithm":{"type":"string","title":"Cert Default Key Algorithm","default":"ec256"},"cert_default_validity_days":{"type":"integer","title":"Cert Default Validity Days","default":365},"cert_default_san_from_user":{"type":"boolean","title":"Cert Default San From User","default":true},"cert_default_subject_template":{"type":"string","title":"Cert Default Subject Template","default":"{username}"},"cert_default_name_template":{"type":"string","title":"Cert Default Name Template","default":"{display_name} - Certificate"},"auto_issue_on_user_create":{"type":"boolean","title":"Auto Issue On User Create","default":false},"auto_issue_on_ldap_sync":{"type":"boolean","title":"Auto Issue On Ldap Sync","default":false},"auto_issue_send_email":{"type":"boolean","title":"Auto Issue Send Email","default":true},"cert_download_token_expiry_hours":{"type":"integer","title":"Cert Download Token Expiry Hours","default":72}},"type":"object","title":"NacPkiSettingsResponse","description":"Full PKI/EST settings document returned by GET."},"NacPkiSettingsUpdate":{"properties":{"pki_public_base_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Pki Public Base Url"},"est_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Est Enabled"},"est_ca_id":{"anyOf":[{"type":"string","maxLength":36},{"type":"null"}],"title":"Est Ca Id"},"est_cert_validity_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Est Cert Validity Days"},"est_require_approval":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Est Require Approval"},"est_approval_group_id":{"anyOf":[{"type":"string","maxLength":36},{"type":"null"}],"title":"Est Approval Group Id"},"est_request_ttl_days":{"anyOf":[{"type":"integer","maximum":365.0,"minimum":1.0},{"type":"null"}],"title":"Est Request Ttl Days"},"est_approval_link_ttl_days":{"anyOf":[{"type":"integer","maximum":90.0,"minimum":1.0},{"type":"null"}],"title":"Est Approval Link Ttl Days"},"est_allowed_auth":{"anyOf":[{"type":"string","pattern":"^(basic|tls)(,(basic|tls))*$"},{"type":"null"}],"title":"Est Allowed Auth"},"est_identity_binding":{"anyOf":[{"type":"string","pattern":"^(strict|device)$"},{"type":"null"}],"title":"Est Identity Binding"},"est_mtls_proxy_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Est Mtls Proxy Secret"},"cert_default_ca_id":{"anyOf":[{"type":"string","maxLength":36},{"type":"null"}],"title":"Cert Default Ca Id"},"cert_default_key_algorithm":{"anyOf":[{"type":"string","pattern":"^(rsa2048|rsa4096|ec256|ec384)$"},{"type":"null"}],"title":"Cert Default Key Algorithm"},"cert_default_validity_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Cert Default Validity Days"},"cert_default_san_from_user":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cert Default San From User"},"cert_default_subject_template":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Cert Default Subject Template"},"cert_default_name_template":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Cert Default Name Template"},"auto_issue_on_user_create":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Issue On User Create"},"auto_issue_on_ldap_sync":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Issue On Ldap Sync"},"auto_issue_send_email":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Issue Send Email"},"cert_download_token_expiry_hours":{"anyOf":[{"type":"integer","maximum":720.0,"minimum":1.0},{"type":"null"}],"title":"Cert Download Token Expiry Hours"}},"type":"object","title":"NacPkiSettingsUpdate","description":"Partial update for PKI/EST settings.\n\nOnly the fields present in the request body will be updated.\nOmitted fields remain unchanged in the database.\n\nDocument-style flat-settings PATCH — deliberately NO extra=\"forbid\" (same as\nthe other *SettingsUpdate documents): the GET document may surface read-only\nderived/ENV keys that a naive client echoes back on save, and a stray key must\nnever 422 a settings save. Bounds / enum patterns apply regardless."},"NacPolicyReorderRequest":{"properties":{"rule_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":10000,"minItems":1,"title":"Rule Ids","description":"Complete list of rule IDs in new order"}},"additionalProperties":false,"type":"object","required":["rule_ids"],"title":"NacPolicyReorderRequest","description":"Request body for bulk reorder."},"NacPolicyRuleCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true},"insert_at_position":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Insert At Position","description":"1-based position to insert the rule at. Existing rules at this position and below are shifted down. If omitted, the rule is appended at the end (before default rule)."},"auth_method":{"type":"string","enum":["peap","eap_tls","eap_ttls","mab","any"],"title":"Auth Method","default":"any"},"action":{"type":"string","enum":["permit","reject"],"title":"Action","default":"permit"},"mfa_required":{"type":"boolean","title":"Mfa Required","default":false},"who_any":{"type":"boolean","title":"Who Any","default":true},"who_user_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"title":"Who User Group Ids"},"what_any":{"type":"boolean","title":"What Any","default":true},"what_endpoint_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"title":"What Endpoint Group Ids"},"where_any":{"type":"boolean","title":"Where Any","default":true},"where_device_group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"title":"Where Device Group Ids"},"when_type":{"type":"string","enum":["always","time_range"],"title":"When Type","default":"always"},"when_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"When Id"},"authorization_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Authorization Profile Id"}},"additionalProperties":false,"type":"object","required":["name"],"title":"NacPolicyRuleCreate","description":"Schema for creating a new NAC policy rule."},"NacPolicyRuleResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"order":{"type":"integer","title":"Order"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"is_default":{"type":"boolean","title":"Is Default"},"auth_method":{"type":"string","title":"Auth Method"},"action":{"type":"string","title":"Action"},"mfa_required":{"type":"boolean","title":"Mfa Required"},"who_any":{"type":"boolean","title":"Who Any"},"who_user_groups":{"items":{"$ref":"#/components/schemas/app__modules__nac__nac_policy__schemas__RefItem"},"type":"array","title":"Who User Groups"},"what_any":{"type":"boolean","title":"What Any"},"what_endpoint_groups":{"items":{"$ref":"#/components/schemas/app__modules__nac__nac_policy__schemas__RefItem"},"type":"array","title":"What Endpoint Groups"},"where_any":{"type":"boolean","title":"Where Any"},"where_device_groups":{"items":{"$ref":"#/components/schemas/app__modules__nac__nac_policy__schemas__RefItem"},"type":"array","title":"Where Device Groups"},"when_type":{"type":"string","title":"When Type"},"when_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"When Id"},"when_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"When Name"},"authorization_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Authorization Profile Id"},"authorization_profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization Profile Name"},"authorization_profile_vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Authorization Profile Vlan Id"},"authorization_profile_vlan_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization Profile Vlan Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","order","is_enabled","is_default","auth_method","action","mfa_required","who_any","what_any","where_any","when_type","created_at","updated_at"],"title":"NacPolicyRuleResponse","description":"Full NAC policy rule response with resolved names."},"NacPolicyRuleUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Description"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"},"auth_method":{"anyOf":[{"type":"string","enum":["peap","eap_tls","eap_ttls","mab","any"]},{"type":"null"}],"title":"Auth Method"},"action":{"anyOf":[{"type":"string","enum":["permit","reject"]},{"type":"null"}],"title":"Action"},"mfa_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Required"},"who_any":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Who Any"},"who_user_group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500},{"type":"null"}],"title":"Who User Group Ids"},"what_any":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"What Any"},"what_endpoint_group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500},{"type":"null"}],"title":"What Endpoint Group Ids"},"where_any":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Where Any"},"where_device_group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500},{"type":"null"}],"title":"Where Device Group Ids"},"when_type":{"anyOf":[{"type":"string","enum":["always","time_range"]},{"type":"null"}],"title":"When Type"},"when_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"When Id"},"authorization_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Authorization Profile Id"}},"additionalProperties":false,"type":"object","title":"NacPolicyRuleUpdate","description":"Schema for updating a NAC policy rule. All fields optional."},"NacPolicyTestAction":{"properties":{"profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Profile Id"},"profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Name"},"action":{"type":"string","title":"Action","description":"permit | reject"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"},"vlan_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vlan Name"},"acl_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acl Name"},"session_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Timeout"},"mfa_required":{"type":"boolean","title":"Mfa Required","description":"True if the matched rule requires MFA after authentication","default":false},"mfa_enforced":{"type":"boolean","title":"Mfa Enforced","description":"True if MFA will actually be enforced (mfa_required=true AND global nac.mfa_enabled=true)","default":false}},"type":"object","required":["action"],"title":"NacPolicyTestAction","description":"Action determined by the matching rule."},"NacPolicyTestRequest":{"properties":{"mac_address":{"type":"string","title":"Mac Address","description":"Endpoint MAC address (AA:BB:CC:DD:EE:FF)"},"auth_method":{"type":"string","enum":["peap","eap_tls","eap_ttls","mab"],"title":"Auth Method","description":"Authentication method to simulate"},"username":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Username","description":"Username (required for dot1x: peap/eap_tls/eap_ttls)"},"nas_ip":{"type":"string","title":"Nas Ip","description":"NAS device IP address for WHERE matching"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp","description":"Simulated time for WHEN matching. Default: now"}},"type":"object","required":["mac_address","auth_method","nas_ip"],"title":"NacPolicyTestRequest","description":"Simulated NAC request for policy testing."},"NacPolicyTestResponse":{"properties":{"matched":{"type":"boolean","title":"Matched","description":"True if a rule matched, false if all rules were exhausted"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result","description":"'permit' or 'reject'. Null if no match."},"matched_rule":{"anyOf":[{"$ref":"#/components/schemas/app__modules__nac__nac_policy__tester_schemas__RuleTraceEntry"},{"type":"null"}],"description":"The winning rule. Null if no match."},"authorization_profile":{"anyOf":[{"$ref":"#/components/schemas/NacPolicyTestAction"},{"type":"null"}],"description":"Authorization profile details. Null if no match."},"radius_attributes":{"items":{"$ref":"#/components/schemas/RadiusAttributeEntry"},"type":"array","title":"Radius Attributes","description":"RADIUS attributes for the resolved NAS vendor (or generic fallback)"},"vendor_previews":{"items":{"$ref":"#/components/schemas/VendorAttributePreview"},"type":"array","title":"Vendor Previews","description":"RADIUS attributes for ALL vendors in the dictionary"},"evaluation_trace":{"items":{"$ref":"#/components/schemas/app__modules__nac__nac_policy__tester_schemas__RuleTraceEntry"},"type":"array","title":"Evaluation Trace","description":"Trace of every rule evaluated, in order."},"resolved_context":{"$ref":"#/components/schemas/app__modules__nac__nac_policy__tester_schemas__ResolvedContext"},"mfa_global_enabled":{"type":"boolean","title":"Mfa Global Enabled","description":"Current value of nac.mfa_enabled system setting. When false, MFA is disabled globally regardless of per-rule flags.","default":true}},"type":"object","required":["matched","resolved_context"],"title":"NacPolicyTestResponse","description":"Full NAC policy tester response."},"NacServiceConnectivity":{"properties":{"reachable":{"type":"boolean","title":"Reachable","default":false},"auth_port":{"type":"integer","title":"Auth Port","default":1822},"acct_port":{"type":"integer","title":"Acct Port","default":1823},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","title":"NacServiceConnectivity","description":"UDP connectivity check result for NAC FreeRADIUS."},"NacSessionBlockEndpointResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"endpoint_id":{"type":"string","format":"uuid","title":"Endpoint Id"},"endpoint_mac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Mac"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["success","endpoint_id","detail"],"title":"NacSessionBlockEndpointResponse","description":"Result of blocking a session's endpoint.\n\nBlocking always tears down the endpoint's live sessions via CoA as a\nbest-effort side effect (see ``EndpointService.block_endpoint``); CoA\nresults are logged server-side, not returned here."},"NacSessionDetailResponse":{"properties":{"state":{"type":"string","title":"State","default":"active"},"id":{"type":"string","format":"uuid","title":"Id"},"acct_session_id":{"type":"string","title":"Acct Session Id"},"endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Endpoint Id"},"endpoint_mac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Mac"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"nas_port_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nas Port Id"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"called_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Called Station Id"},"framed_ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Framed Ip Address"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"},"input_octets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Input Octets"},"output_octets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Octets"},"session_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Time"},"detected_vendor_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Key"},"detected_vendor_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Source"},"correlation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Correlation Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"last_updated_at":{"type":"string","format":"date-time","title":"Last Updated At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"closed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed At"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"terminate_cause":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Terminate Cause"},"endpoint_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Name"},"endpoint_vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Vendor"},"endpoint_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Status"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Location"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds","description":"Session duration in seconds for the UI \"Duration\" column.\n\nWall-clock lifetime: ``(closed_at or now) - started_at``. We deliberately\ndo NOT use the NAS-reported ``Acct-Session-Time`` (``session_time``):\nsome NAS never send it (Cisco IOS in our captures), and others report an\nunreliable value on the final Accounting-Stop (e.g. time since the last\ninterim, or since a CoA, rather than the whole session) — which would\nmake a multi-minute session show only a few seconds once closed. The\nStart→end span is unambiguous and always populated. The raw\n``session_time`` is still returned untouched as NAS-reported state.","readOnly":true}},"type":"object","required":["id","acct_session_id","nas_ip","started_at","last_updated_at","created_at","duration_seconds"],"title":"NacSessionDetailResponse","description":"Full unified session detail (extensible for future fields)."},"NacSessionDisconnectRequest":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Reason"}},"additionalProperties":false,"type":"object","title":"NacSessionDisconnectRequest","description":"Request body for CoA Disconnect.\n\nextra=\"forbid\": admin-only (the UI either posts no body or exactly these\nkeys). ``reason`` is free admin text — LENGTH-bounded, not charset-checked."},"NacSessionListResponse":{"properties":{"state":{"type":"string","title":"State","default":"active"},"id":{"type":"string","format":"uuid","title":"Id"},"acct_session_id":{"type":"string","title":"Acct Session Id"},"endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Endpoint Id"},"endpoint_mac":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Mac"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"nas_port_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nas Port Id"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"called_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Called Station Id"},"framed_ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Framed Ip Address"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"},"input_octets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Input Octets"},"output_octets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Output Octets"},"session_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Time"},"detected_vendor_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Key"},"detected_vendor_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Vendor Source"},"correlation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Correlation Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"last_updated_at":{"type":"string","format":"date-time","title":"Last Updated At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"closed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed At"},"close_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Close Reason"},"terminate_cause":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Terminate Cause"},"endpoint_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Name"},"endpoint_vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Vendor"},"endpoint_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Endpoint Status"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Location"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds","description":"Session duration in seconds for the UI \"Duration\" column.\n\nWall-clock lifetime: ``(closed_at or now) - started_at``. We deliberately\ndo NOT use the NAS-reported ``Acct-Session-Time`` (``session_time``):\nsome NAS never send it (Cisco IOS in our captures), and others report an\nunreliable value on the final Accounting-Stop (e.g. time since the last\ninterim, or since a CoA, rather than the whole session) — which would\nmake a multi-minute session show only a few seconds once closed. The\nStart→end span is unambiguous and always populated. The raw\n``session_time`` is still returned untouched as NAS-reported state.","readOnly":true}},"type":"object","required":["id","acct_session_id","nas_ip","started_at","last_updated_at","created_at","duration_seconds"],"title":"NacSessionListResponse","description":"Unified session item (active or closed) for the Sessions table."},"NacSessionTimelineEvent":{"properties":{"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"kind":{"type":"string","title":"Kind"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"auth_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Method"},"vlan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vlan Id"}},"type":"object","required":["timestamp","kind"],"title":"NacSessionTimelineEvent","description":"One event in a session's lifecycle timeline."},"NacSessionTimelineResponse":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"},"acct_session_id":{"type":"string","title":"Acct Session Id"},"state":{"type":"string","title":"State"},"correlation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Correlation Id"},"events":{"items":{"$ref":"#/components/schemas/NacSessionTimelineEvent"},"type":"array","title":"Events"}},"type":"object","required":["session_id","acct_session_id","state","events"],"title":"NacSessionTimelineResponse","description":"Ordered lifecycle of a single session (active or closed)."},"NacSettingsResponse":{"properties":{"auth_port":{"type":"integer","title":"Auth Port","default":1822},"acct_port":{"type":"integer","title":"Acct Port","default":1823},"coa_port":{"type":"integer","title":"Coa Port","default":3799},"coa_secret":{"type":"string","title":"Coa Secret","default":""},"inactive_threshold_days":{"type":"integer","title":"Inactive Threshold Days","default":30},"guest_cleanup_days":{"type":"integer","title":"Guest Cleanup Days","default":180},"dynamic_cleanup_days":{"type":"integer","title":"Dynamic Cleanup Days","default":0},"auto_classify_on_discovery":{"type":"boolean","title":"Auto Classify On Discovery","default":true},"auto_pin_ldap":{"type":"boolean","title":"Auto Pin Ldap","default":true},"auto_pin_classified":{"type":"boolean","title":"Auto Pin Classified","default":false},"dynamic_client_networks":{"type":"string","title":"Dynamic Client Networks","default":""},"dynamic_client_lifetime":{"type":"integer","title":"Dynamic Client Lifetime","default":300},"mfa_enabled":{"type":"boolean","title":"Mfa Enabled","default":true},"default_auth_method":{"type":"string","title":"Default Auth Method","default":"peap"},"mab_format":{"type":"string","title":"Mab Format","default":"lower_hyphen"},"bruteforce_enabled":{"type":"boolean","title":"Bruteforce Enabled","default":true},"bruteforce_threshold":{"type":"integer","title":"Bruteforce Threshold","default":10},"bruteforce_window_minutes":{"type":"integer","title":"Bruteforce Window Minutes","default":15},"crl_check_enable":{"type":"boolean","title":"Crl Check Enable","default":false},"crl_fetch_interval_hours":{"type":"integer","title":"Crl Fetch Interval Hours","default":6},"log_retention_days":{"type":"integer","title":"Log Retention Days","default":365},"log_auth":{"type":"boolean","title":"Log Auth","default":true},"session_cleanup_interval_hours":{"type":"integer","title":"Session Cleanup Interval Hours","default":1},"session_max_duration_hours":{"type":"integer","title":"Session Max Duration Hours","default":72}},"type":"object","title":"NacSettingsResponse","description":"Full NAC settings document returned by GET.\n\nEncrypted values (coa_secret) are masked as '***'.\nPort fields are read-only (sourced from environment variables)."},"NacSettingsUpdate":{"properties":{"coa_port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Coa Port"},"coa_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Coa Secret"},"inactive_threshold_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Inactive Threshold Days"},"guest_cleanup_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Guest Cleanup Days"},"dynamic_cleanup_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":0.0},{"type":"null"}],"title":"Dynamic Cleanup Days"},"auto_classify_on_discovery":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Classify On Discovery"},"auto_pin_ldap":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Pin Ldap"},"auto_pin_classified":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Pin Classified"},"dynamic_client_networks":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Dynamic Client Networks"},"dynamic_client_lifetime":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Dynamic Client Lifetime"},"mfa_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Enabled"},"default_auth_method":{"anyOf":[{"type":"string","pattern":"^(peap|eap_tls|mab)$"},{"type":"null"}],"title":"Default Auth Method"},"mab_format":{"anyOf":[{"type":"string","pattern":"^(lower_hyphen|upper_colon|lower_colon|cisco_dot)$"},{"type":"null"}],"title":"Mab Format"},"bruteforce_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bruteforce Enabled"},"bruteforce_threshold":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Threshold"},"bruteforce_window_minutes":{"anyOf":[{"type":"integer","maximum":1440.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Window Minutes"},"crl_check_enable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Crl Check Enable"},"crl_fetch_interval_hours":{"anyOf":[{"type":"integer","maximum":600.0,"minimum":1.0},{"type":"null"}],"title":"Crl Fetch Interval Hours"},"log_retention_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Log Retention Days"},"log_auth":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Log Auth"},"session_cleanup_interval_hours":{"anyOf":[{"type":"integer","maximum":168.0,"minimum":1.0},{"type":"null"}],"title":"Session Cleanup Interval Hours"},"session_max_duration_hours":{"anyOf":[{"type":"integer","maximum":720.0,"minimum":0.0},{"type":"null"}],"title":"Session Max Duration Hours"}},"type":"object","title":"NacSettingsUpdate","description":"Partial update for NAC settings.\n\nOnly the fields present in the request body will be updated.\nOmitted fields remain unchanged in the database.\nPort fields (auth_port, acct_port) are not accepted — read-only from env.\n\nDocument-style flat-settings PATCH — deliberately NO extra=\"forbid\" (same as\nthe other *SettingsUpdate documents): the GET document surfaces read-only ENV\nkeys (auth_port / acct_port) that a client may echo back on save, and a stray\nread-only key must never 422 a settings save. Bounds / enum patterns apply\nregardless."},"NacStatusResponse":{"properties":{"service":{"$ref":"#/components/schemas/NacServiceConnectivity"},"config":{"$ref":"#/components/schemas/NacConfigStatusInfo"}},"type":"object","required":["service","config"],"title":"NacStatusResponse","description":"Response for GET /nac/status."},"NacSummaryResponse":{"properties":{"active_sessions_total":{"type":"integer","title":"Active Sessions Total","default":0},"active_by_auth_method":{"additionalProperties":{"type":"integer"},"type":"object","title":"Active By Auth Method","description":"Active sessions grouped by detected method (dot1x / mab / other)"},"endpoints_total":{"type":"integer","title":"Endpoints Total","default":0},"endpoints_by_status":{"additionalProperties":{"type":"integer"},"type":"object","title":"Endpoints By Status","description":"Endpoint counts keyed by status (known / unknown / blocked / inactive)"},"top_vlans":{"items":{"$ref":"#/components/schemas/NacTopVlan"},"type":"array","title":"Top Vlans","description":"Up to 5 VLANs with the most active sessions"}},"type":"object","title":"NacSummaryResponse","description":"Live NAC counters for the nac-sessions / nac-endpoints widgets.\n\nNot cached — these are live operational counts (active sessions move\nfast), and they are single indexed ``count`` / ``GROUP BY`` queries."},"NacTopVlan":{"properties":{"vlan_id":{"type":"integer","title":"Vlan Id"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["vlan_id","count"],"title":"NacTopVlan","description":"A VLAN with its active-session count (top-N list entry)."},"NacTrustedCaCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"ca_cert_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Ca Cert Pem","description":"PEM-encoded CA certificate"},"identity_source":{"type":"string","pattern":"^(cert_cn|cert_san_upn|cert_san_email|cert_subject)$","title":"Identity Source","default":"cert_cn"},"cert_type":{"type":"string","pattern":"^(user|computer|both)$","title":"Cert Type","default":"both"},"enabled":{"type":"boolean","title":"Enabled","default":true},"check_crl":{"type":"boolean","title":"Check Crl","default":false},"crl_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Crl Url"},"crl_pem":{"anyOf":[{"type":"string","maxLength":65536},{"type":"null"}],"title":"Crl Pem","description":"CRL in PEM or DER (base64) format"},"ocsp_enabled":{"type":"boolean","title":"Ocsp Enabled","default":false},"ocsp_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Ocsp Url"}},"additionalProperties":false,"type":"object","required":["name","ca_cert_pem"],"title":"NacTrustedCaCreate","description":"Create a new trusted CA entry.\n\nThe ``ca_cert_pem`` field accepts a PEM-encoded CA certificate.\nIssuer DN, subject DN, validity dates, and serial number are\nparsed automatically from the PEM content on the backend.\n\nextra=\"forbid\": admin-only (TrustedCaForm submits an explicit object with\nexactly these keys). PEM blobs LENGTH-bounded only, NOT stripped."},"NacTrustedCaCrlInfo":{"properties":{"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"last_update":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Update"},"next_update":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Update"},"revoked_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Revoked Count"}},"type":"object","title":"NacTrustedCaCrlInfo","description":"Parsed CRL metadata for display."},"NacTrustedCaResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"identity_source":{"type":"string","title":"Identity Source"},"cert_type":{"type":"string","title":"Cert Type"},"enabled":{"type":"boolean","title":"Enabled"},"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"subject_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Dn"},"not_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not Before"},"not_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not After"},"serial_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial Number"},"check_crl":{"type":"boolean","title":"Check Crl","default":false},"crl_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crl Url"},"crl_pem_loaded":{"type":"boolean","title":"Crl Pem Loaded","default":false},"crl_info":{"anyOf":[{"$ref":"#/components/schemas/NacTrustedCaCrlInfo"},{"type":"null"}]},"crl_last_fetched_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Crl Last Fetched At"},"crl_next_update":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Crl Next Update"},"crl_fetch_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Crl Fetch Error"},"ocsp_enabled":{"type":"boolean","title":"Ocsp Enabled","default":false},"ocsp_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ocsp Url"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","identity_source","cert_type","enabled","created_at","updated_at"],"title":"NacTrustedCaResponse","description":"Response schema for a trusted CA entry.\n\nPEM content is NOT returned — only metadata."},"NacTrustedCaUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"identity_source":{"anyOf":[{"type":"string","pattern":"^(cert_cn|cert_san_upn|cert_san_email|cert_subject)$"},{"type":"null"}],"title":"Identity Source"},"cert_type":{"anyOf":[{"type":"string","pattern":"^(user|computer|both)$"},{"type":"null"}],"title":"Cert Type"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"check_crl":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Check Crl"},"crl_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Crl Url"},"crl_pem":{"anyOf":[{"type":"string","maxLength":65536},{"type":"null"}],"title":"Crl Pem","description":"CRL in PEM or DER (base64) format"},"ocsp_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ocsp Enabled"},"ocsp_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Ocsp Url"}},"additionalProperties":false,"type":"object","title":"NacTrustedCaUpdate","description":"Partial update for a trusted CA entry.\n\nPEM certificate cannot be changed — delete and re-create instead.\nOnly metadata and behavioral settings are mutable.\n\nextra=\"forbid\": admin-only (TrustedCaForm submits an explicit object with\nexactly these keys)."},"NacVendorDictionaryCreate":{"properties":{"key":{"type":"string","maxLength":100,"minLength":1,"pattern":"^[a-z0-9_]+$","title":"Key"},"display_name":{"type":"string","maxLength":255,"minLength":1,"title":"Display Name"},"vendor_id":{"type":"integer","minimum":0.0,"title":"Vendor Id","default":0},"coa_port":{"type":"integer","maximum":65535.0,"minimum":1.0,"title":"Coa Port","default":3799},"capabilities":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Capabilities"},"detect_hints":{"$ref":"#/components/schemas/VendorDetectHintsSchema"},"mappings":{"additionalProperties":{"items":{"$ref":"#/components/schemas/VendorAttributeMappingSchema"},"type":"array"},"type":"object","title":"Mappings"},"coa_actions":{"additionalProperties":{"$ref":"#/components/schemas/VendorCoaActionSchema"},"type":"object","title":"Coa Actions"}},"additionalProperties":false,"type":"object","required":["key","display_name"],"title":"NacVendorDictionaryCreate","description":"Schema for creating a new vendor dictionary entry."},"NacVendorDictionaryListResponse":{"properties":{"vendors":{"items":{"$ref":"#/components/schemas/NacVendorDictionaryResponse"},"type":"array","title":"Vendors"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["vendors","total"],"title":"NacVendorDictionaryListResponse","description":"List of all vendor dictionary entries."},"NacVendorDictionaryResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","title":"Key"},"display_name":{"type":"string","title":"Display Name"},"vendor_id":{"type":"integer","title":"Vendor Id"},"coa_port":{"type":"integer","title":"Coa Port"},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities"},"detect_hints":{"$ref":"#/components/schemas/VendorDetectHintsSchema"},"mappings":{"additionalProperties":{"items":{"$ref":"#/components/schemas/VendorAttributeMappingSchema"},"type":"array"},"type":"object","title":"Mappings"},"coa_actions":{"additionalProperties":{"$ref":"#/components/schemas/VendorCoaActionSchema"},"type":"object","title":"Coa Actions"},"is_builtin":{"type":"boolean","title":"Is Builtin"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","key","display_name","vendor_id","coa_port","capabilities","detect_hints","mappings","is_builtin","created_at","updated_at"],"title":"NacVendorDictionaryResponse","description":"Full vendor dictionary entry response."},"NacVendorDictionaryUpdate":{"properties":{"display_name":{"type":"string","maxLength":255,"minLength":1,"title":"Display Name"},"vendor_id":{"type":"integer","minimum":0.0,"title":"Vendor Id","default":0},"coa_port":{"type":"integer","maximum":65535.0,"minimum":1.0,"title":"Coa Port","default":3799},"capabilities":{"items":{"type":"string"},"type":"array","maxItems":5,"title":"Capabilities"},"detect_hints":{"$ref":"#/components/schemas/VendorDetectHintsSchema"},"mappings":{"additionalProperties":{"items":{"$ref":"#/components/schemas/VendorAttributeMappingSchema"},"type":"array"},"type":"object","title":"Mappings"},"coa_actions":{"additionalProperties":{"$ref":"#/components/schemas/VendorCoaActionSchema"},"type":"object","title":"Coa Actions"}},"additionalProperties":false,"type":"object","required":["display_name"],"title":"NacVendorDictionaryUpdate","description":"Schema for updating a vendor dictionary entry (full replace)."},"NcmIngestPayload":{"properties":{"status":{"type":"string","enum":["ok","failed"],"title":"Status","description":"ok → a snapshot; failed → a recorded failure."},"content_kind":{"type":"string","title":"Content Kind","description":"text|binary — text is re-scrubbed on core; binary is hash-only.","default":"text"},"content_hash":{"type":"string","title":"Content Hash","description":"Collector's sha256 (text: re-verified on core; binary: accepted).","default":""},"scrubbed_body":{"type":"string","title":"Scrubbed Body","description":"Collector-scrubbed text body — RE-SCRUBBED on core.","default":""},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes","description":"Byte size (binary: required; text: derived if absent)."},"captured_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Captured At","description":"Collector capture time — clamped if beyond +skew."},"failure_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Class","description":"auth|transient|partial — only on status='failed'."},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Already-scrubbed failure diagnostic — only on status='failed'."},"trace_steps":{"items":{"$ref":"#/components/schemas/PreviewTraceStep"},"type":"array","title":"Trace Steps","description":"Secret-safe step trace — on-demand traced collect only (else empty)."},"failure_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Stage","description":"Trace stage that failed — on-demand failed collect only."}},"additionalProperties":false,"type":"object","required":["status"],"title":"NcmIngestPayload","description":"The ``ncm_config`` capability's ingest body — the collector-authored result data.\n\nNested under :class:`IngestPayload.payload`. ``status=\"ok\"`` carries the (locally-scrubbed)\nsnapshot fields; ``status=\"failed\"`` carries ``failure_class`` + a scrubbed ``error`` and no\nbody. The core re-scrubs / re-hashes / clamps every field regardless — it is untrusted input.\n\n``trace_steps`` (+ ``failure_stage``) are populated ONLY for an on-demand traced collect\n(collect-now): the same secret-safe step trace a preview emits, so the core persists a trace\non the result and the UI renders it exactly like a preview. Empty for a scheduled sweep collect\n(not traced) and for a pre-trace collector — additive + backward-compatible."},"NcmJobPayload":{"properties":{"source":{"$ref":"#/components/schemas/JobSourceSpec"},"recipe":{"$ref":"#/components/schemas/JobRecipeSpec"},"scrub_rules":{"items":{"$ref":"#/components/schemas/JobScrubRuleSpec"},"type":"array","title":"Scrub Rules"},"credential_plaintext":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Credential Plaintext","description":"Decrypted login credential (JIT-resolved at claim); response-only, never persisted."},"netmiko_device_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Netmiko Device Type","description":"Convenience mirror of recipe.netmiko_device_type."},"timeout_s":{"type":"number","title":"Timeout S","description":"Per-collect transport timeout (seconds).","default":30.0}},"additionalProperties":false,"type":"object","required":["source","recipe"],"title":"NcmJobPayload","description":"The ``ncm_config`` capability's job body — the serialisable collect inputs.\n\nNested under :class:`JobPayload.payload`, this is the capability-specific half of the\ngeneric ``{capability, trigger, ingest_key, version, payload}`` envelope. The collector\nreconstructs ``collect_one`` inputs from ``source`` / ``recipe`` / ``scrub_rules`` /\n``credential_plaintext`` — the generic transport never reads these fields."},"NcmPreviewResultPayload":{"properties":{"status":{"type":"string","enum":["ok","failed"],"title":"Status","description":"ok → a would-be config; failed → a device failure."},"steps":{"items":{"$ref":"#/components/schemas/PreviewTraceStep"},"type":"array","title":"Steps","description":"The ordered, secret-safe traced steps."},"scrubbed_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scrubbed Result","description":"Collector-scrubbed text body — RE-SCRUBBED on core."},"content_kind":{"type":"string","title":"Content Kind","description":"text|binary — text is re-scrubbed on core; binary is hash-only.","default":"text"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash","description":"Collector's sha256 (text: recomputed on core; binary: kept)."},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes","description":"Byte size of the would-be capture (binary/text)."},"failure_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Stage","description":"The trace stage that failed — only on status='failed'."},"failure_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Class","description":"auth|transient|partial — only on status='failed'."},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Already-scrubbed device diagnostic — only on status='failed'."}},"additionalProperties":false,"type":"object","required":["status"],"title":"NcmPreviewResultPayload","description":"The ``ncm_config`` capability's preview body — the traced dry-run result data.\n\nNested under :class:`PreviewJobResultPayload.payload`. ``status='ok'`` carries the\n(locally-scrubbed) would-be config + trace; ``status='failed'`` is a DEVICE failure carried\nas a failure-classed trace (NOT a collector-level error). The core re-scrubs\n``scrubbed_result`` and recomputes ``content_hash``; binary is hash-only (no body to\nre-scrub, hash accepted verbatim — same as binary ingest, spec §10)."},"NetmikoPlatform":{"properties":{"value":{"type":"string","title":"Value","description":"Netmiko device_type identifier stored on the recipe"},"label":{"type":"string","title":"Label","description":"Friendly platform name"},"vendor":{"type":"string","title":"Vendor","description":"Vendor grouping"}},"type":"object","required":["value","label","vendor"],"title":"NetmikoPlatform","description":"One netmiko platform for the recipe form's driver picker.\n\n``value`` is the netmiko ``device_type`` stored on the recipe; ``label`` is a friendly\nname and ``vendor`` groups the picker. Sourced from the live\n``netmiko.ssh_dispatcher.CLASS_MAPPER`` registry (never a hardcoded subset)."},"NetworkMetrics":{"properties":{"bytes_sent":{"type":"integer","title":"Bytes Sent"},"bytes_recv":{"type":"integer","title":"Bytes Recv"},"packets_sent":{"type":"integer","title":"Packets Sent"},"packets_recv":{"type":"integer","title":"Packets Recv"},"errors_in":{"type":"integer","title":"Errors In"},"errors_out":{"type":"integer","title":"Errors Out"},"drops_in":{"type":"integer","title":"Drops In"},"drops_out":{"type":"integer","title":"Drops Out"},"bytes_sent_human":{"type":"string","title":"Bytes Sent Human"},"bytes_recv_human":{"type":"string","title":"Bytes Recv Human"}},"type":"object","required":["bytes_sent","bytes_recv","packets_sent","packets_recv","errors_in","errors_out","drops_in","drops_out","bytes_sent_human","bytes_recv_human"],"title":"NetworkMetrics","description":"Network I/O counters."},"NetworkObjectBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"entry_type":{"type":"string","title":"Entry Type"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start"},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End"}},"type":"object","required":["id","name","entry_type"],"title":"NetworkObjectBrief","description":"Inline network object info embedded in device responses."},"NetworkObjectContainsRequest":{"properties":{"ip_address":{"type":"string","title":"Ip Address","description":"IPv4 or IPv6 address to check"}},"additionalProperties":false,"type":"object","required":["ip_address"],"title":"NetworkObjectContainsRequest","description":"Request schema for checking if an IP is contained in any network object."},"NetworkObjectCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique name for the network object"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description","description":"Optional description"},"entry_type":{"type":"string","enum":["host","subnet","range","fqdn"],"title":"Entry Type","description":"Type: 'host' (single IP), 'subnet' (CIDR), 'range' (IP range), or 'fqdn' (hostname)"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network","description":"IP address (host) or CIDR notation (subnet). Required for host/subnet."},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start","description":"Start of IP range (inclusive). Required for range."},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End","description":"End of IP range (inclusive). Required for range."},"fqdn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fqdn","description":"Fully-qualified domain name. Required for entry_type 'fqdn'."},"tags":{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":64,"title":"Tags","description":"Free-form tags"}},"additionalProperties":false,"type":"object","required":["name","entry_type"],"title":"NetworkObjectCreate","description":"Schema for creating a new network object."},"NetworkObjectListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"entry_type":{"type":"string","title":"Entry Type"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start"},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End"},"fqdn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fqdn"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","entry_type","created_at"],"title":"NetworkObjectListResponse","description":"Abbreviated network object for list views."},"NetworkObjectResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"entry_type":{"type":"string","title":"Entry Type"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start"},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End"},"fqdn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fqdn"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","entry_type","created_at","updated_at"],"title":"NetworkObjectResponse","description":"Full network object response for detail views."},"NetworkObjectSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"entry_type":{"type":"string","title":"Entry Type"},"value":{"type":"string","title":"Value","description":"Display value: host IP / subnet CIDR / range / fqdn."}},"type":"object","required":["id","name","entry_type","value"],"title":"NetworkObjectSummary","description":"Lightweight read-only network-object projection embedded by consumers.\n\nA consumer (e.g. an NCM source) that references a network object embeds this so the\nUI gets an instant, always-fresh preview without a second fetch. ``value`` is the\ndisplay form: the bare IP for a ``host``, the CIDR for a ``subnet``, ``start-end``\nfor a ``range``, and the hostname for an ``fqdn``."},"NetworkObjectUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start"},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End"},"fqdn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fqdn"},"tags":{"anyOf":[{"items":{"type":"string","maxLength":64,"minLength":1},"type":"array","maxItems":64},{"type":"null"}],"title":"Tags"}},"additionalProperties":false,"type":"object","title":"NetworkObjectUpdate","description":"Schema for updating a network object.\n\nAll fields optional — only provided fields are changed.\nentry_type is immutable after creation and not accepted here.\nService layer validates field compatibility with the existing entry_type."},"NetworkRefItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"entry_type":{"type":"string","title":"Entry Type"},"network":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network"},"range_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range Start"},"range_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Range End"}},"type":"object","required":["id","name","entry_type"],"title":"NetworkRefItem","description":"Network-object reference enriched with its entry type and address.\n\nLets the UI render the correct type badge (host/subnet/range) and address\nfor a rule's source networks without a second lookup."},"NodeMembershipResponse":{"properties":{"node_name":{"type":"string","title":"Node Name"},"state":{"type":"string","title":"State","description":"joined | not_joined | joining | failed | unknown"},"joined":{"type":"boolean","title":"Joined"},"domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain"},"machine_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Machine Name"},"detail":{"type":"string","title":"Detail","default":""},"winbindd_running":{"type":"boolean","title":"Winbindd Running","default":false},"has_machine_secret":{"type":"boolean","title":"Has Machine Secret","description":"A machine-account password exists on this node. With joined=False it is the difference between a BROKEN trust and a node that simply never joined.","default":false},"last_join":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Last Join","description":"Outcome of the last join this node performed — a DIFFERENT fact from membership. A refused re-join leaves the node a member while the join failed; both are true."},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"},"stale":{"type":"boolean","title":"Stale","description":"The sidecar stopped publishing — this describes the past, not the present.","default":false},"last_error":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Last Error"}},"type":"object","required":["node_name","state","joined"],"title":"NodeMembershipResponse","description":"One node's view of its own domain membership."},"NodeServiceHealthResponse":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id"},"name":{"type":"string","title":"Name"},"is_self":{"type":"boolean","title":"Is Self","description":"True for the node serving this request."},"node_reachable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Node Reachable","description":"Patroni's verdict for this node (healthy leader / streaming replica); null if topology unknown."},"services":{"items":{"$ref":"#/components/schemas/ServiceHealthCellResponse"},"type":"array","title":"Services"}},"type":"object","required":["node_id","name","is_self","services"],"title":"NodeServiceHealthResponse","description":"A roster node with its per-service health cells."},"OnboardingImportRequest":{"properties":{"transport_type":{"$ref":"#/components/schemas/TransportType","description":"Transport for every source (fixes settings shape)"},"transport_settings":{"additionalProperties":true,"type":"object","title":"Transport Settings","description":"Per-transport settings (shared)"},"port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Port","description":"Optional port; null → transport registry default"},"credential_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Credential Id","description":"One shared credential fanned out to every source"},"recipe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id","description":"Extraction recipe for every tracked config"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id","description":"Collector every onboarded source binds to; null → the default embedded collector"},"addresses":{"items":{"type":"string","maxLength":255,"minLength":1},"type":"array","maxItems":25,"minItems":1,"title":"Addresses"},"stop_on_first_error":{"type":"boolean","title":"Stop On First Error","description":"Halt the run on the first hard error (small runs); default is continue-on-error","default":false}},"additionalProperties":false,"type":"object","required":["transport_type","addresses"],"title":"OnboardingImportRequest","description":"Import an address pool into ready tracked configs (bounded, synchronous)."},"OnboardingImportResponse":{"properties":{"total":{"type":"integer","title":"Total","default":0},"created":{"type":"integer","title":"Created","default":0},"skipped":{"type":"integer","title":"Skipped","default":0},"unreachable":{"type":"integer","title":"Unreachable","default":0},"auth_fail":{"type":"integer","title":"Auth Fail","default":0},"errors":{"type":"integer","title":"Errors","default":0},"items":{"items":{"$ref":"#/components/schemas/OnboardingItemResult"},"type":"array","title":"Items"}},"type":"object","title":"OnboardingImportResponse","description":"Counter summary + per-item results for an import run."},"OnboardingItemResult":{"properties":{"address":{"type":"string","title":"Address"},"status":{"type":"string","enum":["created","skipped","unreachable","auth_fail","error"],"title":"Status"},"tracked_config_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tracked Config Id","description":"Created config (created only)"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Resolved config name (host-Device name if matched, else address)"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message","description":"Info/error detail (i18n)"}},"type":"object","required":["address","status"],"title":"OnboardingItemResult","description":"Per-address outcome."},"OnboardingSampleItemResult":{"properties":{"address":{"type":"string","title":"Address"},"status":{"type":"string","enum":["ok","auth_fail","unreachable","error"],"title":"Status"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Host-Device name if matched (the would-be auto-name)"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["address","status"],"title":"OnboardingSampleItemResult","description":"Per-address sample-probe outcome (no create)."},"OnboardingSampleRequest":{"properties":{"transport_type":{"$ref":"#/components/schemas/TransportType","description":"Transport for every source (fixes settings shape)"},"transport_settings":{"additionalProperties":true,"type":"object","title":"Transport Settings","description":"Per-transport settings (shared)"},"port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Port","description":"Optional port; null → transport registry default"},"credential_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Credential Id","description":"One shared credential fanned out to every source"},"recipe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id","description":"Extraction recipe for every tracked config"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id","description":"Collector every onboarded source binds to; null → the default embedded collector"},"addresses":{"items":{"type":"string","maxLength":255,"minLength":1},"type":"array","maxItems":10,"minItems":1,"title":"Addresses"}},"additionalProperties":false,"type":"object","required":["transport_type","addresses"],"title":"OnboardingSampleRequest","description":"Probe a small sample (no create) to validate the shared credential/recipe."},"OnboardingSampleResponse":{"properties":{"total":{"type":"integer","title":"Total","default":0},"ok":{"type":"integer","title":"Ok","default":0},"failed":{"type":"integer","title":"Failed","default":0},"items":{"items":{"$ref":"#/components/schemas/OnboardingSampleItemResult"},"type":"array","title":"Items"}},"type":"object","title":"OnboardingSampleResponse","description":"Sample-probe summary — validate the shared credential/recipe before the full import."},"OuiLookupResponse":{"properties":{"mac_address":{"type":"string","title":"Mac Address","description":"Queried MAC address (normalized)"},"oui_prefix":{"type":"string","title":"Oui Prefix","description":"Extracted OUI prefix XX:XX:XX"},"vendor_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Name","description":"Manufacturer name (null if not found)"},"vendor_short":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Short","description":"Short display name"},"found":{"type":"boolean","title":"Found","description":"Whether a vendor was found for this prefix"}},"type":"object","required":["mac_address","oui_prefix","found"],"title":"OuiLookupResponse","description":"Response for single MAC → vendor lookup."},"OuiMatchPreviewResponse":{"properties":{"items":{"items":{"anyOf":[{"$ref":"#/components/schemas/OuiVendorMatchItem"},{"$ref":"#/components/schemas/OuiPrefixMatchItem"}]},"type":"array","title":"Items","description":"Matching rows (shape depends on match_type)"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total records in OUI database (no filter)"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total matching search (or total if no search)"},"page":{"type":"integer","minimum":1.0,"title":"Page"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total page count"},"match_type":{"type":"string","enum":["vendor_name","oui_prefix"],"title":"Match Type","description":"Echo of the requested match_type"},"query_type":{"type":"string","enum":["prefix","name","none"],"title":"Query Type","description":"Auto-detected query interpretation (only meaningful for oui_prefix)","default":"none"}},"type":"object","required":["total","total_by_filter","page","per_page","pages","match_type"],"title":"OuiMatchPreviewResponse","description":"Paginated match-preview response for classification rule UI.\n\nExtends the standard pagination shape (items/total/page/per_page/pages/total_by_filter)\nwith:\n  - match_type: echoes the requested filter mode\n  - query_type: for oui_prefix, how the search was interpreted\n    ('prefix' = hex search, 'name' = vendor text search, 'none' = no search).\n    For vendor_name always 'none' or absent."},"OuiPrefixMatchItem":{"properties":{"oui_prefix":{"type":"string","title":"Oui Prefix","description":"OUI prefix XX:XX:XX (stored in match_value)"},"vendor_name":{"type":"string","title":"Vendor Name","description":"Full IEEE organization name"},"vendor_short":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Short","description":"Short display name"}},"type":"object","required":["oui_prefix","vendor_name"],"title":"OuiPrefixMatchItem","description":"Single OUI prefix row with vendor info.\n\nUsed for match_type='oui_prefix' classification rules.\nOne row per OUI record."},"OuiSearchResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/OuiSearchResult"},"type":"array","title":"Items"},"total":{"type":"integer","title":"Total","description":"Total matching records"},"query":{"type":"string","title":"Query","description":"Original search query"}},"type":"object","required":["items","total","query"],"title":"OuiSearchResponse","description":"Response for vendor name search (paginated list view — legacy)."},"OuiSearchResult":{"properties":{"oui_prefix":{"type":"string","title":"Oui Prefix"},"vendor_name":{"type":"string","title":"Vendor Name"},"vendor_short":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Short"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["oui_prefix","vendor_name","updated_at"],"title":"OuiSearchResult","description":"Single OUI record in search results."},"OuiStatsResponse":{"properties":{"total_vendors":{"type":"integer","title":"Total Vendors","description":"Total OUI records in database"},"last_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Updated At","description":"When the DB was last updated from IEEE"},"auto_update_enabled":{"type":"boolean","title":"Auto Update Enabled","description":"Whether weekly auto-update is enabled"}},"type":"object","required":["total_vendors","auto_update_enabled"],"title":"OuiStatsResponse","description":"OUI database statistics."},"OuiUpdateResponse":{"properties":{"created":{"type":"integer","title":"Created","description":"New vendors added"},"updated":{"type":"integer","title":"Updated","description":"Existing vendors updated"},"total":{"type":"integer","title":"Total","description":"Total vendors after update"},"duration_seconds":{"type":"number","title":"Duration Seconds","description":"Update duration"}},"type":"object","required":["created","updated","total","duration_seconds"],"title":"OuiUpdateResponse","description":"Response for manual OUI database update."},"OuiVendorMatchItem":{"properties":{"vendor_name":{"type":"string","title":"Vendor Name","description":"Full IEEE organization name (stored in match_value)"},"vendor_short":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor Short","description":"Short display name"},"prefix_count":{"type":"integer","title":"Prefix Count","description":"How many OUI prefixes belong to this vendor"},"sample_prefixes":{"items":{"type":"string"},"type":"array","title":"Sample Prefixes","description":"Up to 3 sample prefixes for UI preview (sorted)"}},"type":"object","required":["vendor_name","prefix_count"],"title":"OuiVendorMatchItem","description":"Single vendor row (grouped from multiple OUI prefixes).\n\nUsed for match_type='vendor_name' classification rules.\nOne row per unique vendor_name."},"OverviewResponse":{"properties":{"summary":{"$ref":"#/components/schemas/OverviewSummary"},"recent_changes":{"items":{"$ref":"#/components/schemas/RecentChangeItem"},"type":"array","title":"Recent Changes"}},"type":"object","required":["summary"],"title":"OverviewResponse","description":"The NCM module front door: health tiles + the most-recent config-change feed."},"OverviewSummary":{"properties":{"tracked_configs_total":{"type":"integer","title":"Tracked Configs Total","description":"Total tracked configurations"},"tracked_configs_enabled":{"type":"integer","title":"Tracked Configs Enabled","description":"Tracked configurations with collection enabled"},"changed_24h":{"type":"integer","title":"Changed 24H","description":"Snapshots captured in the last 24 hours (across all configs)"},"collectors_online":{"type":"integer","title":"Collectors Online","description":"Collectors whose last heartbeat was healthy"},"collectors_offline":{"type":"integer","title":"Collectors Offline","description":"Collectors whose last heartbeat is stale"},"collectors_unknown":{"type":"integer","title":"Collectors Unknown","description":"Collectors that have never reported a heartbeat"},"drift_count":{"type":"integer","title":"Drift Count","description":"Tracked configs with a baseline set whose LATEST snapshot content_hash differs from the baseline"},"problematic_count":{"type":"integer","title":"Problematic Count","description":"Enabled configs whose derived status is failing or collector_offline (the 'needs attention' set)"}},"type":"object","required":["tracked_configs_total","tracked_configs_enabled","changed_24h","collectors_online","collectors_offline","collectors_unknown","drift_count","problematic_count"],"title":"OverviewSummary","description":"Health tiles for the NCM front-door dashboard — bounded aggregate counters."},"PaginatedResponse_AuditLogResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AuditLogResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[AuditLogResponse]"},"PaginatedResponse_CaptivePortalConfigListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaptivePortalConfigListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CaptivePortalConfigListResponse]"},"PaginatedResponse_CollectionRecipeListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CollectionRecipeListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CollectionRecipeListResponse]"},"PaginatedResponse_CollectionRunResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CollectionRunResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CollectionRunResponse]"},"PaginatedResponse_CollectionSourceListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CollectionSourceListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CollectionSourceListResponse]"},"PaginatedResponse_CollectorListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CollectorListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CollectorListResponse]"},"PaginatedResponse_CommandSetListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CommandSetListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CommandSetListResponse]"},"PaginatedResponse_CredentialBindingResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CredentialBindingResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CredentialBindingResponse]"},"PaginatedResponse_CredentialListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CredentialListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CredentialListResponse]"},"PaginatedResponse_CredentialProviderListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CredentialProviderListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[CredentialProviderListResponse]"},"PaginatedResponse_DatasetResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DatasetResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[DatasetResponse]"},"PaginatedResponse_DeviceGroupListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DeviceGroupListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[DeviceGroupListResponse]"},"PaginatedResponse_DeviceListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/DeviceListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[DeviceListResponse]"},"PaginatedResponse_EndpointGroupListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/EndpointGroupListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[EndpointGroupListResponse]"},"PaginatedResponse_EndpointListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/EndpointListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[EndpointListResponse]"},"PaginatedResponse_GroupListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/GroupListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[GroupListResponse]"},"PaginatedResponse_GuestSessionResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/GuestSessionResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[GuestSessionResponse]"},"PaginatedResponse_LogExclusionListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/LogExclusionListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[LogExclusionListResponse]"},"PaginatedResponse_NacAuthLogListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/NacAuthLogListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[NacAuthLogListResponse]"},"PaginatedResponse_NacAuthorizationProfileResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/NacAuthorizationProfileResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[NacAuthorizationProfileResponse]"},"PaginatedResponse_NacSessionListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/NacSessionListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[NacSessionListResponse]"},"PaginatedResponse_NetworkObjectListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/NetworkObjectListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[NetworkObjectListResponse]"},"PaginatedResponse_PendingComputerListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/PendingComputerListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[PendingComputerListResponse]"},"PaginatedResponse_RBACModelListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RBACModelListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[RBACModelListResponse]"},"PaginatedResponse_RadiusAcctLogListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RadiusAcctLogListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[RadiusAcctLogListResponse]"},"PaginatedResponse_RadiusAuthLogListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RadiusAuthLogListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[RadiusAuthLogListResponse]"},"PaginatedResponse_RadiusProfileListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RadiusProfileListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[RadiusProfileListResponse]"},"PaginatedResponse_RadiusTemplateListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RadiusTemplateListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[RadiusTemplateListResponse]"},"PaginatedResponse_ReportResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ReportResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[ReportResponse]"},"PaginatedResponse_ReportScheduleResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ReportScheduleResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[ReportScheduleResponse]"},"PaginatedResponse_ScrubRuleSetListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ScrubRuleSetListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[ScrubRuleSetListResponse]"},"PaginatedResponse_SnapshotListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SnapshotListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[SnapshotListResponse]"},"PaginatedResponse_SyncLogResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SyncLogResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[SyncLogResponse]"},"PaginatedResponse_SyslogDestinationListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/SyslogDestinationListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[SyslogDestinationListResponse]"},"PaginatedResponse_TacacsAcctLogListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TacacsAcctLogListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TacacsAcctLogListResponse]"},"PaginatedResponse_TacacsAuthnLogListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TacacsAuthnLogListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TacacsAuthnLogListResponse]"},"PaginatedResponse_TacacsAuthzLogListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TacacsAuthzLogListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TacacsAuthzLogListResponse]"},"PaginatedResponse_TacacsProfileListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TacacsProfileListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TacacsProfileListResponse]"},"PaginatedResponse_TacacsTemplateListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TacacsTemplateListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TacacsTemplateListResponse]"},"PaginatedResponse_TimeRangeListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TimeRangeListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TimeRangeListResponse]"},"PaginatedResponse_TrackedConfigListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/TrackedConfigListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[TrackedConfigListResponse]"},"PaginatedResponse_UserListResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/UserListResponse"},"type":"array","title":"Items","description":"List of items for the current page"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total number of matching records"},"page":{"type":"integer","minimum":1.0,"title":"Page","description":"Current page number (1-based)"},"per_page":{"type":"integer","minimum":1.0,"title":"Per Page","description":"Number of items per page"},"pages":{"type":"integer","minimum":0.0,"title":"Pages","description":"Total number of pages"},"total_by_filter":{"type":"integer","minimum":0.0,"title":"Total By Filter","description":"Total number of records after filtering"}},"type":"object","required":["total","page","per_page","pages","total_by_filter"],"title":"PaginatedResponse[UserListResponse]"},"PendingComputerListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"os":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os"},"os_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os Version"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"ldap_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Dn"},"ldap_config_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Config Id"},"synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Synced At"},"matched_endpoint_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Matched Endpoint Id"},"matched_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Matched At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","created_at"],"title":"PendingComputerListResponse","description":"Pending AD computer for list views."},"PeriodCapabilitySummary":{"properties":{"start_bind":{"type":"string","title":"Start Bind"},"end_bind":{"type":"string","title":"End Bind"},"windows":{"items":{"$ref":"#/components/schemas/WindowOption"},"type":"array","title":"Windows"},"default":{"$ref":"#/components/schemas/RelativeWindow-Output"},"custom_max_days":{"type":"integer","title":"Custom Max Days"}},"type":"object","required":["start_bind","end_bind","windows","default","custom_max_days"],"title":"PeriodCapabilitySummary","description":"Period control a dataset over this template may set (§5.1)."},"PeriodOverride":{"properties":{"start":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start"},"end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End"}},"additionalProperties":false,"type":"object","title":"PeriodOverride","description":"An absolute date range for a one-off export (§5.2).\n\nExport takes an explicit range rather than the dataset's stored *relative*\nwindow (never persisted). Both bounds are **optional**: an empty ``start`` means\n\"since the beginning\", an empty ``end`` means \"up to now\", both empty means all\ntime. The bounds are wall-clock in the **system timezone** (the zone the\noperator sees): the export endpoint anchors a naive bound to that zone before\nconverting to the UTC window the engine resolves. ``start < end`` is enforced\ndownstream by ``resolve_period``. The relative-window ``custom_max_days`` cap\ndoes **not** apply — an absolute range is one-off and human-chosen, bounded by\nthe reports statement-timeout + export row ceiling, not a rolling-window guard."},"PermissionActionSchema":{"properties":{"key":{"type":"string","title":"Key","description":"Action identifier, e.g. 'view', 'create'"},"label":{"type":"string","title":"Label","description":"Human-readable label"},"description":{"type":"string","title":"Description","description":"What this action allows"},"default":{"type":"boolean","title":"Default","description":"Default value when creating a new RBAC model","default":false}},"type":"object","required":["key","label","description"],"title":"PermissionActionSchema","description":"A single permission action within a section."},"PermissionSchemaResponse":{"properties":{"sections":{"items":{"$ref":"#/components/schemas/PermissionSectionSchema"},"type":"array","title":"Sections","description":"All permission sections"},"categories":{"items":{"type":"string"},"type":"array","title":"Categories","description":"All available category names, sorted"}},"type":"object","required":["sections","categories"],"title":"PermissionSchemaResponse","description":"Response for GET /rbac/schema — full permission schema."},"PermissionSectionSchema":{"properties":{"key":{"type":"string","title":"Key","description":"Section identifier, e.g. 'users', 'devices'"},"label":{"type":"string","title":"Label","description":"Human-readable section label"},"description":{"type":"string","title":"Description","description":"What this section covers"},"category":{"type":"string","title":"Category","description":"Grouping category: identity, security, system, network, aaa"},"actions":{"items":{"$ref":"#/components/schemas/PermissionActionSchema"},"type":"array","title":"Actions","description":"Available actions in this section"}},"type":"object","required":["key","label","description","category","actions"],"title":"PermissionSectionSchema","description":"A permission section with its available actions."},"PolicyTestAction":{"properties":{"mode":{"type":"string","title":"Mode","description":"none | deny | auth_only | profile"},"profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Profile Id"},"profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Name"},"mfa":{"type":"string","title":"Mfa","description":"off | required"},"mfa_enforced":{"type":"boolean","title":"Mfa Enforced","description":"True if MFA will actually be enforced for this request (mfa=required AND global mfa_mode=enabled)","default":false},"mfa_provider":{"anyOf":[{"$ref":"#/components/schemas/MfaProviderResolved"},{"type":"null"}],"description":"Resolved MFA provider for the user. Present when rule has mfa=required. Shows whether the user has a provider enrolled and which one."},"enable":{"anyOf":[{"$ref":"#/components/schemas/EnableResolved"},{"type":"null"}],"description":"Resolved enable password mode from inheritance chain. Only present for TACACS+ protocol."}},"type":"object","required":["mode","mfa"],"title":"PolicyTestAction","description":"Action determined by the matching rule."},"PolicyTestRequest":{"properties":{"protocol":{"type":"string","enum":["tacacs","radius"],"title":"Protocol","description":"Protocol to test: determines which *_profile_mode column is evaluated"},"username":{"type":"string","maxLength":128,"minLength":1,"title":"Username","description":"Username to test"},"nas_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Nas Ip","description":"NAS device IP for WHERE matching. If omitted, only where_any=true matches."},"source_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Ip","description":"Client IP for SOURCE matching. If omitted, only source_any=true matches."},"access_type":{"type":"string","enum":["remote","console"],"title":"Access Type","description":"Access type: 'remote' (default) or 'console'. Console is TACACS+ only.","default":"remote"},"timestamp":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Timestamp","description":"Simulated time for WHEN matching. If omitted, uses current server time."}},"type":"object","required":["protocol","username"],"title":"PolicyTestRequest","description":"Simulated AAA request for policy testing."},"PolicyTestResponse":{"properties":{"matched":{"type":"boolean","title":"Matched","description":"True if a rule matched, false if all rules were exhausted"},"rule":{"anyOf":[{"$ref":"#/components/schemas/app__modules__aaa__aaa_policy__tester_schemas__RuleTraceEntry"},{"type":"null"}],"description":"The winning rule. Null if no match."},"action":{"anyOf":[{"$ref":"#/components/schemas/PolicyTestAction"},{"type":"null"}],"description":"Action to take. Null if no match."},"evaluation_trace":{"items":{"$ref":"#/components/schemas/app__modules__aaa__aaa_policy__tester_schemas__RuleTraceEntry"},"type":"array","title":"Evaluation Trace","description":"Trace of every rule evaluated, in order."},"warnings":{"items":{"$ref":"#/components/schemas/PolicyTestWarning"},"type":"array","title":"Warnings","description":"Non-blocking caveats about production behavior (e.g. RADIUS rules that rely on SOURCE)."},"resolved_context":{"$ref":"#/components/schemas/app__modules__aaa__aaa_policy__tester_schemas__ResolvedContext"}},"type":"object","required":["matched","resolved_context"],"title":"PolicyTestResponse","description":"Full policy tester response."},"PolicyTestWarning":{"properties":{"code":{"type":"string","title":"Code","description":"Machine-readable warning code, e.g. 'radius_source_unmatchable'"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order","description":"Order of the rule the warning refers to, if rule-specific"},"message":{"type":"string","title":"Message","description":"Human-readable, localized explanation"}},"type":"object","required":["code","message"],"title":"PolicyTestWarning","description":"A non-blocking caveat about how a rule behaves in production.\n\nSurfaced when the simulation result would differ from a live request —\ne.g. a RADIUS rule that relies on SOURCE, which RADIUS device\nadministration cannot evaluate (the NAS does not convey the client IP)."},"PortalPublicFlowResponse":{"properties":{"flow_type":{"type":"string","title":"Flow Type"},"display_name":{"type":"string","title":"Display Name"},"display_icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Icon"},"display_order":{"type":"integer","title":"Display Order"},"icon_svg":{"type":"string","title":"Icon Svg"},"settings":{"additionalProperties":true,"type":"object","title":"Settings"}},"type":"object","required":["flow_type","display_name","display_icon","display_order","icon_svg","settings"],"title":"PortalPublicFlowResponse","description":"Public flow info for the landing page."},"PortalPublicResponse":{"properties":{"name":{"type":"string","title":"Name"},"slug":{"type":"string","title":"Slug"},"logo_data":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Data"},"brand_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Name"},"background_color":{"type":"string","title":"Background Color"},"primary_color":{"type":"string","title":"Primary Color"},"welcome_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Welcome Text"},"success_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Success Text"},"redirect_after_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Redirect After Url"},"captcha_enabled":{"type":"boolean","title":"Captcha Enabled"},"default_flow":{"type":"string","title":"Default Flow"},"flows":{"items":{"$ref":"#/components/schemas/PortalPublicFlowResponse"},"type":"array","title":"Flows","default":[]}},"type":"object","required":["name","slug","logo_data","brand_name","background_color","primary_color","welcome_text","success_text","redirect_after_url","captcha_enabled","default_flow"],"title":"PortalPublicResponse","description":"Public portal config returned to unauthenticated guests."},"PortalServerCertPreview":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"subject_dn":{"type":"string","title":"Subject Dn"},"ca_id":{"type":"string","format":"uuid","title":"Ca Id"},"ca_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ca Name"},"cert_type":{"type":"string","title":"Cert Type"},"status":{"type":"string","title":"Status"},"not_after":{"type":"string","format":"date-time","title":"Not After"},"has_private_key":{"type":"boolean","title":"Has Private Key"},"from_csr":{"type":"boolean","title":"From Csr"}},"type":"object","required":["id","name","subject_dn","ca_id","cert_type","status","not_after","has_private_key","from_csr"],"title":"PortalServerCertPreview","description":"Read-only preview of the bound server certificate.\n\nPopulated by the service from NAC PKI so the admin UI can show the\nbinding (CN, expiry, issuing CA, status) without a second request.\nAll fields are read-only; binding is changed via ``server_certificate_id``."},"PreferencesUpdateRequest":{"properties":{"dashboard":{"anyOf":[{"$ref":"#/components/schemas/DashboardPref"},{"type":"null"}]}},"additionalProperties":false,"type":"object","title":"PreferencesUpdateRequest","description":"PATCH /auth/me/preferences request body.\n\nShallow-merged into ``User.ui_preferences`` by top-level key. v1 carries only\nthe ``dashboard`` section; future sections add their own optional key here.\nGarbage (unknown top-level keys, malformed widget entries) is rejected with\n422 by Pydantic before the service ever runs."},"PreflightCheck":{"properties":{"key":{"type":"string","title":"Key"},"ok":{"type":"boolean","title":"Ok"},"detail":{"type":"string","title":"Detail"},"action":{"type":"string","title":"Action","default":""}},"type":"object","required":["key","ok","detail"],"title":"PreflightCheck","description":"One checked precondition, and what to do when it is not met."},"PreflightResponse":{"properties":{"ready":{"type":"boolean","title":"Ready","description":"Every check passed — a join, or domain authentication, can work."},"checks":{"items":{"$ref":"#/components/schemas/PreflightCheck"},"type":"array","title":"Checks"}},"type":"object","required":["ready","checks"],"title":"PreflightResponse"},"PreviewCollectorRef":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"mode":{"type":"string","title":"Mode"},"effective_status":{"type":"string","title":"Effective Status"}},"type":"object","required":["id","name","mode","effective_status"],"title":"PreviewCollectorRef","description":"Trace header naming the collector that executed (or would execute) a preview.\n\nA preview-context alias of :class:`CollectorRefResponse` (identical shape) — the routed\npreview was executed by (or would be executed by) this collector."},"PreviewConflict":{"properties":{"username":{"type":"string","title":"Username"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["username","reason"],"title":"PreviewConflict","description":"Conflict detected during preview."},"PreviewGroupCreate":{"properties":{"dn":{"type":"string","title":"Dn"},"name":{"type":"string","title":"Name"},"member_count":{"type":"integer","title":"Member Count","default":0}},"type":"object","required":["dn","name"],"title":"PreviewGroupCreate","description":"Group that would be created during sync."},"PreviewGroupUpdate":{"properties":{"name":{"type":"string","title":"Name"},"changes":{"additionalProperties":{"items":{},"type":"array"},"type":"object","title":"Changes"}},"type":"object","required":["name"],"title":"PreviewGroupUpdate","description":"Group that would be updated during sync."},"PreviewJobResultPayload":{"properties":{"capability":{"type":"string","title":"Capability","description":"Self-describing capability tag (informational; the core routes by the dispatch row).","default":"ncm_config"},"ingest_key":{"type":"string","format":"uuid","title":"Ingest Key","description":"The core-minted preview poll-handle — locates the preview dispatch row."},"version":{"type":"string","title":"Version","description":"Snapshot-identity version the collector ran (version-gated first)."},"payload":{"$ref":"#/components/schemas/NcmPreviewResultPayload"}},"additionalProperties":false,"type":"object","required":["ingest_key","version","payload"],"title":"PreviewJobResultPayload","description":"A collector's traced dry-run outcome for one claimed preview request — generic envelope.\n\nTop-level is capability-BLIND: ``ingest_key`` LOCATES the preview dispatch row (its\npoll-handle), ``version`` GATES it, ``capability`` is self-describing metadata (the core\nroutes preview as NCM by the dispatch ROW's trigger/capability). The result data lives in\n``payload`` (:class:`NcmPreviewResultPayload`)."},"PreviewPendingResponse":{"properties":{"overall_status":{"type":"string","enum":["pending","error"],"title":"Overall Status"},"request_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Request Id"},"collector":{"$ref":"#/components/schemas/PreviewCollectorRef"},"collector_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Error"}},"type":"object","required":["overall_status","collector"],"title":"PreviewPendingResponse","description":"A standalone preview was routed to a collector — poll ``request_id`` for the result.\n\nA preview of a config on a STANDALONE source is async: the core mints ``request_id`` and\nthe target collector picks it up on its normal ``/jobs`` poll. The UI polls\n``GET /ncm/runs/preview/{request_id}`` until ``overall_status`` flips to a terminal value.\n``overall_status='pending'`` here signals \"not a sync result — poll this handle\".\n\nA fast-fail (the collector was already offline) instead returns ``overall_status='error'``\nwith ``collector_error='collector_offline'`` and NO ``request_id`` (no row was created)."},"PreviewResponse":{"properties":{"steps":{"items":{"$ref":"#/components/schemas/TraceStepResponse"},"type":"array","title":"Steps"},"overall_status":{"type":"string","enum":["ok","failed"],"title":"Overall Status"},"failure_stage":{"anyOf":[{"$ref":"#/components/schemas/TraceStage"},{"type":"null"}]},"failure_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Class"},"changed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Changed"},"would_be_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Would Be Version"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"content_kind":{"anyOf":[{"$ref":"#/components/schemas/ContentKind"},{"type":"null"}]},"size_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size Bytes"},"scrubbed_result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scrubbed Result"},"failure_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Detail","description":"A scrubbed device failure diagnostic (only on a FAILED preview) — the specific, core-re-scrubbed device text a routed (standalone) failure carried, distinct from the generic per-step 'detail'. NULL on success / when none was reported."},"collector":{"anyOf":[{"$ref":"#/components/schemas/PreviewCollectorRef"},{"type":"null"}]},"collector_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Error"}},"type":"object","required":["overall_status"],"title":"PreviewResponse","description":"The result of a collection preview: a step-by-step trace plus, on success, the\nSCRUBBED would-be config and whether it would cut a new version.\n\n``scrubbed_result`` is the ONLY device-text field — the same ``scrub()`` output an\ningest would store, never the raw capture. For a BINARY capture there is no diffable\nbody: ``content_kind=\"binary\"``, ``size_bytes`` is set and ``scrubbed_result`` stays\n``null`` (change-detection is by ``content_hash`` alone). Nothing here was persisted.\n\n``collector`` names who executed the preview (embedded → a synthetic ref; standalone →\nthe routed collector). ``collector_error`` is the collector-LEVEL error class (offline /\nchannel-down / timed-out / version-mismatch) — DISTINCT from a device error, which lives\ninside the trace with ``overall_status='failed'``. Both are additive (default ``None``),\nso an embedded response and existing consumers are unaffected."},"PreviewResultAck":{"properties":{"ingest_key":{"type":"string","format":"uuid","title":"Ingest Key"},"state":{"type":"string","title":"State","description":"The request state after submit (always 'done')."}},"type":"object","required":["ingest_key","state"],"title":"PreviewResultAck","description":"The core's acknowledgement of a preview-result submission."},"PreviewSummary":{"properties":{"groups_create":{"type":"integer","title":"Groups Create","default":0},"groups_update":{"type":"integer","title":"Groups Update","default":0},"users_create":{"type":"integer","title":"Users Create","default":0},"users_update":{"type":"integer","title":"Users Update","default":0},"users_disable":{"type":"integer","title":"Users Disable","default":0},"users_delete":{"type":"integer","title":"Users Delete","default":0},"conflicts":{"type":"integer","title":"Conflicts","default":0}},"type":"object","title":"PreviewSummary","description":"Summary counts for preview."},"PreviewTraceStep":{"properties":{"stage":{"type":"string","title":"Stage","description":"plan|tcp_connect|negotiate|auth|session_prep|command|scrub|result."},"key":{"type":"string","title":"Key","description":"Stage name or an operator-authored command string — never a secret."},"status":{"type":"string","title":"Status","description":"ok|failed|skipped."},"detail":{"type":"string","title":"Detail","description":"Localized, secret/device-safe stage message.","default":""},"timing_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Timing Ms"},"data":{"additionalProperties":{"anyOf":[{"type":"integer"},{"type":"string"}]},"type":"object","title":"Data","description":"Counts + content hash only."}},"type":"object","required":["stage","key","status"],"title":"PreviewTraceStep","description":"One JSON-serialisable trace step the collector emitted for a traced run.\n\nField-for-field with the core ``TraceStep`` dataclass (secret-safe by construction:\n``key``/``detail`` never carry raw device text; ``data`` is counts + a content hash).\nShared by the routed-preview result AND the on-demand traced-collect ingest — the collector\nemits the same shape for both; the core maps it back to ``TraceStep`` (dropping unknown\nstage/status), never trusting it for device text."},"PreviewUserCreate":{"properties":{"dn":{"type":"string","title":"Dn"},"username":{"type":"string","title":"Username"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},"type":"object","required":["dn","username"],"title":"PreviewUserCreate","description":"User that would be created during sync."},"PreviewUserDelete":{"properties":{"username":{"type":"string","title":"Username"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["username","reason"],"title":"PreviewUserDelete","description":"User that would be hard-deleted during sync."},"PreviewUserDisable":{"properties":{"username":{"type":"string","title":"Username"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["username","reason"],"title":"PreviewUserDisable","description":"User that would be disabled during sync."},"PreviewUserUpdate":{"properties":{"username":{"type":"string","title":"Username"},"changes":{"additionalProperties":{"items":{},"type":"array"},"type":"object","title":"Changes"}},"type":"object","required":["username"],"title":"PreviewUserUpdate","description":"User that would be updated during sync."},"ProcessInfo":{"properties":{"pid":{"type":"integer","title":"Pid"},"cpu_percent":{"type":"number","title":"Cpu Percent"},"memory":{"$ref":"#/components/schemas/ProcessMemory"},"threads":{"type":"integer","title":"Threads"},"open_files":{"type":"integer","title":"Open Files"},"connections":{"type":"integer","title":"Connections"},"create_time":{"type":"string","title":"Create Time"}},"type":"object","required":["pid","cpu_percent","memory","threads","open_files","connections","create_time"],"title":"ProcessInfo","description":"FastAPI process metrics."},"ProcessMemory":{"properties":{"rss_bytes":{"type":"integer","title":"Rss Bytes"},"vms_bytes":{"type":"integer","title":"Vms Bytes"},"rss_human":{"type":"string","title":"Rss Human"},"vms_human":{"type":"string","title":"Vms Human"},"percent":{"type":"number","title":"Percent"}},"type":"object","required":["rss_bytes","vms_bytes","rss_human","vms_human","percent"],"title":"ProcessMemory","description":"Process memory info."},"ProfileUpdateRequest":{"properties":{"lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang","description":"Preferred UI language (must be a SUPPORTED_LOCALES code)"}},"additionalProperties":false,"type":"object","title":"ProfileUpdateRequest","description":"PATCH /auth/me request body — self-service update of one's own profile.\n\nv1 supports only the UI / notification language (``lang``). Future\nincrements add ``first_name``/``last_name``/``display_name``/``phone``\nfor local users (LDAP users keep those directory-synced and read-only)."},"ProgressBucketsResponse":{"properties":{"total":{"type":"integer","title":"Total"},"pending":{"type":"integer","title":"Pending"},"claimed":{"type":"integer","title":"Claimed"},"done":{"type":"integer","title":"Done"},"dead":{"type":"integer","title":"Dead"}},"type":"object","required":["total","pending","claimed","done","dead"],"title":"ProgressBucketsResponse","description":"Run-level roll-up of dispatch/result-state counts."},"QueryResultResponse":{"properties":{"query":{"type":"string","title":"Query"},"columns":{"items":{"type":"string"},"type":"array","title":"Columns"},"rows":{"items":{"items":{},"type":"array"},"type":"array","title":"Rows"}},"type":"object","required":["query","columns","rows"],"title":"QueryResultResponse","description":"Tidy result of one query: ordered columns + positional row values."},"RBACModelCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Unique model name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description","description":"Model description"},"permissions":{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object","maxProperties":256,"title":"Permissions","description":"Permissions JSON object"}},"additionalProperties":false,"type":"object","required":["name","permissions"],"title":"RBACModelCreate","description":"Schema for creating a new RBAC model."},"RBACModelListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_system":{"type":"boolean","title":"Is System"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","is_system","created_at"],"title":"RBACModelListResponse","description":"Abbreviated RBAC model for list views."},"RBACModelResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"is_system":{"type":"boolean","title":"Is System"},"permissions":{"additionalProperties":true,"type":"object","title":"Permissions"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","is_system","permissions","created_at","updated_at"],"title":"RBACModelResponse","description":"Schema for a single RBAC model in API responses."},"RBACModelUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"permissions":{"anyOf":[{"additionalProperties":{"additionalProperties":{"type":"boolean"},"type":"object"},"type":"object","maxProperties":256},{"type":"null"}],"title":"Permissions"}},"additionalProperties":false,"type":"object","title":"RBACModelUpdate","description":"Schema for updating an RBAC model."},"RadiusAcctLogListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"acct_status_type":{"type":"string","title":"Acct Status Type"},"acct_session_id":{"type":"string","title":"Acct Session Id"},"acct_session_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Acct Session Time"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"acct_terminate_cause":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acct Terminate Cause"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","acct_status_type","acct_session_id"],"title":"RadiusAcctLogListResponse","description":"Abbreviated RADIUS acct log for list views."},"RadiusAcctLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"nas_port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Nas Port"},"username":{"type":"string","title":"Username"},"acct_status_type":{"type":"string","title":"Acct Status Type"},"acct_session_id":{"type":"string","title":"Acct Session Id"},"acct_session_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Acct Session Time"},"acct_input_octets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Acct Input Octets"},"acct_output_octets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Acct Output Octets"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"called_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Called Station Id"},"acct_terminate_cause":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Acct Terminate Cause"},"framed_ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Framed Ip Address"},"service_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Type"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"raw_attributes":{"additionalProperties":true,"type":"object","title":"Raw Attributes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","acct_status_type","acct_session_id","created_at"],"title":"RadiusAcctLogResponse","description":"RADIUS accounting log entry response."},"RadiusAttributeDefinition":{"properties":{"name":{"type":"string","title":"Name"},"vsa_type":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Vsa Type"},"data_type":{"type":"string","enum":["string","integer","enum","boolean","ipaddr"],"title":"Data Type","default":"string"},"multi":{"type":"boolean","title":"Multi","default":false},"optional":{"type":"boolean","title":"Optional","default":true},"max_length":{"anyOf":[{"type":"integer","maximum":253.0},{"type":"null"}],"title":"Max Length"},"default":{"anyOf":[{},{"type":"null"}],"title":"Default"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"static":{"anyOf":[{"items":{"$ref":"#/components/schemas/RadiusStaticField"},"type":"array"},{"type":"null"}],"title":"Static"}},"type":"object","required":["name"],"title":"RadiusAttributeDefinition","description":"A single VSA or standard attribute within the template."},"RadiusAttributeEntry":{"properties":{"attribute":{"type":"string","title":"Attribute"},"value":{"type":"string","title":"Value"},"op":{"type":"string","title":"Op","default":"="}},"type":"object","required":["attribute","value"],"title":"RadiusAttributeEntry","description":"Single RADIUS attribute in the preview."},"RadiusAttributePreview":{"properties":{"attribute":{"type":"string","title":"Attribute"},"value":{"type":"string","title":"Value"},"op":{"type":"string","title":"Op","default":"="}},"type":"object","required":["attribute","value"],"title":"RadiusAttributePreview","description":"Single RADIUS attribute for preview."},"RadiusAuthLogListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"status":{"type":"string","title":"Status"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"rule_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Label"},"profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Name"},"reject_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Reason"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"auth_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Type"},"mfa_enforced":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Enforced"},"mfa_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mfa Status"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","status"],"title":"RadiusAuthLogListResponse","description":"Abbreviated RADIUS auth log for table/list views."},"RadiusAuthLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"status":{"type":"string","title":"Status"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"rule_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Label"},"policy_rule_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Policy Rule Id"},"profile_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Name"},"profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Profile Id"},"mfa_enforced":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Mfa Enforced"},"mfa_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mfa Status"},"calling_station_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calling Station Id"},"service_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Type"},"auth_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Type"},"reject_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reject Reason"},"reply_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reply Message"},"auth_duration_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Auth Duration Ms"},"cache_hit":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Cache Hit"},"raw_request":{"additionalProperties":true,"type":"object","title":"Raw Request"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","status","created_at"],"title":"RadiusAuthLogResponse","description":"RADIUS authentication log entry — full detail view."},"RadiusConfigPreviewResponse":{"properties":{"files":{"additionalProperties":{"type":"string"},"type":"object","title":"Files"},"total_size":{"type":"integer","title":"Total Size"}},"type":"object","required":["files","total_size"],"title":"RadiusConfigPreviewResponse","description":"Response for config preview (multi-file)."},"RadiusConfigReloadResponse":{"properties":{"status":{"type":"string","title":"Status"},"config_dir":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Config Dir"},"files":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Files"},"total_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Size"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"timestamp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timestamp"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"}},"type":"object","required":["status"],"title":"RadiusConfigReloadResponse","description":"Response for config reload."},"RadiusConfigSnippetLineSchema":{"properties":{"num":{"type":"integer","title":"Num"},"text":{"type":"string","title":"Text"},"error":{"type":"boolean","title":"Error","default":false}},"type":"object","required":["num","text"],"title":"RadiusConfigSnippetLineSchema","description":"A single line in a config error snippet."},"RadiusConfigStatusInfo":{"properties":{"deployed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed At"},"deployed_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deployed By"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"files":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Files"},"total_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Size"},"validation":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Validation"}},"type":"object","title":"RadiusConfigStatusInfo","description":"Config deploy and validation status."},"RadiusConfigValidateResponse":{"properties":{"valid":{"type":"boolean","title":"Valid"},"content_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Hash"},"files":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Files"},"total_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Size"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"error_file":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error File"},"error_line":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Error Line"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"config_snippet":{"anyOf":[{"items":{"$ref":"#/components/schemas/RadiusConfigSnippetLineSchema"},"type":"array"},{"type":"null"}],"title":"Config Snippet"},"raw_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Error"}},"type":"object","required":["valid"],"title":"RadiusConfigValidateResponse","description":"Response for config validation (dry-run)."},"RadiusFieldDefinition":{"properties":{"type":{"type":"string","enum":["string","integer","enum","boolean"],"title":"Type","default":"string"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"min":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min"},"max":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max"},"max_length":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Length"},"regex":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Regex"},"values":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Values"},"default":{"anyOf":[{},{"type":"null"}],"title":"Default"}},"type":"object","title":"RadiusFieldDefinition","description":"Definition of a single input field within a static attribute."},"RadiusProfileCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique profile name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"template_id":{"type":"string","format":"uuid","title":"Template Id","description":"FK to RadiusTemplate"},"service_type":{"anyOf":[{"type":"string","enum":["Login-User","Administrative-User","NAS-Prompt-User"]},{"type":"null"}],"title":"Service Type","description":"Login-User | Administrative-User | NAS-Prompt-User | null (= template default)"},"attribute_values":{"additionalProperties":true,"type":"object","title":"Attribute Values","description":"Structured values per attribute from template"},"raw_attributes":{"items":{"$ref":"#/components/schemas/RawRadiusAttribute"},"type":"array","maxItems":256,"title":"Raw Attributes","description":"Additional attributes not from template"},"session_timeout":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Idle Timeout"},"reply_message":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Reply Message"},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true}},"additionalProperties":false,"type":"object","required":["name","template_id"],"title":"RadiusProfileCreate","description":"Schema for creating a RADIUS profile."},"RadiusProfileListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"template":{"$ref":"#/components/schemas/RadiusTemplateBrief"},"service_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Type"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","template","is_enabled","created_at"],"title":"RadiusProfileListResponse","description":"Abbreviated profile for list views."},"RadiusProfileResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"template":{"$ref":"#/components/schemas/RadiusTemplateBrief"},"service_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Type"},"attribute_values":{"additionalProperties":true,"type":"object","title":"Attribute Values"},"raw_attributes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Raw Attributes"},"session_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idle Timeout"},"reply_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reply Message"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"template_detail":{"anyOf":[{"$ref":"#/components/schemas/RadiusTemplateResponse"},{"type":"null"}]}},"type":"object","required":["id","name","template_id","template","attribute_values","is_enabled","created_at","updated_at"],"title":"RadiusProfileResponse","description":"Full profile response."},"RadiusProfileUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Description"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"service_type":{"anyOf":[{"type":"string","enum":["Login-User","Administrative-User","NAS-Prompt-User"]},{"type":"null"}],"title":"Service Type"},"attribute_values":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Attribute Values"},"raw_attributes":{"anyOf":[{"items":{"$ref":"#/components/schemas/RawRadiusAttribute"},"type":"array","maxItems":256},{"type":"null"}],"title":"Raw Attributes"},"session_timeout":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Idle Timeout"},"reply_message":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Reply Message"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"}},"additionalProperties":false,"type":"object","title":"RadiusProfileUpdate","description":"Schema for updating a RADIUS profile."},"RadiusServiceConnectivity":{"properties":{"reachable":{"type":"boolean","title":"Reachable","default":false},"auth_port":{"type":"integer","title":"Auth Port","default":1812},"acct_port":{"type":"integer","title":"Acct Port","default":1813},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","title":"RadiusServiceConnectivity","description":"UDP/TCP connectivity check result."},"RadiusServiceStatus":{"properties":{"service":{"type":"string","title":"Service","default":"freeradius"},"port":{"type":"integer","title":"Port","default":1812},"reachable":{"type":"boolean","title":"Reachable","default":false},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"config":{"$ref":"#/components/schemas/ConfigFileStatus"}},"type":"object","title":"RadiusServiceStatus","description":"RADIUS service status."},"RadiusSettingsResponse":{"properties":{"auth_port":{"type":"integer","title":"Auth Port","default":1812},"acct_port":{"type":"integer","title":"Acct Port","default":1813},"global_secret":{"type":"string","title":"Global Secret","default":""},"mfa_mode":{"type":"string","title":"Mfa Mode","default":"challenge"},"status_server":{"type":"boolean","title":"Status Server","default":true},"reject_delay":{"type":"integer","title":"Reject Delay","default":1},"max_request_time":{"type":"integer","title":"Max Request Time","default":30},"duplicate_interval":{"type":"integer","title":"Duplicate Interval","default":5},"cleanup_delay":{"type":"integer","title":"Cleanup Delay","default":5},"log_auth":{"type":"boolean","title":"Log Auth","default":true},"log_auth_badpass":{"type":"boolean","title":"Log Auth Badpass","default":false},"log_auth_goodpass":{"type":"boolean","title":"Log Auth Goodpass","default":false},"log_retention_days":{"type":"integer","title":"Log Retention Days","default":365},"auth_cache_ttl":{"type":"integer","title":"Auth Cache Ttl","default":30},"cache_refresh_interval":{"type":"integer","title":"Cache Refresh Interval","default":30},"acct_batch_size":{"type":"integer","title":"Acct Batch Size","default":500},"acct_flush_interval_ms":{"type":"integer","title":"Acct Flush Interval Ms","default":100},"dynamic_client_networks":{"type":"string","title":"Dynamic Client Networks","default":""},"dynamic_client_lifetime":{"type":"integer","title":"Dynamic Client Lifetime","default":300},"bruteforce_enabled":{"type":"boolean","title":"Bruteforce Enabled","default":true},"bruteforce_threshold":{"type":"integer","title":"Bruteforce Threshold","default":10},"bruteforce_nas_threshold":{"type":"integer","title":"Bruteforce Nas Threshold","default":50},"bruteforce_window_minutes":{"type":"integer","title":"Bruteforce Window Minutes","default":15}},"type":"object","title":"RadiusSettingsResponse","description":"Full RADIUS settings document returned by GET.\n\nEncrypted values (e.g. global_secret) are masked as '***'.\nInternal fields are not included in the response.\nPort fields are read-only (sourced from environment variables)."},"RadiusSettingsUpdate":{"properties":{"global_secret":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Global Secret"},"mfa_mode":{"anyOf":[{"type":"string","enum":["disabled","challenge","append"]},{"type":"null"}],"title":"Mfa Mode"},"status_server":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Status Server"},"reject_delay":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":0.0},{"type":"null"}],"title":"Reject Delay"},"max_request_time":{"anyOf":[{"type":"integer","maximum":120.0,"minimum":1.0},{"type":"null"}],"title":"Max Request Time"},"duplicate_interval":{"anyOf":[{"type":"integer","maximum":60.0,"minimum":0.0},{"type":"null"}],"title":"Duplicate Interval"},"cleanup_delay":{"anyOf":[{"type":"integer","maximum":60.0,"minimum":0.0},{"type":"null"}],"title":"Cleanup Delay"},"log_auth":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Log Auth"},"log_auth_badpass":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Log Auth Badpass"},"log_auth_goodpass":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Log Auth Goodpass"},"log_retention_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Log Retention Days"},"auth_cache_ttl":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":0.0},{"type":"null"}],"title":"Auth Cache Ttl"},"cache_refresh_interval":{"anyOf":[{"type":"integer","maximum":300.0,"minimum":5.0},{"type":"null"}],"title":"Cache Refresh Interval"},"acct_batch_size":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Acct Batch Size"},"acct_flush_interval_ms":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":10.0},{"type":"null"}],"title":"Acct Flush Interval Ms"},"dynamic_client_networks":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Dynamic Client Networks"},"dynamic_client_lifetime":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Dynamic Client Lifetime"},"bruteforce_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bruteforce Enabled"},"bruteforce_threshold":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Threshold"},"bruteforce_nas_threshold":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Nas Threshold"},"bruteforce_window_minutes":{"anyOf":[{"type":"integer","maximum":1440.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Window Minutes"}},"type":"object","title":"RadiusSettingsUpdate","description":"Partial update for RADIUS settings.\n\nOnly the fields present in the request body will be updated.\nOmitted fields remain unchanged in the database.\nPort fields and internal fields are not accepted.\n\nNOTE: this is a document-style flat-settings PATCH. The settings page renders\nthe read-only ENV-sourced ``auth_port`` / ``acct_port`` as badges (they live\nin the response but not here), so the form deliberately treats them as\nread-only and never PATCHes them. We DELIBERATELY do NOT set\n``extra=\"forbid\"`` here (same as TacacsSettingsUpdate): a settings document is\nexactly the case the validation guideline flags — a stray or read-only key in\nthe body must not 422 a settings save. Every field stays bounded (and enum-ish\nones use a Literal whitelist) regardless."},"RadiusStaticField":{"properties":{"key":{"type":"string","pattern":"^[a-z0-9_-]+$","title":"Key"},"label":{"type":"string","title":"Label"},"pattern":{"type":"string","title":"Pattern"},"optional":{"type":"boolean","title":"Optional","default":true},"multi":{"type":"boolean","title":"Multi","default":false},"fields":{"additionalProperties":{"$ref":"#/components/schemas/RadiusFieldDefinition"},"type":"object","title":"Fields"}},"type":"object","required":["key","label","pattern"],"title":"RadiusStaticField","description":"A static (pre-defined) attribute pattern with substitutable fields."},"RadiusStatusResponse":{"properties":{"service":{"$ref":"#/components/schemas/RadiusServiceConnectivity"},"config":{"$ref":"#/components/schemas/RadiusConfigStatusInfo"}},"type":"object","required":["service","config"],"title":"RadiusStatusResponse","description":"Response for GET /radius/status."},"RadiusTemplateBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"vendor":{"type":"string","title":"Vendor"},"vendor_id":{"type":"integer","title":"Vendor Id"}},"type":"object","required":["id","slug","name","vendor","vendor_id"],"title":"RadiusTemplateBrief","description":"Minimal template info embedded in profile responses."},"RadiusTemplateCreate":{"properties":{"slug":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z0-9-]+$","title":"Slug","description":"URL-friendly identifier, immutable after creation"},"name":{"type":"string","maxLength":64,"minLength":1,"title":"Name","description":"Unique template name"},"vendor":{"type":"string","maxLength":64,"minLength":1,"title":"Vendor"},"vendor_id":{"type":"integer","maximum":99999.0,"minimum":0.0,"title":"Vendor Id","description":"IANA Private Enterprise Number"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"data":{"$ref":"#/components/schemas/RadiusTemplateData","description":"Template structure"},"raw_yaml":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Raw Yaml","description":"Original YAML for re-export"}},"additionalProperties":false,"type":"object","required":["slug","name","vendor","vendor_id","data"],"title":"RadiusTemplateCreate","description":"Schema for creating a RADIUS template via direct JSON payload."},"RadiusTemplateData":{"properties":{"defaults":{"anyOf":[{"$ref":"#/components/schemas/RadiusTemplateDefaults"},{"type":"null"}]},"attributes":{"items":{"$ref":"#/components/schemas/RadiusAttributeDefinition"},"type":"array","title":"Attributes"}},"type":"object","title":"RadiusTemplateData","description":"Validates the full JSONB structure of a RadiusTemplate on upload.\n\nThis model is used at upload time to ensure the payload\nconforms to the expected structure before storing as JSONB."},"RadiusTemplateDefaults":{"properties":{"service_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Type"},"session_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idle Timeout"},"reply_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reply Message"}},"type":"object","title":"RadiusTemplateDefaults","description":"Default values for common RADIUS reply attributes."},"RadiusTemplateListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"vendor":{"type":"string","title":"Vendor"},"vendor_id":{"type":"integer","title":"Vendor Id"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"attribute_count":{"type":"integer","title":"Attribute Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","slug","name","vendor","vendor_id","created_at"],"title":"RadiusTemplateListResponse","description":"Abbreviated template for list views (without data/raw_yaml)."},"RadiusTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"vendor":{"type":"string","title":"Vendor"},"vendor_id":{"type":"integer","title":"Vendor Id"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"data":{"additionalProperties":true,"type":"object","title":"Data"},"raw_yaml":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Yaml"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","slug","name","vendor","vendor_id","data","created_at","updated_at"],"title":"RadiusTemplateResponse","description":"Full template response."},"RadiusTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Name"},"vendor":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Vendor"},"vendor_id":{"anyOf":[{"type":"integer","maximum":99999.0,"minimum":0.0},{"type":"null"}],"title":"Vendor Id"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"data":{"anyOf":[{"$ref":"#/components/schemas/RadiusTemplateData"},{"type":"null"}]},"raw_yaml":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Raw Yaml"}},"additionalProperties":false,"type":"object","title":"RadiusTemplateUpdate","description":"Schema for updating a RADIUS template.\n\nNote: slug is immutable and cannot be changed after creation."},"RadiusTemplateValidateRequest":{"properties":{"yaml_content":{"type":"string","maxLength":100000,"minLength":1,"title":"Yaml Content","description":"YAML content to validate"}},"additionalProperties":false,"type":"object","required":["yaml_content"],"title":"RadiusTemplateValidateRequest","description":"Request body for YAML validation endpoint."},"RadiusTemplateValidateResponse":{"properties":{"valid":{"type":"boolean","title":"Valid"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"},"parsed":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parsed"}},"type":"object","required":["valid"],"title":"RadiusTemplateValidateResponse","description":"Response for YAML validation endpoint."},"RawAttribute":{"properties":{"service":{"type":"string","maxLength":256,"minLength":1,"pattern":"^[A-Za-z0-9_.:@/-]+$","title":"Service"},"name":{"type":"string","maxLength":256,"minLength":1,"pattern":"^[A-Za-z0-9_.:@/-]+$","title":"Name"},"separator":{"type":"string","enum":["=","*"],"title":"Separator","default":"="},"value":{"type":"string","maxLength":1024,"title":"Value"}},"additionalProperties":false,"type":"object","required":["service","name","value"],"title":"RawAttribute","description":"Additional AV-pair not covered by the template."},"RawRadiusAttribute":{"properties":{"vendor_id":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Vendor Id","description":"IANA PEN for VSA, null for standard"},"vsa_type":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Vsa Type","description":"VSA type number"},"name":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Name","description":"Attribute name (standard attrs)"},"value":{"type":"string","maxLength":253,"title":"Value","description":"Attribute value string"}},"additionalProperties":false,"type":"object","required":["value"],"title":"RawRadiusAttribute","description":"An arbitrary RADIUS attribute not defined in the template."},"ReassignCertData":{"properties":{"linked_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked User Id"}},"type":"object","title":"ReassignCertData","description":"Reassign a device certificate to a different user (or unlink)."},"RecentChangeEntry":{"properties":{"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When the event was recorded (UTC)"},"event_type":{"type":"string","title":"Event Type","description":"Audit event type, e.g. DEVICE_UPDATED"},"actor_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Username","description":"Who performed the action (null = system)"},"target_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Target Type","description":"Affected entity type, e.g. device"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary","description":"Short human-readable extract of the event details (not the full JSON)"}},"type":"object","required":["created_at","event_type"],"title":"RecentChangeEntry","description":"One audit-log entry condensed for the recent-changes widget."},"RecentChangeItem":{"properties":{"tracked_config_id":{"type":"string","format":"uuid","title":"Tracked Config Id"},"config_name":{"type":"string","title":"Config Name"},"source_id":{"type":"string","format":"uuid","title":"Source Id","description":"The collection source this config is gathered from"},"source_name":{"type":"string","title":"Source Name","description":"Human name of the collection source (joined in — no N+1)"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"},"version":{"type":"integer","title":"Version","description":"Per-config version ordinal of this snapshot (1-based rank by ingest_ordinal)"},"content_kind":{"$ref":"#/components/schemas/ContentKind"},"changed_by_count":{"type":"integer","title":"Changed By Count","description":"Number of distinct AAA users attributed to the change (0 if none)"},"changed_by_users":{"items":{"type":"string"},"type":"array","title":"Changed By Users","description":"Bounded (<=5) distinct AAA usernames attributed to the change"}},"type":"object","required":["tracked_config_id","config_name","source_id","source_name","captured_at","version","content_kind","changed_by_count"],"title":"RecentChangeItem","description":"One entry in the recent-changes feed — a captured snapshot with its config + source.\n\n``version`` is the snapshot's **per-config** version ordinal (its 1-based rank within\nITS config's history ordered by ``ingest_ordinal``), NOT the global ``Snapshot.ingest_ordinal``:\na config's 3rd capture is ``version=3`` regardless of how many other configs were captured.\nIt matches the tracked-config response's ``last_changed_version`` for that config's latest\nsnapshot and preview's ``would_be_version``."},"RecentChangesResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RecentChangeEntry"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"RecentChangesResponse","description":"Latest audit-log entries (newest first)."},"RecipeKind":{"type":"string","enum":["cli","http","file"],"title":"RecipeKind","description":"How a recipe extracts a config."},"RecipientGroupCreate":{"properties":{"group_id":{"type":"string","format":"uuid","title":"Group Id","description":"The user group to subscribe to this config's changes"}},"additionalProperties":false,"type":"object","required":["group_id"],"title":"RecipientGroupCreate","description":"Bind a user group as a change-notification recipient of a tracked config."},"RecipientGroupResponse":{"properties":{"group_id":{"type":"string","format":"uuid","title":"Group Id"},"group_name":{"type":"string","title":"Group Name"},"has_email":{"type":"boolean","title":"Has Email"}},"type":"object","required":["group_id","group_name","has_email"],"title":"RecipientGroupResponse","description":"A recipient-group subscription: the bound group + whether it can actually receive mail.\n\n``has_email`` is False when the group has no active member with a non-empty email — the\nsubscription then delivers to nobody, so the UI surfaces it as a warning rather than a\nsilent no-send."},"Recipients":{"properties":{"group_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Group Ids"},"emails":{"items":{"type":"string","maxLength":254,"format":"email"},"type":"array","title":"Emails"}},"additionalProperties":false,"type":"object","title":"Recipients","description":"Who receives a delivery: user groups (expanded to member e-mails) + literal addresses."},"Recurrence":{"properties":{"kind":{"$ref":"#/components/schemas/RecurrenceKind"},"time":{"type":"string","title":"Time","description":"Wall-clock time of day in the system timezone, 'HH:MM' (24h)."},"weekday":{"anyOf":[{"type":"integer","maximum":6.0,"minimum":0.0},{"type":"null"}],"title":"Weekday","description":"0=Mon .. 6=Sun (weekly only)."},"day_of_month":{"anyOf":[{"type":"integer","maximum":31.0,"minimum":1.0},{"type":"null"}],"title":"Day Of Month","description":"Day of month 1..31 (monthly only)."}},"additionalProperties":false,"type":"object","required":["kind","time"],"title":"Recurrence","description":"A calendar recurrence interpreted in the system timezone."},"RecurrenceKind":{"type":"string","enum":["daily","weekly","monthly"],"title":"RecurrenceKind","description":"The calendar cadence of a schedule."},"RefCount":{"properties":{"blocking":{"type":"integer","title":"Blocking","default":0},"auto":{"type":"integer","title":"Auto","default":0}},"type":"object","title":"RefCount","description":"Compact per-object counts for the list \"Ref\" column (no labels)."},"RefCountsRequest":{"properties":{"ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":200,"title":"Ids"}},"type":"object","title":"RefCountsRequest","description":"Body for the batch counts endpoint: the ids of one visible page."},"RefResolution":{"type":"string","enum":["blocking","auto"],"title":"RefResolution","description":"Which delete-semantics bucket a reference falls into."},"ReferenceReport":{"properties":{"blocking":{"items":{"$ref":"#/components/schemas/app__shared__references__RefItem"},"type":"array","title":"Blocking"},"auto":{"items":{"$ref":"#/components/schemas/app__shared__references__RefItem"},"type":"array","title":"Auto"}},"type":"object","title":"ReferenceReport","description":"Every reference to one object, split into the two buckets."},"RefreshRequest":{"properties":{"refresh_token":{"type":"string","maxLength":4096,"minLength":1,"title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshRequest","description":"POST /auth/refresh request body."},"RefreshResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"}},"type":"object","required":["access_token","refresh_token"],"title":"RefreshResponse","description":"POST /auth/refresh response body (rotated tokens)."},"RegisterNodeRequest":{"properties":{"token":{"type":"string","minLength":1,"title":"Token","description":"The join secret issued for this node."}},"type":"object","required":["token"],"title":"RegisterNodeRequest","description":"A joining node redeeming its token (token-authenticated; no user session)."},"RegisterNodeResponse":{"properties":{"node_id":{"type":"string","format":"uuid","title":"Node Id"},"name":{"type":"string","title":"Name"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"}},"type":"object","required":["node_id","name"],"title":"RegisterNodeResponse"},"RelativeWindow-Input":{"properties":{"type":{"type":"string","const":"relative","title":"Type","default":"relative"},"days":{"type":"integer","maximum":3660.0,"minimum":1.0,"title":"Days","description":"Length of the rolling window in days","default":7}},"additionalProperties":false,"type":"object","title":"RelativeWindow","description":"A rolling window of the last ``days`` days, resolved to bounds at render time."},"RelativeWindow-Output":{"type":"string","enum":["last_24h","last_7d","last_30d","last_60d","custom"],"title":"RelativeWindow","description":"A relative time window a dataset's period filter may select (wave 1a).\n\nA dataset is **always stored relative** (never absolute dates), so a saved\ndataset — and later a scheduled one — resolves its window to ``now - N .. now``\nat each run (engine ``compose``). ``CUSTOM`` means \"last N days\" where the user\nsupplies N; every other member has a fixed day count (:attr:`fixed_days`). A\none-off *export* may later override the window with absolute dates, but that is\nan engine-level override — it does not change what the dataset stores."},"RenderRequest":{"properties":{"filters":{"additionalProperties":true,"type":"object","title":"Filters","description":"Relative filter values"},"display_config":{"additionalProperties":true,"type":"object","title":"Display Config","description":"Kind-specific display config (§5.1)"}},"additionalProperties":false,"type":"object","title":"RenderRequest","description":"Render a template ad-hoc: compose with these filter values + display config."},"RenderResponse":{"properties":{"html":{"type":"string","title":"Html"}},"type":"object","required":["html"],"title":"RenderResponse","description":"A rendered report as one self-contained HTML document (for ``srcdoc``)."},"ReplicationSlotStatus":{"properties":{"name":{"type":"string","title":"Name"},"active":{"type":"boolean","title":"Active","description":"True when a replica is currently connected to the slot."},"wal_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Wal Status","description":"reserved | extended | unreserved | lost. 'unreserved'/'lost' mean WAL is being (or has been) discarded — the slot's replica must re-sync."}},"type":"object","required":["name","active"],"title":"ReplicationSlotStatus","description":"A physical replication slot on the primary — the WAL-retention health signal."},"ReportConfig":{"properties":{"title_page":{"$ref":"#/components/schemas/TitlePageConfig"},"toc":{"$ref":"#/components/schemas/TocConfig"},"period":{"$ref":"#/components/schemas/ReportPeriod"},"pages":{"items":{"$ref":"#/components/schemas/ReportPage"},"type":"array","title":"Pages"}},"additionalProperties":false,"type":"object","title":"ReportConfig","description":"The full report definition — persisted verbatim as the ``config`` JSONB blob."},"ReportCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Unique report name"},"config":{"$ref":"#/components/schemas/ReportConfig","description":"The report composition (§16)"}},"additionalProperties":false,"type":"object","required":["name"],"title":"ReportCreate","description":"Create a report from a name and a composition config."},"ReportPage":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"}},"additionalProperties":false,"type":"object","required":["dataset_id"],"title":"ReportPage","description":"One page of the report — a single saved dataset (§16: page = 1 dataset for MVP)."},"ReportPeriod":{"properties":{"mode":{"type":"string","enum":["global","dataset"],"title":"Mode","default":"global"},"window":{"oneOf":[{"$ref":"#/components/schemas/RelativeWindow-Input"},{"$ref":"#/components/schemas/AbsoluteWindow"}],"title":"Window","discriminator":{"propertyName":"type","mapping":{"absolute":"#/components/schemas/AbsoluteWindow","relative":"#/components/schemas/RelativeWindow-Input"}}}},"additionalProperties":false,"type":"object","title":"ReportPeriod","description":"The report's period policy: one global window for all pages, or per-dataset windows."},"ReportRenderRequest":{"properties":{"name":{"type":"string","maxLength":128,"title":"Name","default":""},"config":{"$ref":"#/components/schemas/ReportConfig"}},"additionalProperties":false,"type":"object","title":"ReportRenderRequest","description":"Render an **ad-hoc** report config to HTML — the builder previewing an unsaved\nor dirty composition (§16). No persistence and no dataset-existence validation: a\nmissing dataset degrades to a placeholder page, exactly as a saved report does.\n``name`` heads the title page and may be blank while the builder is mid-edit."},"ReportResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"config":{"additionalProperties":true,"type":"object","title":"Config"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"dataset_names":{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object","title":"Dataset Names"}},"type":"object","required":["id","name","config","created_at","updated_at"],"title":"ReportResponse","description":"A report's stored shape."},"ReportScheduleCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name"},"enabled":{"type":"boolean","title":"Enabled","default":true},"items":{"items":{"$ref":"#/components/schemas/ScheduleItem"},"type":"array","minItems":1,"title":"Items"},"recurrence":{"$ref":"#/components/schemas/Recurrence"},"start_at":{"type":"string","format":"date-time","title":"Start At"},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End At"},"recipients":{"$ref":"#/components/schemas/Recipients"}},"additionalProperties":false,"type":"object","required":["name","items","recurrence","start_at","recipients"],"title":"ReportScheduleCreate","description":"Payload to create a schedule."},"ReportScheduleResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"enabled":{"type":"boolean","title":"Enabled"},"items":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Items"},"recurrence":{"additionalProperties":true,"type":"object","title":"Recurrence"},"recipients":{"additionalProperties":true,"type":"object","title":"Recipients"},"recipient_groups":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recipient Groups"},"start_at":{"type":"string","format":"date-time","title":"Start At"},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End At"},"next_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Run At"},"last_run_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Run At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","enabled","items","recurrence","recipients","start_at","end_at","next_run_at","last_run_at","created_at","updated_at"],"title":"ReportScheduleResponse","description":"A schedule as returned by the API.\n\nDetail responses (get/create/update) additionally carry **read-only** display\nnames — each item's ``target_name`` and the resolved ``recipient_groups`` — so a\nclient can show the report/dataset/group by name without re-fetching (or falling\nback to the raw UUID). The list endpoint leaves them empty (it shows counts). A\nsince-deleted target resolves to ``null``."},"ReportScheduleUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"items":{"anyOf":[{"items":{"$ref":"#/components/schemas/ScheduleItem"},"type":"array","minItems":1},{"type":"null"}],"title":"Items"},"recurrence":{"anyOf":[{"$ref":"#/components/schemas/Recurrence"},{"type":"null"}]},"start_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start At"},"end_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End At"},"recipients":{"anyOf":[{"$ref":"#/components/schemas/Recipients"},{"type":"null"}]}},"additionalProperties":false,"type":"object","title":"ReportScheduleUpdate","description":"Partial update — every field optional."},"ReportUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name","description":"New unique report name"},"config":{"anyOf":[{"$ref":"#/components/schemas/ReportConfig"},{"type":"null"}],"description":"Replacement composition config"}},"additionalProperties":false,"type":"object","title":"ReportUpdate","description":"Update a report. Both fields are optional (partial update)."},"ResetPasswordRequest":{"properties":{"token":{"type":"string","maxLength":4096,"minLength":1,"title":"Token"},"new_password":{"type":"string","maxLength":256,"minLength":1,"title":"New Password"}},"type":"object","required":["token","new_password"],"title":"ResetPasswordRequest","description":"POST /auth/reset-password request body."},"ResetPasswordResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"ResetPasswordResponse","description":"POST /auth/reset-password response."},"ResetPasswordVerifyResponse":{"properties":{"valid":{"type":"boolean","title":"Valid"},"username":{"type":"string","title":"Username"},"purpose":{"type":"string","title":"Purpose","default":"reset"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"}},"type":"object","required":["valid","username"],"title":"ResetPasswordVerifyResponse","description":"GET /auth/reset-password/verify response."},"ResolvedEndpointContext":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"mac_address":{"type":"string","title":"Mac Address"},"hostname":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hostname"},"endpoint_groups":{"items":{"$ref":"#/components/schemas/ResolvedGroupInfo"},"type":"array","title":"Endpoint Groups"}},"type":"object","required":["id","mac_address"],"title":"ResolvedEndpointContext","description":"Resolved endpoint information."},"ResolvedGroupInfo":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"ResolvedGroupInfo","description":"Abbreviated group info for resolved context."},"ResolvedUserContext":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"username":{"type":"string","title":"Username"},"groups":{"items":{"$ref":"#/components/schemas/ResolvedGroupInfo"},"type":"array","title":"Groups"}},"type":"object","required":["id","username"],"title":"ResolvedUserContext","description":"Resolved user information."},"ResultStatus":{"type":"string","enum":["ok","changed","unchanged","failed"],"title":"ResultStatus","description":"The outcome of collecting one tracked config within a run.\n\n``ok`` — collected, first snapshot (nothing to compare against);\n``changed`` — collected, a new version was cut; ``unchanged`` — collected but\ndeduped (no new version); ``failed`` — collection failed (see ``failure_class``)."},"RevokeCertData":{"properties":{"reason":{"type":"string","enum":["key_compromise","ca_compromise","affiliation_changed","superseded","cessation_of_operation","certificate_hold","unspecified"],"title":"Reason","default":"unspecified"}},"type":"object","title":"RevokeCertData","description":"Revoke an issued certificate."},"RevokeIdentityResponse":{"properties":{"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"collector_name":{"type":"string","title":"Collector Name"},"identity_status":{"type":"string","title":"Identity Status"}},"type":"object","required":["collector_id","collector_name","identity_status"],"title":"RevokeIdentityResponse","description":"Acknowledgement that a collector's pinned identity was revoked."},"RootCaCreate":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"subject_cn":{"type":"string","maxLength":255,"minLength":1,"title":"Subject Cn"},"subject_o":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Subject O"},"subject_ou":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Subject Ou"},"subject_c":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Subject C"},"subject_st":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Subject St"},"subject_l":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Subject L"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa4096"},"validity_years":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Validity Years","default":10},"crl_distribution_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Crl Distribution Url"},"ocsp_responder_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Ocsp Responder Url"}},"additionalProperties":false,"type":"object","required":["name","subject_cn"],"title":"RootCaCreate","description":"Create a new root CA (generates key + self-signed certificate).\n\nextra=\"forbid\": admin-only (CreateCaForm submits an explicit object with\nexactly these keys). Subject fields are LENGTH-bounded only — no charset\nregex on a CN/DN, which may legitimately hold any UTF-8."},"RotateKeyRequest":{"properties":{"new_master_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Master Key","description":"A valid Fernet key to use as the new master key. If null or omitted, a new key is generated automatically."}},"type":"object","title":"RotateKeyRequest","description":"Request body for key rotation."},"RotateKeyResponse":{"properties":{"re_encrypted_count":{"type":"integer","title":"Re Encrypted Count","description":"Number of encrypted records re-encrypted with the new key"},"new_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Key","description":"The auto-generated Fernet key (returned only when new_master_key was null). Store it securely — it will not be shown again."}},"type":"object","required":["re_encrypted_count"],"title":"RotateKeyResponse","description":"Response after a successful key rotation."},"RotatedTableStatus":{"properties":{"table":{"type":"string","title":"Table"},"group":{"type":"string","title":"Group"},"label":{"type":"string","title":"Label"},"mechanism":{"type":"string","title":"Mechanism"},"partition_column":{"type":"string","title":"Partition Column"},"retention_setting":{"type":"string","title":"Retention Setting"},"retention_days":{"type":"integer","title":"Retention Days"},"partitioned":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Partitioned"},"partition_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Partition Count"},"has_default_data":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Default Data"},"oldest_month":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Oldest Month"},"newest_month":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Newest Month"},"current_month":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current Month"},"months_ahead":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Months Ahead"},"retained_months":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Retained Months"},"months_to_drop_next":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Months To Drop Next"},"approx_row_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Approx Row Count"},"oldest_record_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Oldest Record At"},"total_bytes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Bytes"},"note_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note Key"}},"type":"object","required":["table","group","label","mechanism","partition_column","retention_setting","retention_days"],"title":"RotatedTableStatus","description":"Rotation status for one table."},"RuleTacacsPreviewResponse":{"properties":{"rule_id":{"type":"string","title":"Rule Id"},"group_name":{"type":"string","title":"Group Name"},"config":{"type":"string","title":"Config"}},"type":"object","required":["rule_id","group_name","config"],"title":"RuleTacacsPreviewResponse","description":"tac_plus-ng config snippet generated by a single AAA policy rule."},"RunProgressResponse":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"status":{"$ref":"#/components/schemas/RunStatus"},"collectors":{"items":{"$ref":"#/components/schemas/CollectorProgressResponse"},"type":"array","title":"Collectors"},"totals":{"$ref":"#/components/schemas/ProgressBucketsResponse"}},"type":"object","required":["run_id","status","totals"],"title":"RunProgressResponse","description":"Per-collector fan-in progress for a run.\n\nA run reads ``completed`` the moment orchestration is handed off — NOT when every\nstandalone collector has finished collecting. This response is the actual fan-in\ntruth: per-collector ``{pending, claimed, done, dead}`` buckets rebuilt from the\ndispatch rows (standalone) + this run's results (embedded), plus a run-level roll-up."},"RunRequest":{"properties":{"filters":{"additionalProperties":true,"type":"object","title":"Filters","default":{}}},"type":"object","title":"RunRequest","description":"Run a template with these filter values (keyed by ``FilterSpec.name``).\n\nValues are JSON scalars (ISO strings for datetimes); the engine coerces each\nto its declared type and binds it as a query parameter — never interpolated."},"RunResponse":{"properties":{"template_id":{"type":"string","title":"Template Id"},"results":{"items":{"$ref":"#/components/schemas/QueryResultResponse"},"type":"array","title":"Results"}},"type":"object","required":["template_id","results"],"title":"RunResponse","description":"All query results for a run, in the template's query order."},"RunResultCounts":{"properties":{"ok":{"type":"integer","title":"Ok","default":0},"changed":{"type":"integer","title":"Changed","default":0},"unchanged":{"type":"integer","title":"Unchanged","default":0},"failed":{"type":"integer","title":"Failed","default":0},"total":{"type":"integer","title":"Total","default":0}},"type":"object","title":"RunResultCounts","description":"Real per-run outcome tally, counted from the ``ncm_results`` rows.\n\nThis is the fan-in truth (embedded AND standalone results land here), unlike\n``summary`` which freezes embedded-only counts at run-close — a standalone run\nreads ``summary.targets == 0`` while its results ingest later. The journal list\nrenders these so the row matches the run-detail drawer."},"RunStatus":{"type":"string","enum":["running","completed","interrupted"],"title":"RunStatus","description":"The lifecycle of a collection run.\n\n``running`` → ``completed`` on a clean close; ``interrupted`` is terminal and\nonly ever set by the next leader's run-lease sweep when the orchestrator that\nopened the run died mid-flight (an expired lease). ``interrupted`` runs are\nnever resumed."},"RunTrigger":{"type":"string","enum":["scheduled","on_demand"],"title":"RunTrigger","description":"What opened a collection run."},"ScheduleItem":{"properties":{"kind":{"$ref":"#/components/schemas/ScheduleItemKind"},"target_id":{"type":"string","format":"uuid","title":"Target Id"},"format":{"anyOf":[{"$ref":"#/components/schemas/app__modules__reports__contract__ExportFormat"},{"type":"null"}],"description":"Dataset serialization format (csv|xlsx). Omitted for a report (always PDF)."}},"additionalProperties":false,"type":"object","required":["kind","target_id"],"title":"ScheduleItem","description":"One thing to deliver: a report (→ PDF) or a raw-table dataset (→ CSV/XLSX)."},"ScheduleItemKind":{"type":"string","enum":["report","dataset"],"title":"ScheduleItemKind","description":"What a delivery item points at."},"ScheduleSendResult":{"properties":{"delivered":{"type":"boolean","title":"Delivered"},"recipients":{"type":"integer","title":"Recipients"},"attachments":{"items":{"type":"string"},"type":"array","title":"Attachments"},"batches":{"type":"integer","title":"Batches"},"skipped":{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array","title":"Skipped"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["delivered","recipients","attachments","batches","skipped"],"title":"ScheduleSendResult","description":"Outcome summary of an ad-hoc \"Send now\" (or a scheduled) delivery."},"ScpSettings":{"properties":{"kind":{"type":"string","const":"scp","title":"Kind","default":"scp"},"host_key_policy":{"$ref":"#/components/schemas/HostKeyPolicy","default":"trust_on_first_use"}},"additionalProperties":false,"type":"object","title":"ScpSettings","description":"SCP (file copy) transport settings — connection only.\n\nThe *what to fetch* (``remote_path``) lives on the ``kind=file`` recipe now (mirrors\nhttp, whose method/path live on the recipe), so this bag carries only the host-key\npolicy; host/port/credential come from the source's network object + port + credential."},"ScrubRuleCreate":{"properties":{"order":{"type":"integer","minimum":0.0,"title":"Order","description":"Application order within the set (ascending)"},"stage":{"$ref":"#/components/schemas/Stage","description":"drop_volatile | mask_secret | keep"},"pattern":{"type":"string","minLength":1,"title":"Pattern","description":"Regex pattern"},"replacement":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replacement","description":"Optional mask replacement (NULL → sentinel)"}},"additionalProperties":false,"type":"object","required":["order","stage","pattern"],"title":"ScrubRuleCreate","description":"A single scrub rule in a set (input)."},"ScrubRuleResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"order":{"type":"integer","title":"Order"},"stage":{"$ref":"#/components/schemas/Stage"},"pattern":{"type":"string","title":"Pattern"},"replacement":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Replacement"}},"type":"object","required":["id","order","stage","pattern"],"title":"ScrubRuleResponse","description":"A single scrub rule (output)."},"ScrubRuleSetClone":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name","description":"Name for the clone (defaults to '<orig> (copy)')"}},"additionalProperties":false,"type":"object","title":"ScrubRuleSetClone","description":"Optional body for cloning a scrub rule set — a new name for the copy."},"ScrubRuleSetCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Rule set name"},"rules":{"items":{"$ref":"#/components/schemas/ScrubRuleCreate"},"type":"array","title":"Rules","description":"Ordered scrub rules"}},"additionalProperties":false,"type":"object","required":["name"],"title":"ScrubRuleSetCreate","description":"Schema for creating a scrub rule set with its rules."},"ScrubRuleSetListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_system":{"type":"boolean","title":"Is System"},"rule_count":{"type":"integer","title":"Rule Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","is_system","created_at"],"title":"ScrubRuleSetListResponse","description":"Abbreviated rule set for list views."},"ScrubRuleSetResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_system":{"type":"boolean","title":"Is System"},"rules":{"items":{"$ref":"#/components/schemas/ScrubRuleResponse"},"type":"array","title":"Rules"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","is_system","created_at","updated_at"],"title":"ScrubRuleSetResponse","description":"Full rule set response (with rules)."},"ScrubRuleSetUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"rules":{"anyOf":[{"items":{"$ref":"#/components/schemas/ScrubRuleCreate"},"type":"array"},{"type":"null"}],"title":"Rules","description":"If provided, fully replaces the set's rules"}},"additionalProperties":false,"type":"object","title":"ScrubRuleSetUpdate","description":"Schema for updating a scrub rule set. Passing ``rules`` replaces them all."},"SearchTestResult":{"properties":{"status":{"type":"string","title":"Status"},"count":{"type":"integer","title":"Count","default":0},"search_bases_tested":{"items":{"type":"string"},"type":"array","title":"Search Bases Tested"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["status"],"title":"SearchTestResult","description":"Result of testing an LDAP search operation."},"SecretRevealResponse":{"properties":{"tacacs_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tacacs Key"},"radius_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Radius Secret"},"coa_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coa Secret"}},"type":"object","title":"SecretRevealResponse","description":"Response containing decrypted secret values."},"ServerCertExpiryInfo":{"properties":{"has_certificate":{"type":"boolean","title":"Has Certificate","default":false},"subject_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Dn"},"not_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not After"},"days_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Remaining"},"status":{"type":"string","title":"Status","default":"unknown"}},"type":"object","title":"ServerCertExpiryInfo","description":"Server certificate expiry information."},"ServerCertResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source":{"type":"string","title":"Source"},"is_active":{"type":"boolean","title":"Is Active"},"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"subject_dn":{"type":"string","title":"Subject Dn"},"not_before":{"type":"string","format":"date-time","title":"Not Before"},"not_after":{"type":"string","format":"date-time","title":"Not After"},"serial_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial Number"},"san_entries":{"anyOf":[{"items":{},"type":"array"},{"type":"null"}],"title":"San Entries"},"key_algorithm":{"type":"string","title":"Key Algorithm"},"issued_cert_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Issued Cert Id"},"deployed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deployed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","source","is_active","subject_dn","not_before","not_after","key_algorithm","created_at","updated_at"],"title":"ServerCertResponse","description":"Response schema for server certificate info."},"ServerCsrData":{"properties":{"common_name":{"type":"string","maxLength":255,"minLength":1,"title":"Common Name"},"organization":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organization"},"organizational_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organizational Unit"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Country"},"state":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"State"},"locality":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Locality"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Dns"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa2048"}},"type":"object","required":["common_name"],"title":"ServerCsrData","description":"Generate a CSR for the server certificate."},"ServerTestResult":{"properties":{"uri":{"type":"string","title":"Uri"},"status":{"type":"string","title":"Status"},"stage":{"type":"string","title":"Stage","description":"Furthest step reached: connect | tls | ok","default":"connect"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Stable machine-readable cause: unreachable, timeout, tls_client_certificate_required, tls_certificate_untrusted, tls_hostname_mismatch, tls_handshake_failed, tls_expired"},"response_time_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Time Ms"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["uri","status"],"title":"ServerTestResult","description":"Result of testing a single LDAP server.\n\n``stage`` and ``reason`` exist because \"Server ldaps://x: <exception>\" is\nwhere three days of a customer's time went: a directory that demands a\nclient certificate, one whose CA we do not trust, and one that is simply\nunreachable all arrived as the same red line of Python. The stage says WHICH\nstep failed, the reason is a stable code the UI turns into an instruction."},"ServiceConnectivity":{"properties":{"reachable":{"type":"boolean","title":"Reachable","default":false},"port":{"type":"integer","title":"Port","default":49},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","title":"ServiceConnectivity","description":"TCP connectivity check result."},"ServiceHealthCellResponse":{"properties":{"service":{"type":"string","title":"Service","description":"Daemon name: tacacs | radius | nac."},"status":{"type":"string","enum":["up","down","stale","unknown"],"title":"Status","description":"up/down = a fresh reachable/unreachable probe; stale = the last row aged past the freshness cutoff (or Patroni reports the node down) — not trusted as live; unknown = never reported."},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms","description":"Last probe latency; null when unknown."},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Last probe error detail; null when healthy/unknown."},"age_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Age Seconds","description":"Seconds since the last heartbeat write (primary clock, skew-free); null when never reported."},"checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Checked At","description":"When the reporting node observed this result."}},"type":"object","required":["service","status"],"title":"ServiceHealthCellResponse","description":"One (node, service) health verdict for the per-node dashboard matrix (§15.5)."},"ServiceStatusResponse":{"properties":{"timestamp":{"type":"string","title":"Timestamp"},"tacacs":{"$ref":"#/components/schemas/TacacsServiceStatus"},"radius":{"$ref":"#/components/schemas/RadiusServiceStatus"}},"type":"object","required":["timestamp","tacacs","radius"],"title":"ServiceStatusResponse","description":"Response for /monitoring/services endpoint."},"SettingResponse":{"properties":{"key":{"type":"string","title":"Key"},"value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Value"},"value_type":{"type":"string","title":"Value Type","default":"string"},"is_encrypted":{"type":"boolean","title":"Is Encrypted","default":false},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["key"],"title":"SettingResponse","description":"Schema for a single setting in API responses."},"SettingUpdate":{"properties":{"value":{"title":"Value","description":"Setting value (will be serialized based on value_type)"},"value_type":{"type":"string","enum":["string","int","bool","json"],"title":"Value Type","description":"Type hint: string, int, bool, json","default":"string"},"is_encrypted":{"type":"boolean","title":"Is Encrypted","description":"Whether the value should be encrypted","default":false},"description":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Description","description":"Human-readable description"}},"additionalProperties":false,"type":"object","required":["value"],"title":"SettingUpdate","description":"Schema for creating or updating a global setting."},"SftpSettings":{"properties":{"kind":{"type":"string","const":"sftp","title":"Kind","default":"sftp"},"host_key_policy":{"$ref":"#/components/schemas/HostKeyPolicy","default":"trust_on_first_use"}},"additionalProperties":false,"type":"object","title":"SftpSettings","description":"SFTP (file copy) transport settings — connection only.\n\nLike :class:`ScpSettings`, the ``remote_path`` moved to the ``kind=file`` recipe; this\nbag carries only the host-key policy."},"SideBySideRowResponse":{"properties":{"tag":{"type":"string","title":"Tag"},"left":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Left"},"right":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Right"},"left_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Left Lineno"},"right_lineno":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Right Lineno"}},"type":"object","required":["tag","left","right","left_lineno","right_lineno"],"title":"SideBySideRowResponse","description":"One aligned diff row."},"SmsSettingsResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"provider_type":{"type":"string","title":"Provider Type","default":"http_api"},"sender_name":{"type":"string","title":"Sender Name","default":"NAC Portal"},"message_template":{"type":"string","title":"Message Template","default":""},"http_url":{"type":"string","title":"Http Url","default":""},"http_method":{"type":"string","title":"Http Method","default":"POST"},"http_headers":{"anyOf":[{"additionalProperties":true,"type":"object"},{"items":{},"type":"array"},{"type":"string"}],"title":"Http Headers","default":""},"http_body_template":{"type":"string","title":"Http Body Template","default":""},"http_api_key":{"type":"string","title":"Http Api Key","default":""},"http_api_secret":{"type":"string","title":"Http Api Secret","default":""},"http_success_codes":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"string"}],"title":"Http Success Codes","default":""},"http_success_body_regex":{"type":"string","title":"Http Success Body Regex","default":""}},"type":"object","title":"SmsSettingsResponse","description":"Full SMS settings document returned by GET.\n\nEncrypted values (http_api_key, http_api_secret) are masked as '***'."},"SmsSettingsUpdate":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"provider_type":{"anyOf":[{"type":"string","enum":["http_api","smpp"]},{"type":"null"}],"title":"Provider Type"},"sender_name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Sender Name"},"message_template":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Message Template"},"http_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Http Url"},"http_method":{"anyOf":[{"type":"string","enum":["POST","GET"]},{"type":"null"}],"title":"Http Method"},"http_headers":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Http Headers"},"http_body_template":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Http Body Template"},"http_api_key":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Http Api Key"},"http_api_secret":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Http Api Secret"},"http_success_codes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Http Success Codes"},"http_success_body_regex":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"Http Success Body Regex"}},"type":"object","title":"SmsSettingsUpdate","description":"Partial update for SMS settings.\n\nOnly the fields present in the request body will be updated.\nOmitted fields remain unchanged in the database."},"SmsTestRequest":{"properties":{"phone":{"type":"string","maxLength":32,"minLength":3,"title":"Phone"},"message":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Message","description":"Custom message text. If omitted, a default test message is sent."}},"additionalProperties":false,"type":"object","required":["phone"],"title":"SmsTestRequest","description":"Request body for the SMS test endpoint.\n\nA discrete admin request (the settings card posts exactly ``{phone}``), so\n``extra=\"forbid\"`` is safe here — unlike the document-style settings PATCH."},"SmsTestResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"http_status_code":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Http Status Code"},"provider_response":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Response"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["success"],"title":"SmsTestResponse","description":"Response from the SMS test endpoint with full provider details."},"SmtpSettingsResponse":{"properties":{"host":{"type":"string","title":"Host","default":""},"port":{"type":"integer","title":"Port","default":587},"username":{"type":"string","title":"Username","default":""},"password":{"type":"string","title":"Password","default":""},"from_email":{"type":"string","title":"From Email","default":""},"from_name":{"type":"string","title":"From Name","default":""},"base_url":{"type":"string","title":"Base Url","default":""},"use_tls":{"type":"boolean","title":"Use Tls","default":true},"use_ssl":{"type":"boolean","title":"Use Ssl","default":false},"timeout":{"type":"integer","title":"Timeout","default":30},"enabled":{"type":"boolean","title":"Enabled","default":false},"auth_enabled":{"type":"boolean","title":"Auth Enabled","default":true}},"type":"object","title":"SmtpSettingsResponse","description":"GET /email/smtp response — flat typed document."},"SmtpSettingsUpdateRequest":{"properties":{"host":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Host"},"port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Port"},"username":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Username"},"password":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Password"},"from_email":{"anyOf":[{"type":"string","maxLength":254,"format":"email"},{"type":"null"}],"title":"From Email"},"from_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"From Name"},"base_url":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Base Url"},"use_tls":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Tls"},"use_ssl":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Use Ssl"},"timeout":{"anyOf":[{"type":"integer","maximum":300.0,"minimum":1.0},{"type":"null"}],"title":"Timeout"},"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"auth_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auth Enabled"}},"additionalProperties":false,"type":"object","title":"SmtpSettingsUpdateRequest","description":"PUT /email/smtp request body — partial update, only provided fields are saved."},"SnapshotDiffResponse":{"properties":{"from_snapshot_id":{"type":"string","format":"uuid","title":"From Snapshot Id"},"to_snapshot_id":{"type":"string","format":"uuid","title":"To Snapshot Id"},"is_binary":{"type":"boolean","title":"Is Binary"},"changed":{"type":"boolean","title":"Changed"},"unified":{"type":"string","title":"Unified"},"side_by_side":{"items":{"$ref":"#/components/schemas/SideBySideRowResponse"},"type":"array","title":"Side By Side"},"render_mode":{"type":"string","title":"Render Mode","default":"full"},"before_lines":{"type":"integer","title":"Before Lines","default":0},"after_lines":{"type":"integer","title":"After Lines","default":0}},"type":"object","required":["from_snapshot_id","to_snapshot_id","is_binary","changed","unified"],"title":"SnapshotDiffResponse","description":"Rendered diff between two snapshots (binary → is_binary, no rows).\n\n``render_mode`` says how much was rendered given the config's size:\n``full`` (unified + side-by-side), ``unified_only`` (too big for side-by-side),\nor ``too_large`` (no inline diff — the UI offers raw/download instead).\n``before_lines``/``after_lines`` let the UI state the size in its message."},"SnapshotListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tracked_config_id":{"type":"string","format":"uuid","title":"Tracked Config Id"},"version_no":{"type":"integer","title":"Version No","description":"Per-config positional version number (1=oldest … N=newest) — the friendly v{n} in the UI"},"content_kind":{"$ref":"#/components/schemas/ContentKind"},"oversized":{"type":"boolean","title":"Oversized","description":"Text past the store threshold — no body stored; tracked by content_hash alone","default":false},"content_hash":{"type":"string","title":"Content Hash"},"secret_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret Fingerprint"},"size_bytes":{"type":"integer","title":"Size Bytes"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"},"run_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Run Id"},"attribution":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Attribution","description":"Denormalized AAA 'who changed what' summary stored at capture time"},"labels":{"items":{"$ref":"#/components/schemas/VersionLabelResponse"},"type":"array","title":"Labels","description":"Labels on this snapshot (pin/baseline/golden/approved role anchors + an optional user tag)"},"has_raw_body":{"type":"boolean","title":"Has Raw Body","description":"Whether an encrypted raw body was captured (reveal is gated)"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","tracked_config_id","version_no","content_kind","content_hash","size_bytes","captured_at","has_raw_body","created_at"],"title":"SnapshotListResponse","description":"Abbreviated snapshot for timeline/list views (never carries body or blob).\n\nCarries the stored ``attribution`` summary and the snapshot's ``labels`` so the FE\ntimeline renders who-changed-it avatars + pin/baseline/golden/approved badges from\none paginated call — without N+1-fetching each snapshot's full body + labels."},"SnapshotRawRevealResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tracked_config_id":{"type":"string","format":"uuid","title":"Tracked Config Id"},"raw_body":{"type":"string","title":"Raw Body"}},"type":"object","required":["id","tracked_config_id","raw_body"],"title":"SnapshotRawRevealResponse","description":"The decrypted raw (unscrubbed) body — high-privilege, audited."},"SnapshotResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"tracked_config_id":{"type":"string","format":"uuid","title":"Tracked Config Id"},"content_kind":{"$ref":"#/components/schemas/ContentKind"},"body":{"type":"string","title":"Body"},"oversized":{"type":"boolean","title":"Oversized","description":"Text past the configured store threshold: the body was NOT stored (it is empty here) and the version is tracked by content_hash alone. size_bytes still reports the real size.","default":false},"content_hash":{"type":"string","title":"Content Hash"},"secret_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secret Fingerprint"},"size_bytes":{"type":"integer","title":"Size Bytes"},"captured_at":{"type":"string","format":"date-time","title":"Captured At"},"run_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Run Id"},"attribution":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Attribution"},"has_raw_body":{"type":"boolean","title":"Has Raw Body","description":"Whether an encrypted raw body was captured (reveal is gated)"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","tracked_config_id","content_kind","body","content_hash","size_bytes","captured_at","has_raw_body","created_at","updated_at"],"title":"SnapshotResponse","description":"Full snapshot response — the scrubbed body for text, empty for binary.\n\nNever returns ``raw_body`` (the encrypted unscrubbed capture) — that is a separate,\nRBAC-gated reveal. Never returns blob bytes — those come from the download path."},"SortCapabilitySummary":{"properties":{"columns":{"items":{"type":"string"},"type":"array","title":"Columns"},"default_column":{"type":"string","title":"Default Column"},"default_direction":{"$ref":"#/components/schemas/SortOrder"},"direction_choosable":{"type":"boolean","title":"Direction Choosable"}},"type":"object","required":["columns","default_column","default_direction","direction_choosable"],"title":"SortCapabilitySummary","description":"Ordering control (raw table only) — the column whitelist + defaults."},"SortOrder":{"type":"string","enum":["asc","desc"],"title":"SortOrder","description":"Sort direction."},"SshSettings":{"properties":{"kind":{"type":"string","const":"ssh","title":"Kind","default":"ssh"},"no_exec":{"type":"boolean","title":"No Exec","description":"Use an interactive shell instead of exec channels.","default":false},"paging_cmd":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Paging Cmd","description":"Command to disable paging."},"host_key_policy":{"$ref":"#/components/schemas/HostKeyPolicy","default":"trust_on_first_use"},"device_type":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Device Type","description":"Netmiko device_type override (e.g. 'linux'); empty ⇒ platform default (cisco_ios)."}},"additionalProperties":false,"type":"object","title":"SshSettings","description":"SSH transport settings."},"Stage":{"type":"string","enum":["drop_volatile","mask_secret","keep"],"title":"Stage","description":"Scrub rule stage."},"SupportStatus":{"properties":{"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At","description":"UTC; null = no active support window."},"level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Level"},"active":{"type":"boolean","title":"Active","description":"False once expires_at has passed — a warning only, disables nothing."}},"type":"object","required":["active"],"title":"SupportStatus"},"SupportedLocalesResponse":{"properties":{"supported_locales":{"items":{"type":"string"},"type":"array","title":"Supported Locales","description":"Locale codes offered for the UI language picker (from SUPPORTED_LOCALES env)"}},"type":"object","required":["supported_locales"],"title":"SupportedLocalesResponse","description":"GET /auth/locales response — the UI languages this deployment offers."},"SwapMetrics":{"properties":{"total_bytes":{"type":"integer","title":"Total Bytes"},"used_bytes":{"type":"integer","title":"Used Bytes"},"free_bytes":{"type":"integer","title":"Free Bytes"},"percent":{"type":"number","title":"Percent"},"total_human":{"type":"string","title":"Total Human"},"used_human":{"type":"string","title":"Used Human"}},"type":"object","required":["total_bytes","used_bytes","free_bytes","percent","total_human","used_human"],"title":"SwapMetrics","description":"Swap metric snapshot."},"SyncLogResponse":{"properties":{"id":{"type":"string","title":"Id"},"config_id":{"type":"string","title":"Config Id"},"status":{"type":"string","title":"Status"},"sync_mode":{"type":"string","title":"Sync Mode"},"users_created":{"type":"integer","title":"Users Created","default":0},"users_updated":{"type":"integer","title":"Users Updated","default":0},"users_disabled":{"type":"integer","title":"Users Disabled","default":0},"users_deleted":{"type":"integer","title":"Users Deleted","default":0},"groups_created":{"type":"integer","title":"Groups Created","default":0},"groups_updated":{"type":"integer","title":"Groups Updated","default":0},"endpoints_created":{"type":"integer","title":"Endpoints Created","default":0},"endpoints_updated":{"type":"integer","title":"Endpoints Updated","default":0},"endpoints_deactivated":{"type":"integer","title":"Endpoints Deactivated","default":0},"endpoints_deleted":{"type":"integer","title":"Endpoints Deleted","default":0},"pending_created":{"type":"integer","title":"Pending Created","default":0},"pending_updated":{"type":"integer","title":"Pending Updated","default":0},"errors":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Errors"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Duration Seconds"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","config_id","status","sync_mode","started_at"],"title":"SyncLogResponse","description":"Schema for a single LDAP sync log entry."},"SyncPreviewResponse":{"properties":{"groups_to_create":{"items":{"$ref":"#/components/schemas/PreviewGroupCreate"},"type":"array","title":"Groups To Create"},"groups_to_update":{"items":{"$ref":"#/components/schemas/PreviewGroupUpdate"},"type":"array","title":"Groups To Update"},"users_to_create":{"items":{"$ref":"#/components/schemas/PreviewUserCreate"},"type":"array","title":"Users To Create"},"users_to_update":{"items":{"$ref":"#/components/schemas/PreviewUserUpdate"},"type":"array","title":"Users To Update"},"users_to_disable":{"items":{"$ref":"#/components/schemas/PreviewUserDisable"},"type":"array","title":"Users To Disable"},"users_to_delete":{"items":{"$ref":"#/components/schemas/PreviewUserDelete"},"type":"array","title":"Users To Delete"},"conflicts":{"items":{"$ref":"#/components/schemas/PreviewConflict"},"type":"array","title":"Conflicts"},"summary":{"$ref":"#/components/schemas/PreviewSummary"}},"type":"object","title":"SyncPreviewResponse","description":"Response from the LDAP preview (dry run) endpoint."},"SyncStartResponse":{"properties":{"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"},"sync_log_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sync Log Id"}},"type":"object","required":["status","message"],"title":"SyncStartResponse","description":"Response after starting a sync."},"SyncTriggerRequest":{"properties":{"sync_mode":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Sync Mode","description":"Override sync mode for this run"}},"additionalProperties":false,"type":"object","title":"SyncTriggerRequest","description":"Request body for triggering a sync (optional overrides)."},"SyslogDestinationCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"host":{"type":"string","maxLength":255,"minLength":1,"title":"Host"},"port":{"type":"integer","maximum":65535.0,"minimum":1.0,"title":"Port","default":514},"transport":{"type":"string","enum":["udp","tcp"],"title":"Transport","default":"udp"},"tls_ca_cert":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Ca Cert"},"tls_client_cert":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Client Cert"},"tls_client_key":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Client Key"},"tls_verify":{"type":"boolean","title":"Tls Verify","default":true},"format":{"type":"string","enum":["RFC3164","RFC5424","CEF"],"title":"Format","default":"RFC3164"},"facility":{"type":"string","enum":["kern","user","mail","daemon","auth","syslog","lpr","news","local0","local1","local2","local3","local4","local5","local6","local7"],"title":"Facility","default":"local6"},"severity":{"type":"string","enum":["emerg","alert","crit","err","warning","notice","info","debug"],"title":"Severity","default":"info"},"ident":{"type":"string","maxLength":32,"minLength":1,"title":"Ident","default":"taranac"},"source_spoofing":{"type":"boolean","title":"Source Spoofing","default":false},"is_enabled":{"type":"boolean","title":"Is Enabled","default":true}},"additionalProperties":false,"type":"object","required":["name","host"],"title":"SyslogDestinationCreate","description":"Schema for creating a new syslog destination."},"SyslogDestinationListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"host":{"type":"string","title":"Host"},"port":{"type":"integer","title":"Port"},"transport":{"type":"string","title":"Transport"},"format":{"type":"string","title":"Format"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"bindings_count":{"type":"integer","title":"Bindings Count","default":0},"last_delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Delivered At"},"consecutive_failure_count":{"type":"integer","title":"Consecutive Failure Count","default":0},"dropped_record_count":{"type":"integer","title":"Dropped Record Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","host","port","transport","format","is_enabled","created_at"],"title":"SyslogDestinationListResponse","description":"Abbreviated syslog destination for list views."},"SyslogDestinationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"host":{"type":"string","title":"Host"},"port":{"type":"integer","title":"Port"},"transport":{"type":"string","title":"Transport"},"tls_ca_cert":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tls Ca Cert"},"tls_client_cert":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tls Client Cert"},"tls_client_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tls Client Key"},"tls_verify":{"type":"boolean","title":"Tls Verify"},"format":{"type":"string","title":"Format"},"facility":{"type":"string","title":"Facility"},"severity":{"type":"string","title":"Severity"},"ident":{"type":"string","title":"Ident"},"source_spoofing":{"type":"boolean","title":"Source Spoofing"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"last_delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Delivered At"},"consecutive_failure_count":{"type":"integer","title":"Consecutive Failure Count","default":0},"dropped_record_count":{"type":"integer","title":"Dropped Record Count","default":0},"bindings":{"items":{"$ref":"#/components/schemas/LogBindingResponse"},"type":"array","title":"Bindings"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","host","port","transport","tls_verify","format","facility","severity","ident","source_spoofing","is_enabled","created_at","updated_at"],"title":"SyslogDestinationResponse","description":"Full syslog destination response with bindings."},"SyslogDestinationUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"host":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Host"},"port":{"anyOf":[{"type":"integer","maximum":65535.0,"minimum":1.0},{"type":"null"}],"title":"Port"},"transport":{"anyOf":[{"type":"string","enum":["udp","tcp"]},{"type":"null"}],"title":"Transport"},"tls_ca_cert":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Ca Cert"},"tls_client_cert":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Client Cert"},"tls_client_key":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Client Key"},"tls_verify":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Tls Verify"},"format":{"anyOf":[{"type":"string","enum":["RFC3164","RFC5424","CEF"]},{"type":"null"}],"title":"Format"},"facility":{"anyOf":[{"type":"string","enum":["kern","user","mail","daemon","auth","syslog","lpr","news","local0","local1","local2","local3","local4","local5","local6","local7"]},{"type":"null"}],"title":"Facility"},"severity":{"anyOf":[{"type":"string","enum":["emerg","alert","crit","err","warning","notice","info","debug"]},{"type":"null"}],"title":"Severity"},"ident":{"anyOf":[{"type":"string","maxLength":32,"minLength":1},{"type":"null"}],"title":"Ident"},"source_spoofing":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Source Spoofing"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"}},"additionalProperties":false,"type":"object","title":"SyslogDestinationUpdate","description":"Schema for updating a syslog destination. All fields optional."},"SyslogTestRequest":{"properties":{"message":{"type":"string","maxLength":1024,"minLength":1,"title":"Message","description":"Custom test message content","default":"taranac test message"}},"additionalProperties":false,"type":"object","title":"SyslogTestRequest","description":"Request to send a test syslog message."},"SyslogTestResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["success","detail"],"title":"SyslogTestResponse","description":"Response from test syslog send."},"SystemInfoResponse":{"properties":{"version":{"type":"string","title":"Version","description":"Backend package version"},"server_time":{"type":"string","format":"date-time","title":"Server Time","description":"Current server time (UTC)"},"timezone":{"type":"string","title":"Timezone","description":"System IANA timezone (system.timezone)"},"started_at":{"type":"string","format":"date-time","title":"Started At","description":"Process start time (UTC)"},"uptime_seconds":{"type":"integer","title":"Uptime Seconds","description":"Seconds since process start"},"alembic_head":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alembic Head","description":"Current Alembic revision from the alembic_version table"}},"type":"object","required":["version","server_time","timezone","started_at","uptime_seconds"],"title":"SystemInfoResponse","description":"Backend runtime metadata for the system-info widget.\n\nAll timestamps are UTC. ``server_time`` lets the frontend compute a\nclient/server clock offset once and tick a live clock locally without\nre-polling."},"TacacsAcctLogListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"action":{"type":"string","title":"Action"},"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Id"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service"},"command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","action"],"title":"TacacsAcctLogListResponse","description":"Abbreviated TACACS+ acct log for list views."},"TacacsAcctLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line"},"rem_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rem Addr"},"action":{"type":"string","title":"Action"},"task_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Task Id"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service"},"priv_lvl":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Priv Lvl"},"command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command"},"elapsed_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Elapsed Time"},"disc_cause":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Disc Cause"},"disc_cause_ext":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Disc Cause Ext"},"pre_session_time":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pre Session Time"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"stop_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stop Time"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"server":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Server"},"raw_line":{"type":"string","title":"Raw Line"},"unknown_fields":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unknown Fields"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","action","raw_line","created_at"],"title":"TacacsAcctLogResponse","description":"TACACS+ accounting log entry response."},"TacacsAuthnLogListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line"},"rem_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rem Addr"},"action":{"type":"string","title":"Action"},"status":{"type":"string","title":"Status"},"profile":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"rule_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Name"},"rule_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Label"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","action","status"],"title":"TacacsAuthnLogListResponse","description":"Abbreviated TACACS+ authn log for list views."},"TacacsAuthnLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line"},"rem_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rem Addr"},"action":{"type":"string","title":"Action"},"status":{"type":"string","title":"Status"},"profile":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"server":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Server"},"rule_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Name"},"rule_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Label"},"policy_rule_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Policy Rule Id"},"raw_line":{"type":"string","title":"Raw Line"},"unknown_fields":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unknown Fields"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","action","status","raw_line","created_at"],"title":"TacacsAuthnLogResponse","description":"TACACS+ authentication log entry response."},"TacacsAuthzLogListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"action":{"type":"string","title":"Action"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service"},"command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command"},"profile":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"rule_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Name"},"rule_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Label"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","action"],"title":"TacacsAuthzLogListResponse","description":"Abbreviated TACACS+ authz log for list views."},"TacacsAuthzLogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"nas_ip":{"type":"string","title":"Nas Ip"},"username":{"type":"string","title":"Username"},"line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Line"},"rem_addr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rem Addr"},"profile":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile"},"action":{"type":"string","title":"Action"},"service":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service"},"command":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Command"},"device_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Device Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"server":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Server"},"rule_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Name"},"rule_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rule Label"},"policy_rule_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Policy Rule Id"},"rule_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rule Order"},"raw_line":{"type":"string","title":"Raw Line"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"device_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Name"},"device_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Group Names"},"network_object_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Name"},"network_object_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Network Object Type"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name"},"user_group_names":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Group Names"},"node_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Node Id"},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name"}},"type":"object","required":["id","timestamp","nas_ip","username","action","raw_line","created_at"],"title":"TacacsAuthzLogResponse","description":"TACACS+ authorization log entry response."},"TacacsCsrResult":{"properties":{"csr_pem":{"type":"string","title":"Csr Pem"},"private_key_id":{"type":"string","format":"uuid","title":"Private Key Id","description":"Reference to stored private key for later cert import"}},"type":"object","required":["csr_pem","private_key_id"],"title":"TacacsCsrResult","description":"Response from CSR generation."},"TacacsGenerateSelfSigned":{"properties":{"common_name":{"type":"string","maxLength":255,"minLength":1,"title":"Common Name","default":"taranac-tacacs"},"organization":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organization","default":"taranac"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Country"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"San Dns"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa2048"},"validity_days":{"type":"integer","maximum":7300.0,"minimum":1.0,"title":"Validity Days","default":3650}},"type":"object","title":"TacacsGenerateSelfSigned","description":"Generate a new self-signed server certificate."},"TacacsIssueServerCert":{"properties":{"ca_id":{"type":"string","format":"uuid","title":"Ca Id","description":"Internal CA to issue from"},"common_name":{"type":"string","maxLength":255,"minLength":1,"title":"Common Name"},"organization":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organization"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Country"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Dns"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa2048"},"validity_days":{"type":"integer","maximum":3650.0,"minimum":1.0,"title":"Validity Days","default":730}},"type":"object","required":["ca_id","common_name"],"title":"TacacsIssueServerCert","description":"Issue a server certificate from an internal CA."},"TacacsProfileCreate":{"properties":{"name":{"type":"string","maxLength":64,"minLength":1,"title":"Name","description":"Unique profile name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"template_id":{"type":"string","format":"uuid","title":"Template Id","description":"FK to TacacsTemplate"},"service_values":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Service Values","description":"Filled AV-pairs per service: {service_name: {attr: value}}"},"raw_attributes":{"items":{"$ref":"#/components/schemas/RawAttribute"},"type":"array","maxItems":256,"title":"Raw Attributes","description":"Additional AV-pairs not covered by the template"},"command_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Command Set Id","description":"Optional FK to CommandSet"},"default_command_action":{"anyOf":[{"type":"string","enum":["permit","deny"]},{"type":"null"}],"title":"Default Command Action"},"enable":{"anyOf":[{"$ref":"#/components/schemas/EnableConfig"},{"type":"null"}]},"motd":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Motd"},"session_timeout":{"anyOf":[{"type":"integer","maximum":604800.0,"minimum":0.0},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer","maximum":604800.0,"minimum":0.0},{"type":"null"}],"title":"Idle Timeout"}},"additionalProperties":false,"type":"object","required":["name","template_id"],"title":"TacacsProfileCreate","description":"Schema for creating a TACACS+ profile."},"TacacsProfileListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"template":{"$ref":"#/components/schemas/TacacsTemplateBrief"},"command_set":{"anyOf":[{"$ref":"#/components/schemas/CommandSetBrief"},{"type":"null"}]},"has_enable":{"type":"boolean","title":"Has Enable","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","template","created_at"],"title":"TacacsProfileListResponse","description":"Abbreviated profile for list views."},"TacacsProfileResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"template_id":{"type":"string","format":"uuid","title":"Template Id"},"template":{"$ref":"#/components/schemas/TacacsTemplateBrief"},"service_values":{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object","title":"Service Values"},"raw_attributes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Raw Attributes"},"command_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Command Set Id"},"command_set":{"anyOf":[{"$ref":"#/components/schemas/CommandSetBrief"},{"type":"null"}]},"default_command_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Command Action"},"enable":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Enable"},"motd":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Motd"},"session_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Idle Timeout"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"template_detail":{"anyOf":[{"$ref":"#/components/schemas/TacacsTemplateResponse"},{"type":"null"}]},"command_set_detail":{"anyOf":[{"$ref":"#/components/schemas/CommandSetResponse"},{"type":"null"}]}},"type":"object","required":["id","name","template_id","template","service_values","created_at","updated_at"],"title":"TacacsProfileResponse","description":"Full profile response. Enable password shows sentinel if set."},"TacacsProfileUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"service_values":{"anyOf":[{"additionalProperties":{"additionalProperties":true,"type":"object"},"type":"object"},{"type":"null"}],"title":"Service Values"},"raw_attributes":{"anyOf":[{"items":{"$ref":"#/components/schemas/RawAttribute"},"type":"array","maxItems":256},{"type":"null"}],"title":"Raw Attributes"},"command_set_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Command Set Id"},"default_command_action":{"anyOf":[{"type":"string","enum":["permit","deny"]},{"type":"null"}],"title":"Default Command Action"},"enable":{"anyOf":[{"$ref":"#/components/schemas/EnableConfig"},{"type":"null"}]},"motd":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Motd"},"session_timeout":{"anyOf":[{"type":"integer","maximum":604800.0,"minimum":0.0},{"type":"null"}],"title":"Session Timeout"},"idle_timeout":{"anyOf":[{"type":"integer","maximum":604800.0,"minimum":0.0},{"type":"null"}],"title":"Idle Timeout"}},"additionalProperties":false,"type":"object","title":"TacacsProfileUpdate","description":"Schema for updating a TACACS+ profile.\n\nEnable password sentinel logic:\n- sentinel (\"••••••••\") = keep current password\n- empty string (\"\") = clear the password\n- any other value = encrypt and save"},"TacacsServerCertExpiryInfo":{"properties":{"has_certificate":{"type":"boolean","title":"Has Certificate","default":false},"subject_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject Dn"},"not_after":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Not After"},"days_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Remaining"},"status":{"type":"string","title":"Status","default":"unknown"}},"type":"object","title":"TacacsServerCertExpiryInfo","description":"Server certificate expiry information."},"TacacsServerCertResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source":{"type":"string","title":"Source"},"is_active":{"type":"boolean","title":"Is Active"},"issuer_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Issuer Dn"},"subject_dn":{"type":"string","title":"Subject Dn"},"not_before":{"type":"string","format":"date-time","title":"Not Before"},"not_after":{"type":"string","format":"date-time","title":"Not After"},"serial_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Serial Number"},"san_entries":{"anyOf":[{"items":{"additionalProperties":{"type":"string"},"type":"object"},"type":"array"},{"type":"null"}],"title":"San Entries"},"key_algorithm":{"type":"string","title":"Key Algorithm"},"issued_cert_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Issued Cert Id"},"deployed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Deployed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","source","is_active","subject_dn","not_before","not_after","key_algorithm","created_at","updated_at"],"title":"TacacsServerCertResponse","description":"Response schema for TACACS+ server certificate info."},"TacacsServerCsrData":{"properties":{"common_name":{"type":"string","maxLength":255,"minLength":1,"title":"Common Name"},"organization":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organization"},"organizational_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Organizational Unit"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2},{"type":"null"}],"title":"Country"},"state":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"State"},"locality":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Locality"},"san_dns":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"San Dns"},"key_algorithm":{"type":"string","enum":["rsa2048","rsa4096","ec256","ec384"],"title":"Key Algorithm","default":"rsa2048"}},"type":"object","required":["common_name"],"title":"TacacsServerCsrData","description":"Generate a CSR for the TACACS+ server certificate."},"TacacsServiceStatus":{"properties":{"service":{"type":"string","title":"Service","default":"tac_plus-ng"},"port":{"type":"integer","title":"Port","default":49},"reachable":{"type":"boolean","title":"Reachable","default":false},"response_time_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Response Time Ms"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"config":{"$ref":"#/components/schemas/ConfigFileStatus"}},"type":"object","title":"TacacsServiceStatus","description":"TACACS+ service status."},"TacacsSettingsResponse":{"properties":{"port":{"type":"integer","title":"Port","default":49},"tls_port":{"type":"integer","title":"Tls Port","default":6049},"global_key":{"type":"string","title":"Global Key","default":""},"single_connection":{"type":"boolean","title":"Single Connection","default":false},"connection_timeout":{"type":"integer","title":"Connection Timeout","default":600},"password_max_attempts":{"type":"integer","title":"Password Max Attempts","default":1},"anonymous_enable":{"type":"string","title":"Anonymous Enable","default":"permit"},"pap_password_mapping":{"type":"string","title":"Pap Password Mapping","default":"pap"},"spawnd_min_instances":{"type":"integer","title":"Spawnd Min Instances","default":4},"spawnd_max_instances":{"type":"integer","title":"Spawnd Max Instances","default":32},"mavis_cache_timeout":{"type":"integer","title":"Mavis Cache Timeout","default":0},"auth_cache_ttl":{"type":"integer","title":"Auth Cache Ttl","default":60},"cache_refresh_interval":{"type":"integer","title":"Cache Refresh Interval","default":30},"console_pattern":{"type":"string","title":"Console Pattern","default":"^(con|console|tty)\\d*$"},"bruteforce_enabled":{"type":"boolean","title":"Bruteforce Enabled","default":true},"bruteforce_threshold":{"type":"integer","title":"Bruteforce Threshold","default":10},"bruteforce_window_minutes":{"type":"integer","title":"Bruteforce Window Minutes","default":15},"log_file_backup_enabled":{"type":"boolean","title":"Log File Backup Enabled","default":true},"log_retention_days":{"type":"integer","title":"Log Retention Days","default":365},"parser_batch_size":{"type":"integer","title":"Parser Batch Size","default":100},"parser_flush_interval":{"type":"string","title":"Parser Flush Interval","default":"0.5"},"tls_enabled":{"type":"boolean","title":"Tls Enabled","default":false},"tls_cert":{"type":"string","title":"Tls Cert","default":""},"tls_key":{"type":"string","title":"Tls Key","default":""},"tls_ca":{"type":"string","title":"Tls Ca","default":""},"mfa_mode":{"type":"string","title":"Mfa Mode","default":"enabled"},"mfa_prompt":{"type":"string","title":"Mfa Prompt","default":"Password: "},"auto_reload_enabled":{"type":"boolean","title":"Auto Reload Enabled","default":true},"auto_reload_interval":{"type":"integer","title":"Auto Reload Interval","default":30},"debug_enabled":{"type":"boolean","title":"Debug Enabled","default":false},"global_enable_mode":{"type":"string","title":"Global Enable Mode","default":"login_password"},"global_enable_password":{"type":"string","title":"Global Enable Password","default":""}},"type":"object","title":"TacacsSettingsResponse","description":"Full TACACS+ settings document returned by GET.\n\nEncrypted values (e.g. global_key) are masked as '***'.\nInternal fields are not included in the response.\nPort fields are read-only (sourced from environment variables)."},"TacacsSettingsUpdate":{"properties":{"global_key":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Global Key"},"single_connection":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Single Connection"},"connection_timeout":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Connection Timeout"},"password_max_attempts":{"anyOf":[{"type":"integer","maximum":10.0,"minimum":1.0},{"type":"null"}],"title":"Password Max Attempts"},"anonymous_enable":{"anyOf":[{"type":"string","enum":["permit","deny"]},{"type":"null"}],"title":"Anonymous Enable"},"pap_password_mapping":{"anyOf":[{"type":"string","enum":["pap","login"]},{"type":"null"}],"title":"Pap Password Mapping"},"spawnd_min_instances":{"anyOf":[{"type":"integer","maximum":256.0,"minimum":1.0},{"type":"null"}],"title":"Spawnd Min Instances"},"spawnd_max_instances":{"anyOf":[{"type":"integer","maximum":1024.0,"minimum":1.0},{"type":"null"}],"title":"Spawnd Max Instances"},"mavis_cache_timeout":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Mavis Cache Timeout"},"auth_cache_ttl":{"anyOf":[{"type":"integer","maximum":86400.0,"minimum":0.0},{"type":"null"}],"title":"Auth Cache Ttl"},"cache_refresh_interval":{"anyOf":[{"type":"integer","maximum":300.0,"minimum":5.0},{"type":"null"}],"title":"Cache Refresh Interval"},"console_pattern":{"anyOf":[{"type":"string","maxLength":256,"minLength":1},{"type":"null"}],"title":"Console Pattern"},"bruteforce_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Bruteforce Enabled"},"bruteforce_threshold":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Threshold"},"bruteforce_window_minutes":{"anyOf":[{"type":"integer","maximum":1440.0,"minimum":1.0},{"type":"null"}],"title":"Bruteforce Window Minutes"},"log_file_backup_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Log File Backup Enabled"},"log_retention_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Log Retention Days"},"parser_batch_size":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Parser Batch Size"},"parser_flush_interval":{"anyOf":[{"type":"string","maxLength":10,"minLength":1},{"type":"null"}],"title":"Parser Flush Interval"},"tls_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Tls Enabled"},"tls_cert":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Cert"},"tls_key":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Key"},"tls_ca":{"anyOf":[{"type":"string","maxLength":16384},{"type":"null"}],"title":"Tls Ca"},"mfa_mode":{"anyOf":[{"type":"string","enum":["disabled","enabled"]},{"type":"null"}],"title":"Mfa Mode"},"mfa_prompt":{"anyOf":[{"type":"string","maxLength":256,"minLength":1},{"type":"null"}],"title":"Mfa Prompt"},"auto_reload_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Reload Enabled"},"auto_reload_interval":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":10.0},{"type":"null"}],"title":"Auto Reload Interval"},"debug_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Debug Enabled"},"global_enable_mode":{"anyOf":[{"type":"string","enum":["login_password","custom","deny"]},{"type":"null"}],"title":"Global Enable Mode"},"global_enable_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Global Enable Password"}},"type":"object","title":"TacacsSettingsUpdate","description":"Partial update for TACACS+ settings.\n\nOnly the fields present in the request body will be updated.\nOmitted fields remain unchanged in the database.\nPort fields and internal fields are not accepted.\n\nNOTE: this is a document-style flat-settings PATCH. The settings page renders\nthe read-only ENV-sourced ``port`` / ``tls_port`` as badges (they live in the\nresponse but not here), so the form deliberately treats them as read-only and\nnever PATCHes them. We DELIBERATELY do NOT set ``extra=\"forbid\"`` here: a\nsettings document is exactly the case the validation guideline flags — a stray\nor read-only key in the body must not 422 a settings save. Every field stays\nbounded (and enum-ish ones use a Literal whitelist) regardless."},"TacacsStatusResponse":{"properties":{"service":{"$ref":"#/components/schemas/ServiceConnectivity"},"config":{"$ref":"#/components/schemas/ConfigStatusInfo"}},"type":"object","required":["service","config"],"title":"TacacsStatusResponse","description":"Response for GET /tacacs/status."},"TacacsTemplateBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"vendor":{"type":"string","title":"Vendor"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"}},"type":"object","required":["id","name","vendor"],"title":"TacacsTemplateBrief","description":"Minimal template info embedded in profile responses."},"TacacsTemplateCreate":{"properties":{"name":{"type":"string","maxLength":64,"minLength":1,"title":"Name","description":"Unique template name"},"vendor":{"type":"string","maxLength":64,"minLength":1,"title":"Vendor"},"platform":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Platform"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"data":{"$ref":"#/components/schemas/TemplateData","description":"Template structure"},"raw_yaml":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Raw Yaml","description":"Original YAML for re-export"}},"additionalProperties":false,"type":"object","required":["name","vendor","data"],"title":"TacacsTemplateCreate","description":"Schema for creating a template via direct JSON payload."},"TacacsTemplateListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"vendor":{"type":"string","title":"Vendor"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"supports_command_auth":{"type":"boolean","title":"Supports Command Auth","default":false},"service_count":{"type":"integer","title":"Service Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","vendor","created_at"],"title":"TacacsTemplateListResponse","description":"Abbreviated template for list views (without data/raw_yaml)."},"TacacsTemplateResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"vendor":{"type":"string","title":"Vendor"},"platform":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"data":{"additionalProperties":true,"type":"object","title":"Data"},"raw_yaml":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Raw Yaml"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","vendor","data","created_at","updated_at"],"title":"TacacsTemplateResponse","description":"Full template response."},"TacacsTemplateUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Name"},"vendor":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Vendor"},"platform":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Platform"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"data":{"anyOf":[{"$ref":"#/components/schemas/TemplateData"},{"type":"null"}]},"raw_yaml":{"anyOf":[{"type":"string","maxLength":100000},{"type":"null"}],"title":"Raw Yaml"}},"additionalProperties":false,"type":"object","title":"TacacsTemplateUpdate","description":"Schema for updating a template."},"TacacsUploadServerCert":{"properties":{"cert_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Cert Pem","description":"PEM-encoded server certificate"},"private_key_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Private Key Pem","description":"PEM-encoded private key"},"private_key_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Private Key Password","description":"Password for encrypted private key"},"ca_chain_pem":{"anyOf":[{"type":"string","maxLength":131072},{"type":"null"}],"title":"Ca Chain Pem","description":"PEM-encoded CA chain (intermediate + root)"}},"type":"object","required":["cert_pem","private_key_pem"],"title":"TacacsUploadServerCert","description":"Upload a server certificate with private key and optional CA chain."},"TagUpsert":{"properties":{"title":{"type":"string","maxLength":40,"minLength":1,"title":"Title","description":"Required short user-facing label (longer text belongs in note)"},"note":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Note","description":"Optional description"}},"additionalProperties":false,"type":"object","required":["title"],"title":"TagUpsert","description":"Set (create-or-replace) the single user ``tag`` on a snapshot.\n\nA tag is a purely user-facing label with no anchor semantics — ``title`` is required,\n``note`` optional. Distinct from :class:`VersionLabelCreate` (role labels), which carry\nbaseline/pin invariants."},"TelnetSettings":{"properties":{"kind":{"type":"string","const":"telnet","title":"Kind","default":"telnet"},"paging_cmd":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Paging Cmd","description":"Command to disable paging."},"prompt_regex":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Prompt Regex","description":"Override for the device prompt regex."},"device_type":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Device Type","description":"Netmiko device_type override (e.g. 'linux'); empty ⇒ platform default (cisco_ios)."}},"additionalProperties":false,"type":"object","title":"TelnetSettings","description":"Telnet transport settings."},"TemplateAttribute":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"pattern":"^[A-Za-z0-9_.:@/-]+$","title":"Name"},"separator":{"type":"string","enum":["=","*"],"title":"Separator","default":"="},"data_type":{"type":"string","enum":["string","integer","enum","boolean"],"title":"Data Type","default":"string"},"multi":{"type":"boolean","title":"Multi","default":false},"optional":{"type":"boolean","title":"Optional","default":true},"default":{"anyOf":[{},{"type":"null"}],"title":"Default"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"options":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Options"},"static":{"anyOf":[{"items":{"$ref":"#/components/schemas/TemplateStaticField"},"type":"array"},{"type":"null"}],"title":"Static"}},"type":"object","required":["name"],"title":"TemplateAttribute","description":"A single attribute within a service definition."},"TemplateCategory":{"type":"string","enum":["system","aaa","nac","ncm","alerts"],"title":"TemplateCategory","description":"The product domain a template belongs to (§16 gallery grouping).\n\nA curation axis for the \"New dataset\" template gallery: templates are grouped\ninto these product domains so a builder browses by area rather than scrolling a\nflat list. Declared **explicitly** per template (not derived from the ``id``\nprefix) because the prefix lies — ``auth_failures`` is cross-surface and lands\nin ``SYSTEM``, ``aaa_authn`` is a raw log under ``AAA``. Both template kinds\n(preset + raw) carry a category; the gallery shows presets first, then raw,\ninside each domain section."},"TemplateCommandAuth":{"properties":{"supports_command_auth":{"type":"boolean","title":"Supports Command Auth","default":false},"command_match_style":{"type":"string","enum":["regex","exact","prefix"],"title":"Command Match Style","default":"regex"}},"type":"object","title":"TemplateCommandAuth","description":"Command authorization metadata for the platform."},"TemplateData":{"properties":{"defaults":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Defaults"},"services":{"items":{"$ref":"#/components/schemas/TemplateService"},"type":"array","minItems":1,"title":"Services"},"enable":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Enable"},"command_authorization":{"anyOf":[{"$ref":"#/components/schemas/TemplateCommandAuth"},{"type":"null"}]}},"type":"object","required":["services"],"title":"TemplateData","description":"Validates the full JSONB structure of a TacacsTemplate on upload.\n\nThis model is used at upload time to ensure the YAML/JSON payload\nconforms to the expected structure before storing as JSONB."},"TemplateDetail":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"$ref":"#/components/schemas/TemplateKind"},"category":{"$ref":"#/components/schemas/TemplateCategory"},"title":{"type":"string","title":"Title"},"description":{"type":"string","title":"Description"},"export_formats":{"items":{"$ref":"#/components/schemas/ExportFormat-Output"},"type":"array","title":"Export Formats"},"views":{"items":{"$ref":"#/components/schemas/ViewSummary"},"type":"array","title":"Views","default":[]},"filters":{"items":{"$ref":"#/components/schemas/FilterSummary"},"type":"array","title":"Filters"},"columns":{"items":{"$ref":"#/components/schemas/ColumnSummary"},"type":"array","title":"Columns"},"capabilities":{"$ref":"#/components/schemas/CapabilitiesSummary"}},"type":"object","required":["id","kind","category","title","description","export_formats","filters","columns","capabilities"],"title":"TemplateDetail","description":"A template's **full** public shape — the lean summary plus everything needed\nto render its filter form, its result columns (roles/labels for the view picker)\nand its capabilities. Returned by ``GET /reports/templates/{id}``."},"TemplateFieldDefinition":{"properties":{"type":{"type":"string","enum":["string","integer","enum","boolean"],"title":"Type","default":"string"},"label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Label"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"required":{"type":"boolean","title":"Required","default":false},"default":{"anyOf":[{},{"type":"null"}],"title":"Default"},"options":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Options"}},"type":"object","title":"TemplateFieldDefinition","description":"Definition of a single input field within a static attribute."},"TemplateKind":{"type":"string","enum":["raw_table","preset"],"title":"TemplateKind","description":"Who owns the visual presentation of a template's result (§4).\n\n``RAW_TABLE`` — the **user** owns display: exactly one query, over whose tidy\nresult the user picks the view (table / bar / line / pie / …) and maps columns\nto channels (wave 1, ``dataset.display_config``).\n``PRESET`` — **we** own display: curated panels/layout authored in code (wave\n0b); the user only supplies filter values."},"TemplateListResponse":{"properties":{"templates":{"items":{"$ref":"#/components/schemas/TemplateSummary"},"type":"array","title":"Templates"}},"type":"object","required":["templates"],"title":"TemplateListResponse","description":"The in-code template catalog (lean summaries)."},"TemplateService":{"properties":{"service":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[A-Za-z0-9_.:@/-]+$","title":"Service"},"protocol":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Protocol"},"attributes":{"items":{"$ref":"#/components/schemas/TemplateAttribute"},"type":"array","title":"Attributes"}},"type":"object","required":["service"],"title":"TemplateService","description":"A service definition within the template (shell, junos-exec, etc.)."},"TemplateStaticField":{"properties":{"key":{"type":"string","pattern":"^[a-z0-9_-]+$","title":"Key"},"label":{"type":"string","title":"Label"},"pattern":{"type":"string","title":"Pattern"},"optional":{"type":"boolean","title":"Optional","default":true},"multi":{"type":"boolean","title":"Multi","default":false},"fields":{"additionalProperties":{"$ref":"#/components/schemas/TemplateFieldDefinition"},"type":"object","title":"Fields"}},"type":"object","required":["key","label","pattern"],"title":"TemplateStaticField","description":"A static (pre-defined) attribute pattern with substitutable fields."},"TemplateSummary":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"$ref":"#/components/schemas/TemplateKind"},"category":{"$ref":"#/components/schemas/TemplateCategory"},"title":{"type":"string","title":"Title"},"description":{"type":"string","title":"Description"},"export_formats":{"items":{"$ref":"#/components/schemas/ExportFormat-Output"},"type":"array","title":"Export Formats"},"views":{"items":{"$ref":"#/components/schemas/ViewSummary"},"type":"array","title":"Views","default":[]}},"type":"object","required":["id","kind","category","title","description","export_formats"],"title":"TemplateSummary","description":"A template's **lean** shape for the catalog list — just what the gallery, the\ndataset list and the pickers need to show and group a template: identity, kind,\ncategory, labels, its preset views (small: key+label) and its export formats. The\nheavy parts (filter specs, result columns, capabilities) live only on the detail\nendpoint (:class:`TemplateDetail`, ``GET /reports/templates/{id}``) so the catalog\nstays small as the template set grows."},"TestConnectionResponse":{"properties":{"connection":{"type":"string","title":"Connection"},"servers_tested":{"items":{"$ref":"#/components/schemas/ServerTestResult"},"type":"array","title":"Servers Tested"},"bind":{"type":"string","title":"Bind","default":"not_tested"},"user_search":{"anyOf":[{"$ref":"#/components/schemas/SearchTestResult"},{"type":"null"}]},"group_search":{"anyOf":[{"$ref":"#/components/schemas/SearchTestResult"},{"type":"null"}]},"root_dns":{"items":{"type":"string"},"type":"array","title":"Root Dns","description":"Auto-detected root naming contexts from RootDSE"},"errors":{"items":{"type":"string"},"type":"array","title":"Errors"}},"type":"object","required":["connection"],"title":"TestConnectionResponse","description":"Response from the LDAP test-connection endpoint."},"TimeRangeCreate":{"properties":{"name":{"type":"string","maxLength":64,"minLength":1,"title":"Name","description":"Unique name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"entries":{"items":{"$ref":"#/components/schemas/TimeRangeEntry"},"type":"array","maxItems":100,"minItems":1,"title":"Entries","description":"At least one time entry required"}},"additionalProperties":false,"type":"object","required":["name","entries"],"title":"TimeRangeCreate","description":"Schema for creating a new time range."},"TimeRangeEntry":{"properties":{"days":{"items":{"type":"string"},"type":"array","maxItems":7,"minItems":1,"title":"Days","description":"Days of week: mon, tue, wed, thu, fri, sat, sun"},"start_time":{"type":"string","title":"Start Time","description":"Start time in HH:MM format (24h)"},"end_time":{"type":"string","title":"End Time","description":"End time in HH:MM format (24h)"}},"additionalProperties":false,"type":"object","required":["days","start_time","end_time"],"title":"TimeRangeEntry","description":"A single time window within a TimeRange."},"TimeRangeListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"entries":{"items":{"$ref":"#/components/schemas/TimeRangeEntry"},"type":"array","title":"Entries","description":"Time entries"},"entries_count":{"type":"integer","title":"Entries Count","description":"Number of time entries"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","name","entries_count","created_at"],"title":"TimeRangeListResponse","description":"Abbreviated time range for list views."},"TimeRangeResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"entries":{"items":{"$ref":"#/components/schemas/TimeRangeEntry"},"type":"array","title":"Entries"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","created_at","updated_at"],"title":"TimeRangeResponse","description":"Full time range response."},"TimeRangeUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Description"},"entries":{"anyOf":[{"items":{"$ref":"#/components/schemas/TimeRangeEntry"},"type":"array","maxItems":100,"minItems":1},{"type":"null"}],"title":"Entries"}},"additionalProperties":false,"type":"object","title":"TimeRangeUpdate","description":"Schema for updating a time range. All fields optional."},"TitlePageConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true},"subtitle":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Subtitle"},"confidentiality":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}],"title":"Confidentiality"}},"additionalProperties":false,"type":"object","title":"TitlePageConfig","description":"The optional cover page — the report name, a subtitle, and an optional\nconfidentiality / NDA notice.\n\n``confidentiality`` is rich text (HTML) authored in the builder's editor; it is\nsanitized server-side to the safe tag/attribute subset on save (like the captive\nportal's terms text), so the cover can render it inline without an injection risk."},"TocConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true}},"additionalProperties":false,"type":"object","title":"TocConfig","description":"The optional table of contents — an ordered list of the report's pages."},"TopFailedAuthResponse":{"properties":{"period":{"type":"string","title":"Period"},"items":{"items":{"$ref":"#/components/schemas/FailedAuthEntry"},"type":"array","title":"Items"}},"type":"object","required":["period","items"],"title":"TopFailedAuthResponse","description":"Response for top-failed-auth widget."},"TraceStage":{"type":"string","enum":["plan","tcp_connect","negotiate","auth","session_prep","command","scrub","result"],"title":"TraceStage","description":"The phase of a collection a :class:`TraceStep` reports on (also its display order)."},"TraceStatus":{"type":"string","enum":["ok","failed","skipped"],"title":"TraceStatus","description":"Outcome of one trace step."},"TraceStepResponse":{"properties":{"stage":{"$ref":"#/components/schemas/TraceStage"},"key":{"type":"string","title":"Key"},"status":{"$ref":"#/components/schemas/TraceStatus"},"detail":{"type":"string","title":"Detail"},"timing_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Timing Ms"},"data":{"additionalProperties":{"anyOf":[{"type":"integer"},{"type":"string"}]},"type":"object","title":"Data"}},"type":"object","required":["stage","key","status","detail"],"title":"TraceStepResponse","description":"One phase of a preview collection. Secret-safe: ``data`` is counts only, and\n``key``/``detail`` never carry raw device text (``key`` is a stage name or an\noperator-authored command string)."},"TrackedConfigAddressCreate":{"properties":{"address":{"type":"string","maxLength":64,"minLength":1,"title":"Address","description":"Concrete v4/v6 host address (NOT a subnet)"},"collector_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Collector Id","description":"Collector scoping the address; defaults to the default collector when omitted"}},"additionalProperties":false,"type":"object","required":["address"],"title":"TrackedConfigAddressCreate","description":"Add a concrete, collector-scoped address to a tracked config."},"TrackedConfigAddressResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"address":{"type":"string","title":"Address"},"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","address","collector_id","created_at"],"title":"TrackedConfigAddressResponse","description":"A tracked-config address child row."},"TrackedConfigCreate":{"properties":{"name":{"type":"string","maxLength":128,"minLength":1,"title":"Name","description":"Identity discriminator (mandatory)"},"source_id":{"type":"string","format":"uuid","title":"Source Id","description":"Collection source this config is gathered from"},"recipe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id","description":"Override extraction recipe; null → default at use-time"},"is_enabled":{"type":"boolean","title":"Is Enabled","description":"Whether this config is actively collected","default":true}},"additionalProperties":false,"type":"object","required":["name","source_id"],"title":"TrackedConfigCreate","description":"Create a tracked config."},"TrackedConfigListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"source_id":{"type":"string","format":"uuid","title":"Source Id"},"source_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Name"},"baseline_snapshot_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Baseline Snapshot Id"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"definition_updated_at":{"type":"string","format":"date-time","title":"Definition Updated At"},"last_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Changed At"},"last_changed_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Changed Version"},"last_collected_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Collected At"},"status":{"type":"string","title":"Status"},"failure_class":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failure Class"},"recipe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"},"recipe_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Name"},"collectors":{"items":{"type":"string"},"type":"array","title":"Collectors"},"recipient_groups":{"items":{"type":"string"},"type":"array","title":"Recipient Groups"},"recipient_group_count":{"type":"integer","title":"Recipient Group Count","default":0}},"type":"object","required":["id","name","source_id","is_enabled","created_at","definition_updated_at","status"],"title":"TrackedConfigListResponse","description":"Abbreviated tracked-config for list views (four honest times + derived status).\n\n``status`` is the at-a-glance derived health (``disabled`` / ``collector_offline`` /\n``failing`` / ``drifted`` / ``never`` / ``ok``), computed in the list query from first\nsources — never stored (see ``service.ConfigStatus`` / ``derive_config_status``).\n``failure_class`` (``auth`` / ``transient`` / ``partial``) is carried ONLY when\n``status == \"failing\"``, so the operator sees *why* the newest scheduled collect failed."},"TrackedConfigResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"source_id":{"type":"string","format":"uuid","title":"Source Id"},"source_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Name"},"source":{"anyOf":[{"$ref":"#/components/schemas/TrackedConfigSourceSummary"},{"type":"null"}]},"recipe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"},"recipe_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Name"},"baseline_snapshot_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Baseline Snapshot Id"},"is_enabled":{"type":"boolean","title":"Is Enabled"},"addresses":{"items":{"$ref":"#/components/schemas/TrackedConfigAddressResponse"},"type":"array","title":"Addresses"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"definition_updated_at":{"type":"string","format":"date-time","title":"Definition Updated At"},"last_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Changed At"},"last_changed_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Last Changed Version"},"last_collected_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Collected At"}},"type":"object","required":["id","name","source_id","is_enabled","created_at","definition_updated_at"],"title":"TrackedConfigResponse","description":"Full tracked-config response, including its addresses.\n\nExposes FOUR distinct, honest times so \"updated\" is never ambiguous:\n\n* ``created_at`` — when the config was first tracked.\n* ``definition_updated_at`` — when the *settings/form* (name/recipe/addresses)\n  were last edited (service-set only; never bumped by a poll or a baseline label).\n* ``last_changed_at`` / ``last_changed_version`` — the ``captured_at`` of the LATEST\n  snapshot = when the config *content* last actually changed, and the config's CURRENT\n  **per-config** version ordinal (= its snapshot count = the latest snapshot's 1-based\n  rank by ``ingest_ordinal``, ``v{last_changed_version}``); both ``null`` when nothing has ever\n  been captured. This is NOT the global ``Snapshot.ingest_ordinal``; it matches the Overview\n  feed's per-snapshot ``version`` and preview's ``would_be_version``.\n* ``last_collected_at`` — when the config was last *polled* (changed or not); ``null``\n  when it has never been collected."},"TrackedConfigSourceSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"transport_type":{"type":"string","title":"Transport Type"},"address":{"type":"string","title":"Address"},"effective_port":{"type":"integer","title":"Effective Port"},"collector_id":{"type":"string","format":"uuid","title":"Collector Id"},"collector_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collector Name"}},"type":"object","required":["id","name","transport_type","address","effective_port","collector_id"],"title":"TrackedConfigSourceSummary","description":"Read-only preview of the config's collection source (transport / endpoint / collector),\nembedded on the detail read so the metadata card renders the collection endpoint without a\nseparate ``GET /sources/{id}`` fetch. ``effective_port`` is the transport-registry default\nwhen the source pins no explicit port."},"TrackedConfigUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":128,"minLength":1},{"type":"null"}],"title":"Name"},"source_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source Id"},"recipe_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Recipe Id"},"is_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Enabled"}},"additionalProperties":false,"type":"object","title":"TrackedConfigUpdate","description":"Update a tracked config (partial). ``baseline_snapshot_id`` is set via labeling."},"TransportMetadataResponse":{"properties":{"type":{"$ref":"#/components/schemas/TransportType","description":"Transport registry key"},"default_port":{"type":"integer","maximum":65535.0,"minimum":1.0,"title":"Default Port","description":"Default port used when a source leaves port NULL"},"requires_credential":{"type":"boolean","title":"Requires Credential","description":"Whether the transport needs a credential to authenticate"},"tls_capable":{"type":"boolean","title":"Tls Capable","description":"Whether the transport carries a TLS-verify setting (https only)"},"available":{"type":"boolean","title":"Available","description":"Whether a working collector driver exists today"}},"type":"object","required":["type","default_port","requires_credential","tls_capable","available"],"title":"TransportMetadataResponse","description":"One transport's static registry metadata (drives the data-driven source form).\n\n``available`` marks whether a working collector driver exists **today**:\n``ssh``/``telnet`` and ``http``/``https`` are wired; the rest are registered (so\na source can be modelled) but their drivers / push-server are not built yet — the\nUI shows a \"coming soon\" marker so operators are not misled."},"TransportType":{"type":"string","enum":["ssh","telnet","scp","sftp","http","https"],"title":"TransportType","description":"The mechanism a collector uses to reach a source (the transport registry key)."},"UpdateFeedStatus":{"properties":{"enabled":{"type":"boolean","title":"Enabled","description":"Whether update checking is turned on (update_feed.enabled)"},"current_version":{"type":"string","title":"Current Version","description":"The deployed version (APP_VERSION)"},"latest_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Latest Version","description":"Latest published release for this edition, or null"},"update_available":{"type":"boolean","title":"Update Available","description":"True when a reachable check found latest != current"},"min_supported":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Min Supported","description":"Oldest supported version (informational only in Phase 1)"},"reachable":{"type":"boolean","title":"Reachable","description":"False when taranac.pro could not be reached (e.g. air-gapped)"},"problem":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Problem","description":"Machine reason on the last failed check (localized in the UI)"},"checked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Checked At","description":"When the manifest was last successfully fetched (UTC)"},"released_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Released At","description":"Release date of the latest version (UTC)"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes","description":"Free-text release notes (rendered as plain text, never HTML)"},"changelog_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Changelog Url","description":"Link to the full changelog for the latest version"}},"type":"object","required":["enabled","current_version","update_available","reachable"],"title":"UpdateFeedStatus","description":"Current update-feed state for the UI (drives the System-info widget row).\n\nA pure read of the persisted last-check result plus the deployed version. Never\nthe wire payload verbatim: ``update_available`` is computed here (client-side\ncomparison), and ``problem`` is a stable machine code the frontend localizes.\nWhen checks are disabled or nothing has been checked this session, the optional\nfields are ``null`` / ``false`` and the feature stays invisible."},"UploadServerCert":{"properties":{"cert_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Cert Pem","description":"PEM-encoded server certificate"},"private_key_pem":{"type":"string","maxLength":65536,"minLength":50,"title":"Private Key Pem","description":"PEM-encoded private key"},"private_key_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Private Key Password","description":"Password for encrypted private key"},"ca_chain_pem":{"anyOf":[{"type":"string","maxLength":131072},{"type":"null"}],"title":"Ca Chain Pem","description":"PEM-encoded CA chain (intermediate + root)"}},"type":"object","required":["cert_pem","private_key_pem"],"title":"UploadServerCert","description":"Upload a server certificate with private key and optional CA chain."},"UptimeMetrics":{"properties":{"system_boot_time":{"type":"string","title":"System Boot Time"},"app_uptime_seconds":{"type":"integer","title":"App Uptime Seconds"}},"type":"object","required":["system_boot_time","app_uptime_seconds"],"title":"UptimeMetrics","description":"Uptime information."},"UserCreate":{"properties":{"username":{"type":"string","maxLength":64,"minLength":1,"title":"Username","description":"Unique username"},"email":{"type":"string","maxLength":254,"format":"email","title":"Email","description":"Email address (not unique)"},"first_name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"First Name","description":"First name"},"last_name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Last Name","description":"Last name / surname"},"display_name":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Display Name","description":"Display name. If not set, computed from first_name + last_name."},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone","description":"Phone number"},"password":{"type":"string","maxLength":256,"minLength":1,"title":"Password","description":"Plain-text password (validated by policy)"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether the account is active","default":true},"must_change_password":{"type":"boolean","title":"Must Change Password","description":"Force password change on next login","default":false},"lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang","description":"Preferred language code; falls back to system.default_locale when omitted"},"group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100},{"type":"null"}],"title":"Group Ids","description":"Group IDs to assign the user to"},"enable_mode":{"type":"string","enum":["inherit","login_password","custom","deny"],"title":"Enable Mode","description":"TACACS+ enable password mode","default":"inherit"},"enable_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Enable Password","description":"Enable password (required when enable_mode='custom')"},"valid_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid From","description":"Account valid from this date/time. NULL = no start restriction."},"valid_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid Until","description":"Account valid until this date/time. NULL = no expiration."}},"additionalProperties":false,"type":"object","required":["username","email","password"],"title":"UserCreate","description":"Schema for creating a new user."},"UserGroupBrief":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_admins":{"type":"boolean","title":"Is Admins"}},"type":"object","required":["id","name","is_admins"],"title":"UserGroupBrief","description":"Brief group info embedded in UserResponse."},"UserListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"username":{"type":"string","title":"Username"},"email":{"type":"string","title":"Email"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"groups":{"items":{"$ref":"#/components/schemas/GroupInfoResponse"},"type":"array","title":"Groups"},"is_active":{"type":"boolean","title":"Is Active"},"is_locked":{"type":"boolean","title":"Is Locked"},"auth_source":{"type":"string","title":"Auth Source"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"enable_mode":{"type":"string","title":"Enable Mode","default":"inherit"},"valid_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid From"},"valid_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid Until"}},"type":"object","required":["id","username","email","groups","is_active","is_locked","auth_source","created_at"],"title":"UserListResponse","description":"Schema for a single user in list (abbreviated, no groups detail)."},"UserRefItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"auth_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Source"}},"type":"object","required":["id","name"],"title":"UserRefItem","description":"User reference enriched with its auth source (detail view only)."},"UserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"username":{"type":"string","title":"Username"},"email":{"type":"string","title":"Email"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"is_active":{"type":"boolean","title":"Is Active"},"is_locked":{"type":"boolean","title":"Is Locked"},"must_change_password":{"type":"boolean","title":"Must Change Password"},"failed_login_count":{"type":"integer","title":"Failed Login Count"},"auth_source":{"type":"string","title":"Auth Source"},"lang":{"type":"string","title":"Lang"},"ldap_dn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Dn"},"ldap_config_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Config Id"},"ldap_guid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ldap Guid"},"ldap_synced_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ldap Synced At"},"password_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Password Changed At"},"last_login_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login At"},"last_login_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Login Ip"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"groups":{"items":{"$ref":"#/components/schemas/UserGroupBrief"},"type":"array","title":"Groups"},"enable_mode":{"type":"string","title":"Enable Mode","default":"inherit"},"enable_password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enable Password"},"valid_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid From"},"valid_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid Until"},"has_nt_password":{"type":"boolean","title":"Has Nt Password","default":false},"aaa_live_auth":{"type":"boolean","title":"Aaa Live Auth","default":false}},"type":"object","required":["id","username","email","is_active","is_locked","must_change_password","failed_login_count","auth_source","lang","created_at","updated_at"],"title":"UserResponse","description":"Schema for a single user in API responses."},"UserUpdate":{"properties":{"email":{"anyOf":[{"type":"string","maxLength":254,"format":"email"},{"type":"null"}],"title":"Email"},"first_name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Last Name"},"display_name":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Display Name"},"phone":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Phone"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"must_change_password":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Must Change Password"},"lang":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lang"},"group_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100},{"type":"null"}],"title":"Group Ids"},"password":{"anyOf":[{"type":"string","maxLength":256,"minLength":1},{"type":"null"}],"title":"Password","description":"New password (admin reset)"},"enable_mode":{"anyOf":[{"type":"string","enum":["inherit","login_password","custom","deny"]},{"type":"null"}],"title":"Enable Mode","description":"TACACS+ enable password mode"},"enable_password":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Enable Password","description":"Enable password. Sentinel = keep, empty = clear, other = encrypt."},"valid_from":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid From","description":"Account valid from (NULL = clear)"},"valid_until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Valid Until","description":"Account valid until (NULL = clear)"}},"additionalProperties":false,"type":"object","title":"UserUpdate","description":"Schema for updating an existing user.\n\nAll fields are optional — only provided fields are updated.\nPassword changes go through a separate endpoint.\n\nEnable password sentinel logic:\n- sentinel (\"••••••••\") = keep current password\n- empty string (\"\") = clear the password\n- any other value = encrypt and save\n\n``username`` is intentionally absent — it is immutable, and extra=\"forbid\"\nmeans the client must not send it in an update payload."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VendorAttributeMappingSchema":{"properties":{"attr":{"type":"string","maxLength":255,"minLength":1,"title":"Attr"},"value":{"type":"string","maxLength":1024,"title":"Value"},"op":{"type":"string","maxLength":10,"title":"Op","default":"="}},"additionalProperties":false,"type":"object","required":["attr","value"],"title":"VendorAttributeMappingSchema","description":"Single RADIUS attribute template within a capability mapping."},"VendorAttributePreview":{"properties":{"vendor_key":{"type":"string","title":"Vendor Key"},"vendor_name":{"type":"string","title":"Vendor Name"},"attributes":{"items":{"$ref":"#/components/schemas/RadiusAttributeEntry"},"type":"array","title":"Attributes"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["vendor_key","vendor_name"],"title":"VendorAttributePreview","description":"RADIUS attributes rendered for a specific vendor in the dictionary."},"VendorCapabilityInfo":{"properties":{"key":{"type":"string","title":"Key"},"display_name":{"type":"string","title":"Display Name"},"vendor_id":{"type":"integer","title":"Vendor Id"},"coa_port":{"type":"integer","title":"Coa Port"},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities"}},"type":"object","required":["key","display_name","vendor_id","coa_port","capabilities"],"title":"VendorCapabilityInfo","description":"Brief vendor info for the vendor dictionary list endpoint."},"VendorCoaActionSchema":{"properties":{"method":{"type":"string","maxLength":20,"title":"Method","default":"unsupported"},"attrs":{"items":{"$ref":"#/components/schemas/VendorAttributeMappingSchema"},"type":"array","maxItems":64,"title":"Attrs"}},"additionalProperties":false,"type":"object","title":"VendorCoaActionSchema","description":"Single CoA action definition for a vendor.\n\nmethod:\n  - coa_request: send a CoA-Request (code 43) with the listed `attrs`.\n  - disconnect:  fall back to a standard RFC 5176 Disconnect-Request\n                 (no VSA); used where the vendor has no native action.\n  - unsupported: the vendor cannot perform this action at all.\n`attrs` are only meaningful when method == coa_request and reuse the same\n{attr, value, op} template shape as mappings (supports {{placeholders}})."},"VendorDetectHintsSchema":{"properties":{"vsa_present":{"items":{"type":"string"},"type":"array","maxItems":64,"title":"Vsa Present"},"calling_station_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Calling Station Format"}},"additionalProperties":false,"type":"object","title":"VendorDetectHintsSchema","description":"Auto-detection hints for identifying vendor from RADIUS request."},"VendorDictionaryResponse":{"properties":{"vendors":{"items":{"$ref":"#/components/schemas/VendorCapabilityInfo"},"type":"array","title":"Vendors"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["vendors","total"],"title":"VendorDictionaryResponse","description":"Full vendor dictionary listing."},"VendorPreviewEntry":{"properties":{"vendor_key":{"type":"string","title":"Vendor Key"},"vendor_name":{"type":"string","title":"Vendor Name"},"attributes":{"items":{"$ref":"#/components/schemas/RadiusAttributePreview"},"type":"array","title":"Attributes"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["vendor_key","vendor_name"],"title":"VendorPreviewEntry","description":"RADIUS attributes rendered for a specific vendor."},"VerifyCodeRequest":{"properties":{"code":{"type":"string","maxLength":8,"minLength":4,"title":"Code"}},"type":"object","required":["code"],"title":"VerifyCodeRequest","description":"Verification code submission.\n\nPUBLIC endpoint — posted by the guest's browser. No extra=\"forbid\"; already\nbounded."},"VerifyCodeResponse":{"properties":{"status":{"type":"string","title":"Status"},"message":{"type":"string","title":"Message"},"attempts_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Attempts Remaining"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["status","message"],"title":"VerifyCodeResponse","description":"Response after code verification attempt."},"VersionLabelCreate":{"properties":{"kind":{"$ref":"#/components/schemas/LabelKind","description":"pin|baseline|golden|approved"},"note":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Note","description":"Optional operator note"}},"additionalProperties":false,"type":"object","required":["kind"],"title":"VersionLabelCreate","description":"Apply a role label to a snapshot."},"VersionLabelResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"snapshot_id":{"type":"string","format":"uuid","title":"Snapshot Id"},"kind":{"$ref":"#/components/schemas/LabelKind"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title","description":"User-facing title; set only for kind='tag'"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","snapshot_id","kind","created_at"],"title":"VersionLabelResponse","description":"A version label (role anchor or user tag)."},"ViewSummary":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"}},"type":"object","required":["key","label"],"title":"ViewSummary","description":"One authored preset view — a named presentation of the result (§5).\n\nPost render-pivot the panel/layout composition lives in the backend's Jinja\ntemplates; the API exposes only the view's stable ``key`` (what a preset\ndataset stores in ``display_config.view``) and its resolved ``label``. A\n``raw_table`` template has no views (its list is empty)."},"WindowOption":{"properties":{"value":{"$ref":"#/components/schemas/RelativeWindow-Output"},"label":{"type":"string","title":"Label"}},"type":"object","required":["value","label"],"title":"WindowOption","description":"One offered relative period window with its resolved label."},"WorkerJobStatus":{"properties":{"id":{"type":"string","title":"Id","description":"Job ID in APScheduler"},"name":{"type":"string","title":"Name","description":"Human-readable job name"},"description":{"type":"string","title":"Description","description":"What the job does","default":""},"category":{"type":"string","title":"Category","description":"Logical category for UI grouping","default":""},"trigger_type":{"type":"string","title":"Trigger Type","description":"'interval' or 'cron'"},"trigger_description":{"type":"string","title":"Trigger Description","description":"Human-readable trigger (e.g. 'every 60 seconds')"},"interval_unit":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Interval Unit","description":"Native unit for an editable interval job (seconds/minutes/hours); null for cron or non-editable jobs"},"min_interval_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Interval Seconds","description":"Minimum allowed interval in seconds (for editable interval jobs)"},"next_run_time":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Run Time","description":"Next scheduled execution time"},"is_paused":{"type":"boolean","title":"Is Paused","description":"Whether the job is currently paused (runtime)"},"settings_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Settings Key","description":"SystemSetting key that controls this job's interval/schedule"},"enabled_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Enabled Key","description":"SystemSetting key that controls enabled/disabled state"},"enabled":{"type":"boolean","title":"Enabled","description":"Persistent enabled state. Always true for jobs without an enabled_key.","default":true},"is_registered":{"type":"boolean","title":"Is Registered","description":"Whether the job is currently registered in the live scheduler. False for jobs disabled via their enabled_key.","default":true},"scope":{"type":"string","title":"Scope","description":"Leader scope: 'per_node' (runs on every node) or 'leader_only' (runs only on the Postgres primary). Under HA a leader_only job is registered on every node but its work is gated to the leader — on a replica it is honestly idle, not 'active'.","default":"per_node"}},"type":"object","required":["id","name","trigger_type","trigger_description","is_paused"],"title":"WorkerJobStatus","description":"Status of a single scheduled job (or a known-but-unregistered job)."},"WorkerRunResponse":{"properties":{"job_id":{"type":"string","title":"Job Id"},"triggered":{"type":"boolean","title":"Triggered"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["job_id","triggered","detail"],"title":"WorkerRunResponse","description":"Response from manually triggering a job."},"WorkerStatusResponse":{"properties":{"scheduler_running":{"type":"boolean","title":"Scheduler Running"},"total_jobs":{"type":"integer","title":"Total Jobs"},"jobs":{"items":{"$ref":"#/components/schemas/WorkerJobStatus"},"type":"array","title":"Jobs"},"is_ha":{"type":"boolean","title":"Is Ha","description":"Whether this node runs in an HA cluster (DB_HOSTS set). Standalone → false.","default":false},"node_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Node Name","description":"This node's roster name (TARANAC_NODE_NAME / hostname); null on standalone."},"is_leader":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Leader","description":"Whether THIS node is the current leader (node-local pg_is_in_recovery — the same signal that gates leader_only jobs). null = standalone or leadership undeterminable."}},"type":"object","required":["scheduler_running","total_jobs","jobs"],"title":"WorkerStatusResponse","description":"Overall workers status.\n\nThe node-context fields (``is_ha``/``node_name``/``is_leader``) let the UI\nrender an HA-honest per-worker status: a ``leader_only`` job on a replica is\nidle (it runs on the primary), not \"active\". They are inert on a standalone\nnode (``is_ha=false``), where the single node is always the leader."},"app__modules__aaa__aaa_policy__tester_schemas__ResolvedContext":{"properties":{"user":{"anyOf":[{"$ref":"#/components/schemas/ResolvedUserContext"},{"type":"null"}]},"device":{"anyOf":[{"$ref":"#/components/schemas/app__modules__aaa__aaa_policy__tester_schemas__ResolvedDeviceContext"},{"type":"null"}]},"is_console":{"type":"boolean","title":"Is Console","default":false},"source_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Ip"},"timestamp_used":{"type":"string","format":"date-time","title":"Timestamp Used"}},"type":"object","required":["timestamp_used"],"title":"ResolvedContext","description":"Shows how the tester resolved the input parameters."},"app__modules__aaa__aaa_policy__tester_schemas__ResolvedDeviceContext":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"groups":{"items":{"$ref":"#/components/schemas/ResolvedGroupInfo"},"type":"array","title":"Groups"}},"type":"object","required":["id","name"],"title":"ResolvedDeviceContext","description":"Resolved device information."},"app__modules__aaa__aaa_policy__tester_schemas__RuleTraceEntry":{"properties":{"rule_id":{"type":"string","format":"uuid","title":"Rule Id"},"order":{"type":"integer","title":"Order"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"result":{"type":"string","enum":["match","skip","disabled"],"title":"Result","description":"match = rule won, skip = condition failed, disabled = is_enabled=false"},"conditions":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/ConditionResult"},"type":"object"},{"type":"null"}],"title":"Conditions","description":"Detailed condition results. Present for skip and match, null for disabled."}},"type":"object","required":["rule_id","order","result"],"title":"RuleTraceEntry","description":"Trace entry for a single rule evaluation."},"app__modules__infra__dashboard__schemas__AaaActivityResponse":{"properties":{"period":{"type":"string","title":"Period"},"interval":{"type":"string","title":"Interval"},"buckets":{"items":{"$ref":"#/components/schemas/AaaActivityBucket"},"type":"array","title":"Buckets"},"totals":{"$ref":"#/components/schemas/AaaActivityTotals"}},"type":"object","required":["period","interval","buckets","totals"],"title":"AaaActivityResponse","description":"Response for AAA activity chart widget."},"app__modules__infra__import_export__schemas__ExportFormat":{"type":"string","enum":["json","xlsx","csv"],"title":"ExportFormat","description":"Supported export file formats."},"app__modules__nac__nac_policy__schemas__RefItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"RefItem","description":"Minimal id + name reference for response lists."},"app__modules__nac__nac_policy__tester_schemas__ResolvedContext":{"properties":{"endpoint":{"anyOf":[{"$ref":"#/components/schemas/ResolvedEndpointContext"},{"type":"null"}]},"user":{"anyOf":[{"$ref":"#/components/schemas/ResolvedUserContext"},{"type":"null"}]},"device":{"anyOf":[{"$ref":"#/components/schemas/app__modules__nac__nac_policy__tester_schemas__ResolvedDeviceContext"},{"type":"null"}]},"timestamp_used":{"type":"string","format":"date-time","title":"Timestamp Used"}},"type":"object","required":["timestamp_used"],"title":"ResolvedContext","description":"Shows how the tester resolved the input parameters."},"app__modules__nac__nac_policy__tester_schemas__ResolvedDeviceContext":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"vendor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Vendor"},"groups":{"items":{"$ref":"#/components/schemas/ResolvedGroupInfo"},"type":"array","title":"Groups"}},"type":"object","required":["id","name"],"title":"ResolvedDeviceContext","description":"Resolved device (NAS) information."},"app__modules__nac__nac_policy__tester_schemas__RuleTraceEntry":{"properties":{"rule_id":{"type":"string","format":"uuid","title":"Rule Id"},"order":{"type":"integer","title":"Order"},"name":{"type":"string","title":"Name"},"result":{"type":"string","enum":["match","skip","disabled"],"title":"Result","description":"match = rule won, skip = condition failed, disabled = is_enabled=false"},"conditions":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/ConditionResult"},"type":"object"},{"type":"null"}],"title":"Conditions","description":"Detailed condition results. Present for skip and match, null for disabled."}},"type":"object","required":["rule_id","order","name","result"],"title":"RuleTraceEntry","description":"Trace entry for a single rule evaluation."},"app__modules__ncm__aaa_activity__schemas__AaaActivityResponse":{"properties":{"window":{"$ref":"#/components/schemas/ActivityWindow"},"addresses":{"items":{"type":"string"},"type":"array","title":"Addresses","description":"The tracked config's addresses used for correlation"},"users":{"items":{"type":"string"},"type":"array","title":"Users","description":"Distinct usernames active in the window across TACACS+ and RADIUS (for the FE user filter)"},"authentication":{"items":{"$ref":"#/components/schemas/AuthenticationEvent"},"type":"array","title":"Authentication"},"authorization":{"items":{"$ref":"#/components/schemas/AuthorizationEvent"},"type":"array","title":"Authorization"},"accounting":{"items":{"$ref":"#/components/schemas/AccountingEvent"},"type":"array","title":"Accounting"}},"type":"object","required":["window","addresses","users","authentication","authorization","accounting"],"title":"AaaActivityResponse","description":"AAA activity for a config-change window: who connected, ran what, and session accounting.\n\nCovers device administration over **both** TACACS+ and RADIUS (each row tagged via\n``protocol`` on the authn/acct lists); the command dimension is TACACS+-only.\nBest-effort and address-correlated: a tracked config with no addresses, or an\naddress absent from the AAA logs, yields empty lists (never an error). Each list is\ncapped to the most-recent rows in the window (see ``service.py`` for the bounds)."},"app__modules__reports__contract__ExportFormat":{"type":"string","enum":["pdf","csv","xlsx"],"title":"ExportFormat","description":"A file format a report can be exported to (§6)."},"app__shared__references__RefItem":{"properties":{"ref_type":{"type":"string","title":"Ref Type","description":"Machine tag for icon/grouping, e.g. 'aaa_rule'."},"label":{"type":"string","title":"Label","description":"Fully-localized human label, e.g. 'AAA rule #3 — VPN admins'."},"link":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Link","description":"Frontend route where the operator resolves it."},"resolution":{"$ref":"#/components/schemas/RefResolution"}},"type":"object","required":["ref_type","label","resolution"],"title":"RefItem","description":"One place an object is used."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}},"tags":[{"name":"Authentication","description":"Login, logout, token refresh, password reset and the self-service profile."},{"name":"MFA","description":"Multi-factor enrollment, challenge/verify (TOTP and push) and admin setup links."},{"name":"MFA (Internal)","description":"Internal MFA challenge/verify called by the RADIUS/NAC daemons during live auth."},{"name":"Users","description":"Local and LDAP-synced user accounts, lock/unlock and enable-password settings."},{"name":"Groups","description":"User groups — membership, admin flag, MFA requirement and RBAC model binding."},{"name":"RBAC","description":"Permission models and the permission schema that gates every endpoint."},{"name":"LDAP Directory","description":"LDAP/AD connections, user & computer sync, directory browse and EAP-TLS mapping."},{"name":"Domain Membership","description":"Active Directory machine account — the join MS-CHAPv2 needs to verify domain passwords."},{"name":"Devices","description":"Network devices (NAS) — addresses, shared secrets and per-protocol flags."},{"name":"Device Groups","description":"Group devices for shared-secret and CoA inheritance."},{"name":"Network Objects","description":"Reusable hosts, subnets and IP ranges referenced by devices and policy."},{"name":"Time Ranges","description":"Named weekly time windows used as a policy condition."},{"name":"TACACS+ Profiles","description":"Authorization profiles — services, command sets and enable behavior."},{"name":"TACACS+ Templates","description":"Vendor/platform attribute templates that profiles fill in."},{"name":"Command Sets","description":"Permit/deny command rule sets for command authorization."},{"name":"TACACS+ Settings","description":"Global tac_plus-ng daemon settings and config preview/reload."},{"name":"TACACS+ Server Certificate","description":"The TLS server certificate presented by the TACACS+ daemon."},{"name":"RADIUS Profiles","description":"Authorization profiles — reply attributes and service type."},{"name":"RADIUS Templates","description":"Vendor attribute templates that RADIUS profiles fill in."},{"name":"RADIUS Settings","description":"Global FreeRADIUS (aaa virtual server) settings and config preview/reload."},{"name":"AAA Policy","description":"Ordered TACACS+/RADIUS authorization rules (who · what · where · when → profile)."},{"name":"AAA Logs","description":"TACACS+/RADIUS authentication, authorization and accounting records."},{"name":"Log Exclusions","description":"Rules that suppress selected AAA log records from storage/syslog."},{"name":"Endpoints","description":"Discovered/registered endpoints (MAC identities), pinning and blocking."},{"name":"Endpoint Groups","description":"Static and rule-classified endpoint groups used as a policy condition."},{"name":"Pending Computers","description":"AD computer accounts awaiting NAC onboarding approval."},{"name":"Authorization Profiles","description":"NAC results — VLAN, ACL, session control and web redirect."},{"name":"NAC Policy","description":"Ordered 802.1X rules (method · who · what · where → authorization profile)."},{"name":"NAC Sessions","description":"Live RADIUS sessions and Change-of-Authorization (disconnect, reauth, VLAN)."},{"name":"NAC Logs","description":"802.1X authentication records and exportable session history."},{"name":"OUI Database","description":"MAC OUI vendor lookups and database sync."},{"name":"Vendor Dictionary","description":"RADIUS vendor dictionary (VSAs, CoA capabilities) for NAC profiles."},{"name":"Captive Portal","description":"Guest / self-registration / BYOD / AUP portal configuration (admin)."},{"name":"Captive Portal (Public)","description":"Public, unauthenticated portal flow endpoints driven by the guest browser."},{"name":"NAC Settings","description":"Global FreeRADIUS (nac virtual server) settings and config preview/reload."},{"name":"NAC Config","description":"NAC daemon config status, validation and reload."},{"name":"NAC PKI","description":"Internal CA lifecycle and client-certificate issuance/revocation."},{"name":"NAC Trusted CAs","description":"Externally-trusted CA certificates and the rebuilt trust bundle."},{"name":"NAC Server Certificate","description":"The TLS server certificate presented by the NAC (802.1X) RADIUS daemon."},{"name":"NAC Certificate Store","description":"Stored issued client certificates and their lifecycle."},{"name":"EST Enrollment","description":"RFC 7030 EST certificate enrollment for endpoints."},{"name":"Certificate Download (Public)","description":"Public, token-scoped certificate / CA download links."},{"name":"CRL Distribution (Public)","description":"Public revocation lists — the CDP embedded in issued certificates."},{"name":"EST Approval (Public)","description":"One-time emailed links for deciding EST enrollment requests."},{"name":"NAC CA Bundle","description":"Public CA-bundle download consumed by endpoints and daemons."},{"name":"NAC PKI Settings","description":"PKI defaults — key size, validity windows and auto-enrollment policy."},{"name":"NCM Collectors","description":"Config-collection deployment/reachability domains that own sources and addresses."},{"name":"NCM Recipes","description":"Extraction recipes — ordered CLI commands or an HTTP request spec, plus trim."},{"name":"NCM Scrub Rule Sets","description":"Ordered scrub transforms (drop-volatile / mask-secret / keep) stored as data."},{"name":"NCM Credentials","description":"Credential vault — encrypted device-collection secrets with audited reveal."},{"name":"NCM Credential Providers","description":"External secret-store seam (Vault/CyberArk) — phase-2, CRUD only."},{"name":"NCM Credential Bindings","description":"Auto-bind memory: which credential last worked at an address."},{"name":"NCM Sources","description":"Collection sources — reachable endpoints (transport + address + creds) feeding configs."},{"name":"NCM Transports","description":"Transport registry metadata — default port, TLS/credential, availability."},{"name":"NCM Tracked Configs","description":"Tracked configurations — identity (name + collector-scoped addresses) and CRUD."},{"name":"NCM Snapshots","description":"Config versions — timeline, diff, pin/baseline labels, and audited raw-body reveal."},{"name":"NCM Collection Runs","description":"Collection runs — leader-only scheduled + on-demand collect, per-target results."},{"name":"NCM Onboarding","description":"Bulk onboarding — sample-probe + import an address pool into ready tracked configs."},{"name":"NCM Collector Gateway","description":"Standalone collector enrollment & transport plane (token-authed enroll + request-signing auth)."},{"name":"Dashboard","description":"Aggregated widgets — activity, top failures, entity counts and NAC summaries."},{"name":"Monitoring","description":"Live daemon health and system status."},{"name":"Alerts","description":"Stateful alerts (brute-force, unknown device, provider-degraded) — ack/resolve."},{"name":"Audit Log","description":"Immutable record of every administrative state change."},{"name":"Workers","description":"Background scheduler jobs — status, intervals and run-now."},{"name":"Backups","description":"Config-only encrypted backups — create, download, restore and schedule."},{"name":"Log Rotation","description":"Retention/rotation status for the high-volume log tables."},{"name":"Import / Export","description":"Bulk import/export of devices, users and other core entities."},{"name":"Settings","description":"General, authentication, alerting and other system-wide settings."},{"name":"Email","description":"SMTP configuration, templates/layout and test send."},{"name":"SMS","description":"SMS provider configuration and test send."},{"name":"Syslog","description":"Syslog destinations and the bindings that forward logs to them."},{"name":"Crypto","description":"Master-key (KEK) rotation."},{"name":"License","description":"Pro licensing — the installation id that binds a Pro license to this install."},{"name":"Update Feed","description":"Signed 'is a newer release available?' check against taranac.pro (opt-in, pull-only)."},{"name":"Cluster","description":"HA cluster membership — node status, license-gated join tokens, decommission."},{"name":"Reports","description":"Reporting — the in-code template catalog, saved datasets, and read-only report runs."},{"name":"Health","description":"Liveness and readiness probes (unauthenticated)."}],"x-tagGroups":[{"name":"Authentication & Access","tags":["Authentication","MFA","MFA (Internal)"]},{"name":"Identity","tags":["Users","Groups","RBAC","LDAP Directory","Domain Membership"]},{"name":"Network","tags":["Devices","Device Groups","Network Objects","Time Ranges"]},{"name":"AAA · TACACS+","tags":["TACACS+ Profiles","TACACS+ Templates","Command Sets","TACACS+ Settings","TACACS+ Server Certificate"]},{"name":"AAA · RADIUS","tags":["RADIUS Profiles","RADIUS Templates","RADIUS Settings"]},{"name":"AAA · Policy & Logs","tags":["AAA Policy","AAA Logs","Log Exclusions"]},{"name":"NAC","tags":["Endpoints","Endpoint Groups","Pending Computers","Authorization Profiles","NAC Policy","NAC Sessions","NAC Logs","OUI Database","Vendor Dictionary","Captive Portal","Captive Portal (Public)","NAC Settings","NAC Config"]},{"name":"NAC · PKI","tags":["NAC PKI","NAC Trusted CAs","NAC Server Certificate","NAC Certificate Store","EST Enrollment","Certificate Download (Public)","CRL Distribution (Public)","EST Approval (Public)","NAC CA Bundle","NAC PKI Settings"]},{"name":"Configuration Tracker","tags":["NCM Collectors","NCM Recipes","NCM Scrub Rule Sets","NCM Credentials","NCM Credential Providers","NCM Credential Bindings","NCM Sources","NCM Transports","NCM Tracked Configs","NCM Snapshots","NCM Collection Runs","NCM Onboarding","NCM Collector Gateway"]},{"name":"Monitoring & Ops","tags":["Dashboard","Monitoring","Alerts","Audit Log","Workers","Backups","Log Rotation","Import / Export"]},{"name":"System Settings","tags":["Settings","Email","SMS","Syslog","Crypto","License","Update Feed","Cluster"]},{"name":"Reports","tags":["Reports"]},{"name":"System","tags":["Health"]}]}