{
  "openapi": "3.0.3",
  "info": {
    "title": "Platform & Administration API",
    "version": "1.0.0",
    "description": "Cross-cutting platform administration \u2014 tenants, identity & RBAC, licensing, settings, audit, and support."
  },
  "servers": [
    {
      "url": "https://versus-demo.com"
    }
  ],
  "paths": {
    "/api/activation/v1/activate": {
      "post": {
        "operationId": "activation_v1_activate_create",
        "description": "\u00a73.1 \u2014 exchange a one-time activation code for a node-bound .veslic.",
        "tags": [
          "activation"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create activate"
      }
    },
    "/api/activation/v1/issued": {
      "get": {
        "operationId": "activation_v1_issued_retrieve",
        "description": "Recent issued licenses + their activation state, for the Control Plane.",
        "tags": [
          "activation"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List issueds"
      }
    },
    "/api/activation/v1/mint-code": {
      "post": {
        "operationId": "activation_v1_mint_code_create",
        "description": "Mint a fresh activation code for an existing issued license.",
        "tags": [
          "activation"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create mint code"
      }
    },
    "/api/activation/v1/revoke": {
      "post": {
        "operationId": "activation_v1_revoke_create",
        "description": "Revoke an issued license \u2014 connected installs go read-only on next heartbeat.",
        "tags": [
          "activation"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create revoke"
      }
    },
    "/api/activation/v1/validate": {
      "post": {
        "operationId": "activation_v1_validate_create",
        "description": "\u00a73.2 \u2014 heartbeat: state / revocation / superseding token, signed.",
        "tags": [
          "activation"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create validate"
      }
    },
    "/api/ai/analyze-device/": {
      "post": {
        "operationId": "ai_analyze_device_create",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create analyze device"
      }
    },
    "/api/ai/analyze-screen/": {
      "post": {
        "operationId": "ai_analyze_screen_create",
        "description": "Vision + live-state helper. Looks at a screenshot of the app and, using RBAC-scoped\nread tools, diagnoses what the user is seeing / any error and tells them what to do next.\n\nRoutes through the configured default AIProvider: an 'openai_compatible' provider\n(e.g. OpenAI GPT-4o) uses the OpenAI vision + function-calling loop; otherwise it falls\nback to Anthropic + ANTHROPIC_API_KEY. Both drive the same RBAC-scoped SCREEN_TOOLS.",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create analyze screen"
      }
    },
    "/api/ai/analyze-waf/": {
      "post": {
        "operationId": "ai_analyze_waf_create",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create analyze waf"
      }
    },
    "/api/ai/appbuilder-build/": {
      "post": {
        "operationId": "ai_appbuilder_build_create",
        "description": "App Builder AI that actually creates app components from a description.",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create appbuilder build"
      }
    },
    "/api/ai/appbuilder-chat/": {
      "post": {
        "operationId": "ai_appbuilder_chat_create",
        "description": "App Builder AI guide \u2014 walks admins through building Versus apps.",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create appbuilder chat"
      }
    },
    "/api/ai/chat/": {
      "post": {
        "operationId": "ai_chat_create",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create chat"
      }
    },
    "/api/ai/generate-report/": {
      "post": {
        "operationId": "ai_generate_report_create",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create generate report"
      }
    },
    "/api/ai/panel-chat/": {
      "post": {
        "operationId": "ai_panel_chat_create",
        "description": "Streaming-compatible chat with automatic environment context injection.",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create panel chat"
      }
    },
    "/api/ai/suggest-irule/": {
      "post": {
        "operationId": "ai_suggest_irule_create",
        "tags": [
          "ai"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create suggest irule"
      }
    },
    "/api/audit-log/": {
      "get": {
        "operationId": "audit_log_list",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "in": "query",
            "name": "action",
            "schema": {
              "type": "string",
              "enum": [
                "backup",
                "create",
                "delete",
                "login",
                "other",
                "toggle",
                "update",
                "upgrade"
              ]
            },
            "description": "* `create` - Create\n* `update` - Update\n* `delete` - Delete\n* `toggle` - Toggle\n* `upgrade` - Upgrade\n* `backup` - Backup\n* `login` - Login\n* `other` - Other"
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "resource_type",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "user",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "audit-log"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedAuditList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List audit logs"
      }
    },
    "/api/audit-log/{id}/": {
      "get": {
        "operationId": "audit_log_retrieve",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this audit.",
            "required": true
          }
        ],
        "tags": [
          "audit-log"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Audit"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve audit log"
      }
    },
    "/api/auth-backends/": {
      "get": {
        "operationId": "auth_backends_list",
        "description": "Configure pluggable auth backends. Super Admin only.",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedAuthBackendConfigList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List auth backends"
      },
      "post": {
        "operationId": "auth_backends_create",
        "description": "Configure pluggable auth backends. Super Admin only.",
        "tags": [
          "auth-backends"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create auth backend"
      }
    },
    "/api/auth-backends/{id}/": {
      "get": {
        "operationId": "auth_backends_retrieve",
        "description": "Configure pluggable auth backends. Super Admin only.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve auth backend"
      },
      "put": {
        "operationId": "auth_backends_update",
        "description": "Configure pluggable auth backends. Super Admin only.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update auth backend"
      },
      "patch": {
        "operationId": "auth_backends_partial_update",
        "description": "Configure pluggable auth backends. Super Admin only.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedAuthBackendConfigRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedAuthBackendConfigRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedAuthBackendConfigRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update auth backend"
      },
      "delete": {
        "operationId": "auth_backends_destroy",
        "description": "Configure pluggable auth backends. Super Admin only.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete auth backend"
      }
    },
    "/api/auth-backends/{id}/import_idp_metadata/": {
      "post": {
        "operationId": "auth_backends_import_idp_metadata_create",
        "description": "Parse IdP SAML metadata XML (or fetch from URL) and return extracted fields.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Import idp metadata: auth backend"
      }
    },
    "/api/auth-backends/{id}/sp_metadata/": {
      "get": {
        "operationId": "auth_backends_sp_metadata_retrieve",
        "description": "Generate SAML SP metadata XML from the saved config.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Sp metadata: auth backend"
      }
    },
    "/api/auth-backends/{id}/test/": {
      "post": {
        "operationId": "auth_backends_test_create",
        "description": "Test connectivity for a backend without saving credentials.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this auth backend config.",
            "required": true
          }
        ],
        "tags": [
          "auth-backends"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/AuthBackendConfigRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Test: auth backend"
      }
    },
    "/api/auth-backends/status/": {
      "get": {
        "operationId": "auth_backends_status_retrieve",
        "description": "Return enabled/disabled state of all four backends.",
        "tags": [
          "auth-backends"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AuthBackendConfig"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List status"
      }
    },
    "/api/auth/oidc/callback": {
      "get": {
        "operationId": "auth_oidc_callback_retrieve",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List callbacks"
      }
    },
    "/api/auth/oidc/enabled": {
      "get": {
        "operationId": "auth_oidc_enabled_retrieve",
        "description": "Public: lets the login page decide whether to show the SSO button.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List enableds"
      }
    },
    "/api/auth/oidc/login": {
      "get": {
        "operationId": "auth_oidc_login_retrieve",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List logins"
      }
    },
    "/api/auth/oidc/logout": {
      "get": {
        "operationId": "auth_oidc_logout_retrieve",
        "description": "RP-initiated single logout (VS-SPEC-IDENTITY-PLATFORM-001 \u00a77).\n\nClearing local tokens alone doesn't log the user out \u2014 the IdP session\nsurvives and the next SSO redirect logs them straight back in. This ends the\nIdP session via the discovered end_session_endpoint, then returns to the app\n(which, being SSO-only, lands on the IdP login form \u2014 i.e. actually signed out).",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List logouts"
      }
    },
    "/api/auth/saml/acs/": {
      "post": {
        "operationId": "auth_saml_acs_create",
        "description": "Assertion Consumer Service \u2014 receives the IdP POST after successful SSO.\nProcesses the assertion, creates/updates the user, issues a JWT,\nand redirects the browser to the frontend with tokens in the fragment.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create ac"
      }
    },
    "/api/auth/saml/login/": {
      "get": {
        "operationId": "auth_saml_login_retrieve",
        "description": "Redirects the browser to the IdP SSO URL.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List logins"
      }
    },
    "/api/auth/sso/callback": {
      "get": {
        "operationId": "auth_sso_callback_retrieve",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List callbacks"
      }
    },
    "/api/auth/sso/enabled": {
      "get": {
        "operationId": "auth_sso_enabled_retrieve",
        "description": "Public: lets the login page decide whether to show the SSO button.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List enableds"
      }
    },
    "/api/auth/sso/login": {
      "get": {
        "operationId": "auth_sso_login_retrieve",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List logins"
      }
    },
    "/api/auth/token/": {
      "post": {
        "operationId": "auth_token_create",
        "description": "Multi-backend login endpoint.\nReplaces the default SimpleJWT TokenObtainPairView.\nTries enabled auth backends in priority order, then resolves group-based roles.\n\nA user with a CONFIRMED TOTPDevice doesn't get tokens here \u2014 they get\na short-lived challenge and must complete TOTPVerifyView next. A user\nwith no device (every current user, as of Phase 0 \u2014 see the Phase 0\nplan) logs in exactly as before this endpoint existed.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create token"
      }
    },
    "/api/auth/token/refresh/": {
      "post": {
        "operationId": "auth_token_refresh_create",
        "description": "Takes a refresh type JSON web token and returns an access type JSON web\ntoken if the refresh token is valid.",
        "tags": [
          "auth"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenRefreshRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/TokenRefreshRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/TokenRefreshRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenRefresh"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create refresh"
      }
    },
    "/api/auth/totp/confirm/": {
      "post": {
        "operationId": "auth_totp_confirm_create",
        "description": "Verifies the first code from an authenticator app against the\ndevice TOTPEnrollView just created, marking it confirmed \u2014 from this\npoint on, LoginView requires it. Returns recovery codes exactly once;\nonly their hashes are ever stored.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create confirm"
      }
    },
    "/api/auth/totp/enroll/": {
      "post": {
        "operationId": "auth_totp_enroll_create",
        "description": "Starts (or restarts) TOTP enrollment for the current user \u2014 issues\na fresh, UNCONFIRMED device and a provisioning URI for an\nauthenticator app to scan. The device doesn't gate login until\nTOTPConfirmView verifies a code against it.\n\nRefuses to touch a CONFIRMED device: overwriting one here would let\nany request bearing a valid access token silently disable the second\nfactor (and a UI bug that re-mounts the enroll step would wipe a\nworking authenticator). Re-enrollment of a confirmed device needs an\nexplicit admin-driven reset, which deliberately doesn't exist yet.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create enroll"
      }
    },
    "/api/auth/totp/status/": {
      "get": {
        "operationId": "auth_totp_status_retrieve",
        "description": "Whether the current user has a confirmed authenticator \u2014 drives the\nself-service Security page.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List status"
      }
    },
    "/api/auth/totp/verify/": {
      "post": {
        "operationId": "auth_totp_verify_create",
        "description": "Completes login for a user LoginView returned mfa_required for.\nAccepts either a live TOTP `code` or a one-time `recovery_code`.",
        "tags": [
          "auth"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create verify"
      }
    },
    "/api/client-tools/": {
      "get": {
        "operationId": "client_tools_list",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "client-tools"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/ClientTool"
                  }
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List client tools"
      },
      "post": {
        "operationId": "client_tools_create",
        "tags": [
          "client-tools"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientToolRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ClientToolRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ClientToolRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientTool"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create client tool"
      }
    },
    "/api/client-tools/{filename}/": {
      "get": {
        "operationId": "client_tools_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "filename",
            "schema": {
              "type": "string",
              "pattern": "^[^/]+$"
            },
            "required": true
          }
        ],
        "tags": [
          "client-tools"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientTool"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve client tool"
      },
      "put": {
        "operationId": "client_tools_update",
        "parameters": [
          {
            "in": "path",
            "name": "filename",
            "schema": {
              "type": "string",
              "pattern": "^[^/]+$"
            },
            "required": true
          }
        ],
        "tags": [
          "client-tools"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientToolRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ClientToolRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ClientToolRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientTool"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update client tool"
      },
      "patch": {
        "operationId": "client_tools_partial_update",
        "parameters": [
          {
            "in": "path",
            "name": "filename",
            "schema": {
              "type": "string",
              "pattern": "^[^/]+$"
            },
            "required": true
          }
        ],
        "tags": [
          "client-tools"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedClientToolRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedClientToolRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedClientToolRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientTool"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update client tool"
      },
      "delete": {
        "operationId": "client_tools_destroy",
        "parameters": [
          {
            "in": "path",
            "name": "filename",
            "schema": {
              "type": "string",
              "pattern": "^[^/]+$"
            },
            "required": true
          }
        ],
        "tags": [
          "client-tools"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete client tool"
      }
    },
    "/api/client-tools/{filename}/download/": {
      "get": {
        "operationId": "client_tools_download_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "filename",
            "schema": {
              "type": "string",
              "pattern": "^[^/]+$"
            },
            "required": true
          }
        ],
        "tags": [
          "client-tools"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ClientTool"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Download: client tool"
      }
    },
    "/api/clients/": {
      "get": {
        "operationId": "clients_list",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "clients"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedClientList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List clients"
      },
      "post": {
        "operationId": "clients_create",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "tags": [
          "clients"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ClientRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ClientRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create client"
      }
    },
    "/api/clients/{id}/": {
      "get": {
        "operationId": "clients_retrieve",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this client.",
            "required": true
          }
        ],
        "tags": [
          "clients"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve client"
      },
      "put": {
        "operationId": "clients_update",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this client.",
            "required": true
          }
        ],
        "tags": [
          "clients"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ClientRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ClientRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ClientRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update client"
      },
      "patch": {
        "operationId": "clients_partial_update",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this client.",
            "required": true
          }
        ],
        "tags": [
          "clients"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedClientRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedClientRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedClientRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Client"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update client"
      },
      "delete": {
        "operationId": "clients_destroy",
        "description": "Deploy-safe base for making an existing DRF ModelViewSet tenant-isolated\n(VS-SPEC-TENANT-IDENTITY-001 \u00a714). Use as the FIRST base:\n\n    class DeviceViewSet(TenantScopedModelViewSet, viewsets.ModelViewSet):\n        queryset = Device.objects.select_related(...)\n        ...\n\nUnlike the strict TenantScopedViewSet pilot, this **degrades gracefully**:\nit is INERT unless the tenant_scoped alias is configured\n(TENANT_SCOPED_DATABASE_URL) AND the request carries a tenant_id claim.\nWhen inert it behaves exactly like a plain ModelViewSet \u2014 so the rollout\nlands additively and isolation switches on only once the non-superuser\nPostgres role exists (mirrors tenant_subdomain.py's \"inert unless\nconfigured\" contract). When active: reads route through the RLS-enforcing\nconnection and tenant_id is stamped server-side (never client input).",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this client.",
            "required": true
          }
        ],
        "tags": [
          "clients"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete client"
      }
    },
    "/api/default-roles/": {
      "get": {
        "operationId": "default_roles_list",
        "description": "Default roles are system-defined and read-only from the API.",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "default-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedDefaultRoleList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List default roles"
      }
    },
    "/api/default-roles/{id}/": {
      "get": {
        "operationId": "default_roles_retrieve",
        "description": "Default roles are system-defined and read-only from the API.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this default role.",
            "required": true
          }
        ],
        "tags": [
          "default-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DefaultRole"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve default role"
      }
    },
    "/api/default-roles/permissions_list/": {
      "get": {
        "operationId": "default_roles_permissions_list_retrieve",
        "description": "Return the full list of available permission strings.",
        "tags": [
          "default-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DefaultRole"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List permissions lists"
      }
    },
    "/api/group-mappings/": {
      "get": {
        "operationId": "group_mappings_list",
        "parameters": [
          {
            "in": "query",
            "name": "default_role",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "provider",
            "schema": {
              "type": "string",
              "enum": [
                "ldap",
                "local",
                "saml",
                "tacacs"
              ]
            },
            "description": "* `ldap` - AD / LDAP\n* `saml` - SAML / SSO\n* `tacacs` - TACACS+\n* `local` - Local"
          },
          {
            "in": "query",
            "name": "scoped_role",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "group-mappings"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedGroupMappingList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List group mappings"
      },
      "post": {
        "operationId": "group_mappings_create",
        "tags": [
          "group-mappings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupMappingRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/GroupMappingRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/GroupMappingRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupMapping"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create group mapping"
      }
    },
    "/api/group-mappings/{id}/": {
      "get": {
        "operationId": "group_mappings_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this group mapping.",
            "required": true
          }
        ],
        "tags": [
          "group-mappings"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupMapping"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve group mapping"
      },
      "put": {
        "operationId": "group_mappings_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this group mapping.",
            "required": true
          }
        ],
        "tags": [
          "group-mappings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GroupMappingRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/GroupMappingRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/GroupMappingRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupMapping"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update group mapping"
      },
      "patch": {
        "operationId": "group_mappings_partial_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this group mapping.",
            "required": true
          }
        ],
        "tags": [
          "group-mappings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedGroupMappingRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedGroupMappingRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedGroupMappingRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GroupMapping"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update group mapping"
      },
      "delete": {
        "operationId": "group_mappings_destroy",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this group mapping.",
            "required": true
          }
        ],
        "tags": [
          "group-mappings"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete group mapping"
      }
    },
    "/api/import-jobs/": {
      "get": {
        "operationId": "import_jobs_list",
        "parameters": [
          {
            "in": "query",
            "name": "device",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "status",
            "schema": {
              "type": "string",
              "enum": [
                "completed",
                "failed",
                "pending",
                "running"
              ]
            },
            "description": "* `pending` - Pending\n* `running` - Running\n* `completed` - Completed\n* `failed` - Failed"
          }
        ],
        "tags": [
          "import-jobs"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedDeviceImportJobList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List import jobs"
      }
    },
    "/api/import-jobs/{id}/": {
      "get": {
        "operationId": "import_jobs_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this device import job.",
            "required": true
          }
        ],
        "tags": [
          "import-jobs"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceImportJob"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve import job"
      }
    },
    "/api/internal/idp/confirm-totp": {
      "post": {
        "operationId": "internal_idp_confirm_totp_create",
        "tags": [
          "internal"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create confirm totp"
      }
    },
    "/api/internal/idp/enroll-totp": {
      "post": {
        "operationId": "internal_idp_enroll_totp_create",
        "tags": [
          "internal"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create enroll totp"
      }
    },
    "/api/internal/idp/userinfo": {
      "get": {
        "operationId": "internal_idp_userinfo_retrieve",
        "tags": [
          "internal"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List userinfos"
      }
    },
    "/api/internal/idp/verify-password": {
      "post": {
        "operationId": "internal_idp_verify_password_create",
        "tags": [
          "internal"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create verify password"
      }
    },
    "/api/internal/idp/verify-totp": {
      "post": {
        "operationId": "internal_idp_verify_totp_create",
        "tags": [
          "internal"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create verify totp"
      }
    },
    "/api/licensing/activate": {
      "post": {
        "operationId": "licensing_activate_create",
        "description": "Online activation: exchange an activation code for a node-bound license\n(VS-SPEC-LICENSE-ACTIVATION-001 \u00a73.1). Reuses apply_license for storage.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create activate"
      }
    },
    "/api/licensing/apply": {
      "post": {
        "operationId": "licensing_apply_create",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create apply"
      }
    },
    "/api/licensing/fingerprint": {
      "get": {
        "operationId": "licensing_fingerprint_retrieve",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List fingerprints"
      }
    },
    "/api/licensing/issue": {
      "post": {
        "operationId": "licensing_issue_create",
        "description": "Sign a new license token (issuer side). The Ed25519 private key comes from\nthe LICENSE_SIGNING_KEY env var \u2014 never from the client \u2014 so the secret stays\non the server. Returns the token plus the decoded payload for display.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create issue"
      }
    },
    "/api/licensing/issue-meta": {
      "get": {
        "operationId": "licensing_issue_meta_retrieve",
        "description": "Form metadata for the Control Plane license generator: the feature\ncatalogue and whether a signing key is configured on this server.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List issue metas"
      }
    },
    "/api/licensing/pricing": {
      "get": {
        "operationId": "licensing_pricing_retrieve",
        "description": "Reference pricing model for the quote generator (units, bands, discounts).",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List pricings"
      }
    },
    "/api/licensing/pricing-config": {
      "get": {
        "operationId": "licensing_pricing_config_retrieve",
        "description": "Read / edit / reset the quote Rate Card. GET returns the effective config\n(defaults + saved overrides) plus the code defaults; PUT saves an edited\nconfig; DELETE reverts to defaults.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List pricing configs"
      },
      "put": {
        "operationId": "licensing_pricing_config_update",
        "description": "Read / edit / reset the quote Rate Card. GET returns the effective config\n(defaults + saved overrides) plus the code defaults; PUT saves an edited\nconfig; DELETE reverts to defaults.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Update pricing config"
      },
      "delete": {
        "operationId": "licensing_pricing_config_destroy",
        "description": "Read / edit / reset the quote Rate Card. GET returns the effective config\n(defaults + saved overrides) plus the code defaults; PUT saves an edited\nconfig; DELETE reverts to defaults.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete pricing config"
      }
    },
    "/api/licensing/quote": {
      "post": {
        "operationId": "licensing_quote_create",
        "description": "Price a quote from per-module quantities + bundle + term.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create quote"
      }
    },
    "/api/licensing/quote.xlsx": {
      "post": {
        "operationId": "licensing_quote.xlsx_create",
        "description": "Return the quote as a Versus-branded .xlsx download.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create quote.xlsx"
      }
    },
    "/api/licensing/status": {
      "get": {
        "operationId": "licensing_status_retrieve",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List status"
      }
    },
    "/api/licensing/validate": {
      "post": {
        "operationId": "licensing_validate_create",
        "description": "'Check now' \u2014 run one heartbeat against the license server and return the\nrefreshed status. Offline-safe: an unreachable server is not an error.",
        "tags": [
          "licensing"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create validate"
      }
    },
    "/api/options/{provider}/": {
      "get": {
        "operationId": "options_retrieve",
        "description": "Dynamic options provider for form fields.\nGET /api/options/{provider}?...\n\nRegistered providers:\n  dns_zones   \u2014 forward DNS zones from IPAM\n  devices     \u2014 managed devices (id, name, hostname, vendor)\n  environments \u2014 placeholder; environments come from entitlements",
        "parameters": [
          {
            "in": "path",
            "name": "provider",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "options"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Retrieve option"
      }
    },
    "/api/public/kb/{public_slug}/{page_slug}/": {
      "get": {
        "operationId": "public_kb_retrieve",
        "description": "UNAUTHENTICATED read-only page render (spec \u00a77/\u00a79 rule 6).\n\nNo JWT tenant claim: resolve the tenant from the space's public_slug on the\ndefault connection, then read the page under tenant_context(space.tenant_id).\nServes the cached, allow-listed rendered_html only (spec \u00a75) \u2014 no draft,\ncomment, restriction, or attachment-upload affordances. Because this bypasses\nEntitlementMiddleware (no Bearer token), it re-checks per-module entitlement\nbefore serving any gated-module data a smart block would surface (spec \u00a79).",
        "parameters": [
          {
            "in": "path",
            "name": "page_slug",
            "schema": {
              "type": "string"
            },
            "required": true
          },
          {
            "in": "path",
            "name": "public_slug",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "public"
        ],
        "security": [
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Retrieve kb"
      }
    },
    "/api/public/v1/set-password": {
      "post": {
        "operationId": "public_v1_set_password_create",
        "description": "Public invite completion for Versus-IdP tenants (POST\n/api/public/v1/set-password). Sets the invitee's Zitadel password from the\none-time code in their invite link, so the whole set-password step happens\ninside versus-demo \u2014 the invitee never lands in Zitadel's hosted console.",
        "tags": [
          "public"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create set password"
      }
    },
    "/api/public/v1/tenant-registrations/{token}/": {
      "post": {
        "operationId": "public_v1_tenant_registrations_create",
        "description": "Public registration completion (spec \u00a72.4 steps 1-2) \u2014 POST\n/api/public/v1/tenant-registrations/<token>/. Validates the\ninvitation token, creates the User + TenantMembership, and mints\ntokens immediately (a brand-new user has no TOTP device yet, so\nLoginView's second-factor gate doesn't apply). The frontend doesn't\ntreat registration as DONE until it's also driven the existing Phase\n0 TOTPEnrollView/TOTPConfirmView/EulaAcceptView with those tokens \u2014\nthis view only ever completes steps 1-2 of \u00a72.4's fail-closed list.",
        "parameters": [
          {
            "in": "path",
            "name": "token",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "public"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create tenant registration"
      }
    },
    "/api/public/v1/tenant-requests": {
      "post": {
        "operationId": "public_v1_tenant_requests_create",
        "description": "Public intake (spec \u00a72.1) \u2014 POST /api/public/v1/tenant-requests.\nCreates a TenantRequest row only; nothing is provisioned until an\nadmin approves it (spec D-6 \u2014 no auto-approval).",
        "tags": [
          "public"
        ],
        "security": [
          {
            "jwtAuth": []
          },
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create tenant request"
      }
    },
    "/api/role-assignments/": {
      "get": {
        "operationId": "role_assignments_list",
        "description": "Manage manual scoped-role assignments to specific users.",
        "parameters": [
          {
            "in": "query",
            "name": "assignment_source",
            "schema": {
              "type": "string",
              "enum": [
                "group_match",
                "manual"
              ]
            },
            "description": "* `group_match` - Group Match\n* `manual` - Manual"
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "in": "query",
            "name": "scoped_role",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          },
          {
            "in": "query",
            "name": "user",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "tags": [
          "role-assignments"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedUserRoleAssignmentList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List role assignments"
      },
      "post": {
        "operationId": "role_assignments_create",
        "description": "Manage manual scoped-role assignments to specific users.",
        "tags": [
          "role-assignments"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleAssignmentRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleAssignmentRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleAssignmentRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRoleAssignment"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create role assignment"
      }
    },
    "/api/role-assignments/{id}/": {
      "get": {
        "operationId": "role_assignments_retrieve",
        "description": "Manage manual scoped-role assignments to specific users.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user role assignment.",
            "required": true
          }
        ],
        "tags": [
          "role-assignments"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRoleAssignment"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve role assignment"
      },
      "put": {
        "operationId": "role_assignments_update",
        "description": "Manage manual scoped-role assignments to specific users.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user role assignment.",
            "required": true
          }
        ],
        "tags": [
          "role-assignments"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleAssignmentRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleAssignmentRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRoleAssignmentRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRoleAssignment"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update role assignment"
      },
      "patch": {
        "operationId": "role_assignments_partial_update",
        "description": "Manage manual scoped-role assignments to specific users.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user role assignment.",
            "required": true
          }
        ],
        "tags": [
          "role-assignments"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRoleAssignmentRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRoleAssignmentRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRoleAssignmentRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRoleAssignment"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update role assignment"
      },
      "delete": {
        "operationId": "role_assignments_destroy",
        "description": "Manage manual scoped-role assignments to specific users.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user role assignment.",
            "required": true
          }
        ],
        "tags": [
          "role-assignments"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete role assignment"
      }
    },
    "/api/role-assignments/for-user/{user_id}/": {
      "get": {
        "operationId": "role_assignments_for_user_retrieve",
        "description": "Manage manual scoped-role assignments to specific users.",
        "parameters": [
          {
            "in": "path",
            "name": "user_id",
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            },
            "required": true
          }
        ],
        "tags": [
          "role-assignments"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserRoleAssignment"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve for user"
      }
    },
    "/api/roles/": {
      "get": {
        "operationId": "roles_list",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedRoleList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List roles"
      },
      "post": {
        "operationId": "roles_create",
        "tags": [
          "roles"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/RoleRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/RoleRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create role"
      }
    },
    "/api/roles/{id}/": {
      "get": {
        "operationId": "roles_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this role.",
            "required": true
          }
        ],
        "tags": [
          "roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve role"
      },
      "put": {
        "operationId": "roles_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this role.",
            "required": true
          }
        ],
        "tags": [
          "roles"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RoleRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/RoleRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/RoleRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update role"
      },
      "patch": {
        "operationId": "roles_partial_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this role.",
            "required": true
          }
        ],
        "tags": [
          "roles"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedRoleRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedRoleRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedRoleRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Role"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update role"
      },
      "delete": {
        "operationId": "roles_destroy",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this role.",
            "required": true
          }
        ],
        "tags": [
          "roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete role"
      }
    },
    "/api/scoped-roles/": {
      "get": {
        "operationId": "scoped_roles_list",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "scoped-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedScopedRoleList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List scoped roles"
      },
      "post": {
        "operationId": "scoped_roles_create",
        "tags": [
          "scoped-roles"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScopedRoleWriteRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ScopedRoleWriteRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ScopedRoleWriteRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScopedRoleWrite"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create scoped role"
      }
    },
    "/api/scoped-roles/{id}/": {
      "get": {
        "operationId": "scoped_roles_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this scoped role.",
            "required": true
          }
        ],
        "tags": [
          "scoped-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScopedRole"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve scoped role"
      },
      "put": {
        "operationId": "scoped_roles_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this scoped role.",
            "required": true
          }
        ],
        "tags": [
          "scoped-roles"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScopedRoleWriteRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/ScopedRoleWriteRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/ScopedRoleWriteRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScopedRoleWrite"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update scoped role"
      },
      "patch": {
        "operationId": "scoped_roles_partial_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this scoped role.",
            "required": true
          }
        ],
        "tags": [
          "scoped-roles"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedScopedRoleWriteRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedScopedRoleWriteRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedScopedRoleWriteRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScopedRoleWrite"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update scoped role"
      },
      "delete": {
        "operationId": "scoped_roles_destroy",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this scoped role.",
            "required": true
          }
        ],
        "tags": [
          "scoped-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete scoped role"
      }
    },
    "/api/scoped-roles/{id}/assignments/": {
      "get": {
        "operationId": "scoped_roles_assignments_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this scoped role.",
            "required": true
          }
        ],
        "tags": [
          "scoped-roles"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScopedRole"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Assignments: scoped role"
      }
    },
    "/api/search/": {
      "get": {
        "operationId": "search_retrieve",
        "tags": [
          "search"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List searchs"
      }
    },
    "/api/settings/": {
      "get": {
        "operationId": "settings_list",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "settings"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedSystemSettingsList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List settings"
      },
      "post": {
        "operationId": "settings_create",
        "tags": [
          "settings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemSettings"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create setting"
      }
    },
    "/api/settings/{id}/": {
      "get": {
        "operationId": "settings_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this system settings.",
            "required": true
          }
        ],
        "tags": [
          "settings"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemSettings"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve setting"
      },
      "put": {
        "operationId": "settings_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this system settings.",
            "required": true
          }
        ],
        "tags": [
          "settings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemSettings"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update setting"
      },
      "patch": {
        "operationId": "settings_partial_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this system settings.",
            "required": true
          }
        ],
        "tags": [
          "settings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedSystemSettingsRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedSystemSettingsRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedSystemSettingsRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemSettings"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update setting"
      },
      "delete": {
        "operationId": "settings_destroy",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this system settings.",
            "required": true
          }
        ],
        "tags": [
          "settings"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete setting"
      }
    },
    "/api/settings/bulk_update/": {
      "post": {
        "operationId": "settings_bulk_update_create",
        "tags": [
          "settings"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/SystemSettingsRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SystemSettings"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create bulk update"
      }
    },
    "/api/support/ask/": {
      "post": {
        "operationId": "support_ask_create",
        "description": "POST /api/support/ask/  {question, conversation_id?}\n  \u2192 grounded, cited answer + known-issue overlay, persisted as a conversation\n    so follow-up questions have context (P1 multi-turn).\n\nRequires an authenticated caller (avoids an open, abusable LLM endpoint);\nanonymous public access + rate-limiting/captcha is the next step per the spec.",
        "tags": [
          "support"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create ask"
      }
    },
    "/api/support/escalate/": {
      "post": {
        "operationId": "support_escalate_create",
        "description": "POST /api/support/escalate/  {conversation_id, reason?}\n\u2192 opens a real Versus Desk incident (INC) seeded with the transcript,\n  scoped to the caller's tenant. Returns the ticket number (P1).",
        "tags": [
          "support"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create escalate"
      }
    },
    "/api/support/public/ask/": {
      "post": {
        "operationId": "support_public_ask_create",
        "description": "POST /api/support/public/ask/  {question, conversation_id?}\n  \u2192 the anonymous support-site copilot (VS-SPEC-SUPPORT-COPILOT-001 P2).\n\nSHIPS INERT: returns 403 unless settings.SUPPORT_PUBLIC_ENABLED is turned on,\nso deploying this does NOT open a public LLM endpoint. When enabled it is\nanonymous (AllowAny), IP rate-limited, length-capped, answers ONLY from the\npublic doc corpus, and NEVER exposes the internal Sentinel known-issue overlay.",
        "tags": [
          "support"
        ],
        "security": [
          {}
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create ask"
      }
    },
    "/api/tenant-admin/meta/": {
      "get": {
        "operationId": "tenant_admin_meta_retrieve",
        "description": "/api/tenant-admin/meta/ \u2014 assignable roles + context for the console UI.",
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List metas"
      }
    },
    "/api/tenant-admin/users/": {
      "get": {
        "operationId": "tenant_admin_users_retrieve",
        "description": "/api/tenant-admin/users/ \u2014 org-scoped user administration.",
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List users"
      },
      "post": {
        "operationId": "tenant_admin_users_create",
        "description": "Invite a user: {email, first_name?, last_name?, role?}.",
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "description": "No response body"
          }
        },
        "summary": "Create user"
      }
    },
    "/api/tenant-admin/users/{id}/": {
      "delete": {
        "operationId": "tenant_admin_users_destroy",
        "description": "/api/tenant-admin/users/ \u2014 org-scoped user administration.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete user"
      }
    },
    "/api/tenant-admin/users/{id}/deactivate/": {
      "post": {
        "operationId": "tenant_admin_users_deactivate_create",
        "description": "/api/tenant-admin/users/ \u2014 org-scoped user administration.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Deactivate: user"
      }
    },
    "/api/tenant-admin/users/{id}/reactivate/": {
      "post": {
        "operationId": "tenant_admin_users_reactivate_create",
        "description": "/api/tenant-admin/users/ \u2014 org-scoped user administration.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Reactivate: user"
      }
    },
    "/api/tenant-admin/users/{id}/role/": {
      "post": {
        "operationId": "tenant_admin_users_role_create",
        "description": "/api/tenant-admin/users/ \u2014 org-scoped user administration.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string"
            },
            "required": true
          }
        ],
        "tags": [
          "tenant-admin"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Role: user"
      }
    },
    "/api/tenants/eula/accept/": {
      "post": {
        "operationId": "tenants_eula_accept_create",
        "description": "Records an immutable acceptance (spec \u00a76) \u2014 body_sha256 is\ncomputed server-side from the version's own stored text, never\ntrusted from the client, so the acceptance record can't be forged to\nclaim agreement to different words than what's actually on file.",
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "Create accept"
      }
    },
    "/api/tenants/eula/current/": {
      "get": {
        "operationId": "tenants_eula_current_retrieve",
        "description": "The version a registration/login flow should show and require\nacceptance of \u2014 not wired into any flow yet (Phase 1 does that), but\nreal and callable now.",
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List currents"
      }
    },
    "/api/tenants/my-entitlement/": {
      "get": {
        "operationId": "tenants_my_entitlement_retrieve",
        "description": "The caller's tenant entitlement (VS-SPEC-SAAS-LICENSING-001) \u2014 the module\nkeys + plan the SPA uses to gate navigation. Enforcement off, or a tenant\nwith no (effective) entitlement, returns all modules (full access).",
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List my entitlements"
      }
    },
    "/api/tenants/notes/": {
      "get": {
        "operationId": "tenants_notes_list",
        "description": "The RLS + envelope-encryption pilot's only endpoint. The queryset\nbelow is DELIBERATELY not filtered by tenant_id in Python \u2014 that's\nthe point of this pilot: isolation comes entirely from the Postgres\nRLS policy (migrations/0003_tenant_note_rls.py) plus the SET LOCAL\nTenantScopedViewSet.initial() performs, not from application code. If\nthat ever silently regresses, this endpoint would start leaking rows\nacross tenants and the RLS conformance test (tests/test_rls.py)\nshould catch it before this does in production.",
        "parameters": [
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedTenantNoteList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List notes"
      },
      "post": {
        "operationId": "tenants_notes_create",
        "description": "The RLS + envelope-encryption pilot's only endpoint. The queryset\nbelow is DELIBERATELY not filtered by tenant_id in Python \u2014 that's\nthe point of this pilot: isolation comes entirely from the Postgres\nRLS policy (migrations/0003_tenant_note_rls.py) plus the SET LOCAL\nTenantScopedViewSet.initial() performs, not from application code. If\nthat ever silently regresses, this endpoint would start leaking rows\nacross tenants and the RLS conformance test (tests/test_rls.py)\nshould catch it before this does in production.",
        "tags": [
          "tenants"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantNoteRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/TenantNoteRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/TenantNoteRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantNote"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create note"
      }
    },
    "/api/tenants/notes/{id}/": {
      "get": {
        "operationId": "tenants_notes_retrieve",
        "description": "The RLS + envelope-encryption pilot's only endpoint. The queryset\nbelow is DELIBERATELY not filtered by tenant_id in Python \u2014 that's\nthe point of this pilot: isolation comes entirely from the Postgres\nRLS policy (migrations/0003_tenant_note_rls.py) plus the SET LOCAL\nTenantScopedViewSet.initial() performs, not from application code. If\nthat ever silently regresses, this endpoint would start leaking rows\nacross tenants and the RLS conformance test (tests/test_rls.py)\nshould catch it before this does in production.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A UUID string identifying this tenant note.",
            "required": true
          }
        ],
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantNote"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve note"
      },
      "put": {
        "operationId": "tenants_notes_update",
        "description": "The RLS + envelope-encryption pilot's only endpoint. The queryset\nbelow is DELIBERATELY not filtered by tenant_id in Python \u2014 that's\nthe point of this pilot: isolation comes entirely from the Postgres\nRLS policy (migrations/0003_tenant_note_rls.py) plus the SET LOCAL\nTenantScopedViewSet.initial() performs, not from application code. If\nthat ever silently regresses, this endpoint would start leaking rows\nacross tenants and the RLS conformance test (tests/test_rls.py)\nshould catch it before this does in production.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A UUID string identifying this tenant note.",
            "required": true
          }
        ],
        "tags": [
          "tenants"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantNoteRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/TenantNoteRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/TenantNoteRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantNote"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update note"
      },
      "patch": {
        "operationId": "tenants_notes_partial_update",
        "description": "The RLS + envelope-encryption pilot's only endpoint. The queryset\nbelow is DELIBERATELY not filtered by tenant_id in Python \u2014 that's\nthe point of this pilot: isolation comes entirely from the Postgres\nRLS policy (migrations/0003_tenant_note_rls.py) plus the SET LOCAL\nTenantScopedViewSet.initial() performs, not from application code. If\nthat ever silently regresses, this endpoint would start leaking rows\nacross tenants and the RLS conformance test (tests/test_rls.py)\nshould catch it before this does in production.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A UUID string identifying this tenant note.",
            "required": true
          }
        ],
        "tags": [
          "tenants"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedTenantNoteRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedTenantNoteRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedTenantNoteRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantNote"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update note"
      },
      "delete": {
        "operationId": "tenants_notes_destroy",
        "description": "The RLS + envelope-encryption pilot's only endpoint. The queryset\nbelow is DELIBERATELY not filtered by tenant_id in Python \u2014 that's\nthe point of this pilot: isolation comes entirely from the Postgres\nRLS policy (migrations/0003_tenant_note_rls.py) plus the SET LOCAL\nTenantScopedViewSet.initial() performs, not from application code. If\nthat ever silently regresses, this endpoint would start leaking rows\nacross tenants and the RLS conformance test (tests/test_rls.py)\nshould catch it before this does in production.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "description": "A UUID string identifying this tenant note.",
            "required": true
          }
        ],
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete note"
      }
    },
    "/api/tenants/setup-status/": {
      "get": {
        "operationId": "tenants_setup_status_retrieve",
        "description": "Tells the frontend whether the logged-in user still needs to finish\nmandatory account setup (MFA + EULA) \u2014 e.g. after a registration flow\nthat was interrupted between steps 1 and 3. Only enforced for tenant\nusers (TenantMembership holders); pre-Phase-0 staff accounts are exempt\nper the decision to make MFA mandatory only going forward, not\nretroactively (see apps/tenants CLAUDE.md history).",
        "tags": [
          "tenants"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "No response body"
          }
        },
        "summary": "List setup status"
      }
    },
    "/api/users/": {
      "get": {
        "operationId": "users_list",
        "parameters": [
          {
            "in": "query",
            "name": "is_active",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "in": "query",
            "name": "is_staff",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "ordering",
            "required": false,
            "in": "query",
            "description": "Which field to use when ordering the results.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "A page number within the paginated result set.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "page_size",
            "required": false,
            "in": "query",
            "description": "Number of results to return per page.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "search",
            "required": false,
            "in": "query",
            "description": "A search term.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "tags": [
          "users"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaginatedUserList"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List users"
      },
      "post": {
        "operationId": "users_create",
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserCreateRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserCreateRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserCreateRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserCreate"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create user"
      }
    },
    "/api/users/{id}/": {
      "get": {
        "operationId": "users_retrieve",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Retrieve user"
      },
      "put": {
        "operationId": "users_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update user"
      },
      "patch": {
        "operationId": "users_partial_update",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update user"
      },
      "delete": {
        "operationId": "users_destroy",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "No response body"
          }
        },
        "summary": "Delete user"
      }
    },
    "/api/users/{id}/reset-mfa/": {
      "post": {
        "operationId": "users_reset_mfa_create",
        "description": "Admin: clear a user's TOTP device so they can re-enrol \u2014 lockout\nrecovery for someone who lost their authenticator (there is no\nself-service disable). Network-Admin (level 4+) only.",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Reset mfa: user"
      }
    },
    "/api/users/{id}/review-request/": {
      "post": {
        "operationId": "users_review_request_create",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Review request: user"
      }
    },
    "/api/users/{id}/set-role/": {
      "post": {
        "operationId": "users_set_role_create",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Set role: user"
      }
    },
    "/api/users/{id}/set_password/": {
      "post": {
        "operationId": "users_set_password_create",
        "parameters": [
          {
            "in": "path",
            "name": "id",
            "schema": {
              "type": "integer"
            },
            "description": "A unique integer value identifying this user.",
            "required": true
          }
        ],
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Set password: user"
      }
    },
    "/api/users/me/": {
      "get": {
        "operationId": "users_me_retrieve",
        "tags": [
          "users"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List mes"
      },
      "patch": {
        "operationId": "users_me_partial_update",
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/PatchedUserRequest"
              }
            }
          }
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Update me"
      }
    },
    "/api/users/my-role-request/": {
      "get": {
        "operationId": "users_my_role_request_retrieve",
        "tags": [
          "users"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List my role requests"
      }
    },
    "/api/users/request-role/": {
      "post": {
        "operationId": "users_request_role_create",
        "tags": [
          "users"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            },
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/UserRequest"
              }
            }
          },
          "required": true
        },
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "Create request role"
      }
    },
    "/api/users/role-requests/": {
      "get": {
        "operationId": "users_role_requests_retrieve",
        "tags": [
          "users"
        ],
        "security": [
          {
            "jwtAuth": []
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/User"
                }
              }
            },
            "description": ""
          }
        },
        "summary": "List role requests"
      }
    }
  },
  "components": {
    "schemas": {
      "PatchedUserRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
            "pattern": "^[\\w.@+-]+$",
            "maxLength": 150
          },
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email address",
            "maxLength": 254
          },
          "first_name": {
            "type": "string",
            "maxLength": 150
          },
          "last_name": {
            "type": "string",
            "maxLength": 150
          },
          "is_active": {
            "type": "boolean",
            "title": "Active",
            "description": "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
          },
          "is_staff": {
            "type": "boolean",
            "title": "Staff status",
            "description": "Designates whether the user can log into this admin site."
          }
        }
      },
      "GroupMapping": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "external_group": {
            "type": "string",
            "maxLength": 255
          },
          "provider": {
            "$ref": "#/components/schemas/GroupMappingProviderEnum"
          },
          "default_role": {
            "type": "integer",
            "nullable": true
          },
          "default_role_name": {
            "type": "string",
            "readOnly": true
          },
          "scoped_role": {
            "type": "integer",
            "nullable": true
          },
          "scoped_role_name": {
            "type": "string",
            "readOnly": true
          }
        },
        "required": [
          "default_role_name",
          "external_group",
          "id",
          "provider",
          "scoped_role_name"
        ]
      },
      "TokenRefresh": {
        "type": "object",
        "properties": {
          "access": {
            "type": "string",
            "readOnly": true
          },
          "refresh": {
            "type": "string"
          }
        },
        "required": [
          "access",
          "refresh"
        ]
      },
      "Client": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "device_count": {
            "type": "string",
            "readOnly": true
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "contact_name": {
            "type": "string",
            "maxLength": 150
          },
          "contact_email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "contact_phone": {
            "type": "string",
            "maxLength": 50
          },
          "distribution_group": {
            "type": "string",
            "description": "Email distribution list for notifications",
            "maxLength": 150
          },
          "ad_group": {
            "type": "string",
            "description": "Active Directory group for access control",
            "maxLength": 150
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "created_at",
          "device_count",
          "id",
          "name"
        ]
      },
      "UserRoleAssignmentRequest": {
        "type": "object",
        "properties": {
          "user": {
            "type": "integer"
          },
          "scoped_role": {
            "type": "integer"
          }
        },
        "required": [
          "scoped_role",
          "user"
        ]
      },
      "PaginatedScopedRoleList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScopedRole"
            }
          }
        }
      },
      "AssignmentSourceEnum": {
        "enum": [
          "group_match",
          "manual"
        ],
        "type": "string",
        "description": "* `group_match` - Group Match\n* `manual` - Manual"
      },
      "ScopedRole": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceScope"
            },
            "readOnly": true
          },
          "assignment_count": {
            "type": "string",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "assignment_count",
          "created_at",
          "id",
          "name",
          "scopes",
          "updated_at"
        ]
      },
      "GroupMappingRequest": {
        "type": "object",
        "properties": {
          "external_group": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "provider": {
            "$ref": "#/components/schemas/GroupMappingProviderEnum"
          },
          "default_role": {
            "type": "integer",
            "nullable": true
          },
          "scoped_role": {
            "type": "integer",
            "nullable": true
          }
        },
        "required": [
          "external_group",
          "provider"
        ]
      },
      "PaginatedAuthBackendConfigList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AuthBackendConfig"
            }
          }
        }
      },
      "PatchedGroupMappingRequest": {
        "type": "object",
        "properties": {
          "external_group": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "provider": {
            "$ref": "#/components/schemas/GroupMappingProviderEnum"
          },
          "default_role": {
            "type": "integer",
            "nullable": true
          },
          "scoped_role": {
            "type": "integer",
            "nullable": true
          }
        }
      },
      "Status92bEnum": {
        "enum": [
          "pending",
          "running",
          "completed",
          "failed"
        ],
        "type": "string",
        "description": "* `pending` - Pending\n* `running` - Running\n* `completed` - Completed\n* `failed` - Failed"
      },
      "RoleRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "is_admin": {
            "type": "boolean"
          }
        },
        "required": [
          "name"
        ]
      },
      "DeviceImportJob": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "device": {
            "type": "integer"
          },
          "status": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Status92bEnum"
              }
            ],
            "readOnly": true
          },
          "progress": {
            "type": "integer",
            "readOnly": true
          },
          "current_step": {
            "type": "string",
            "readOnly": true
          },
          "log": {
            "type": "string",
            "readOnly": true
          },
          "error": {
            "type": "string",
            "readOnly": true
          },
          "started_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "created_at",
          "current_step",
          "device",
          "error",
          "finished_at",
          "id",
          "log",
          "progress",
          "started_at",
          "status"
        ]
      },
      "UserProfileRoleEnum": {
        "enum": [
          "admin",
          "operator",
          "cert_approver",
          "guest"
        ],
        "type": "string",
        "description": "* `admin` - Admin\n* `operator` - Operator\n* `cert_approver` - Cert Approver\n* `guest` - Guest"
      },
      "TokenRefreshRequest": {
        "type": "object",
        "properties": {
          "refresh": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "refresh"
        ]
      },
      "UserRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
            "pattern": "^[\\w.@+-]+$",
            "maxLength": 150
          },
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email address",
            "maxLength": 254
          },
          "first_name": {
            "type": "string",
            "maxLength": 150
          },
          "last_name": {
            "type": "string",
            "maxLength": 150
          },
          "is_active": {
            "type": "boolean",
            "title": "Active",
            "description": "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
          },
          "is_staff": {
            "type": "boolean",
            "title": "Staff status",
            "description": "Designates whether the user can log into this admin site."
          }
        },
        "required": [
          "username"
        ]
      },
      "SystemSettingsRequest": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "value": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": [
          "key"
        ]
      },
      "ClientRequest": {
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "contact_name": {
            "type": "string",
            "maxLength": 150
          },
          "contact_email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "contact_phone": {
            "type": "string",
            "maxLength": 50
          },
          "distribution_group": {
            "type": "string",
            "description": "Email distribution list for notifications",
            "maxLength": 150
          },
          "ad_group": {
            "type": "string",
            "description": "Active Directory group for access control",
            "maxLength": 150
          }
        },
        "required": [
          "name"
        ]
      },
      "DefaultRole": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "name": {
            "type": "string",
            "maxLength": 50
          },
          "slug": {
            "type": "string",
            "maxLength": 20
          },
          "level": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": -2147483648
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "user_count": {
            "type": "string",
            "readOnly": true
          }
        },
        "required": [
          "id",
          "level",
          "name",
          "slug",
          "user_count"
        ]
      },
      "UserRoleAssignment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "user": {
            "type": "integer"
          },
          "username": {
            "type": "string",
            "readOnly": true
          },
          "scoped_role": {
            "type": "integer"
          },
          "scoped_role_name": {
            "type": "string",
            "readOnly": true
          },
          "assignment_source": {
            "allOf": [
              {
                "$ref": "#/components/schemas/AssignmentSourceEnum"
              }
            ],
            "readOnly": true
          },
          "assigned_by": {
            "type": "integer",
            "readOnly": true,
            "nullable": true
          },
          "assigned_by_username": {
            "type": "string",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "assigned_by",
          "assigned_by_username",
          "assignment_source",
          "created_at",
          "id",
          "scoped_role",
          "scoped_role_name",
          "user",
          "username"
        ]
      },
      "PatchedTenantNoteRequest": {
        "type": "object",
        "description": "body is plaintext in/out; body_encrypted (the actual DB column) is\nnever exposed directly \u2014 this is the RLS + envelope-encryption pilot's\nserializer, proving both mechanisms end-to-end on one small model.",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "body": {
            "type": "string",
            "writeOnly": true,
            "minLength": 1
          }
        }
      },
      "AuditActionEnum": {
        "enum": [
          "create",
          "update",
          "delete",
          "toggle",
          "upgrade",
          "backup",
          "login",
          "other"
        ],
        "type": "string",
        "description": "* `create` - Create\n* `update` - Update\n* `delete` - Delete\n* `toggle` - Toggle\n* `upgrade` - Upgrade\n* `backup` - Backup\n* `login` - Login\n* `other` - Other"
      },
      "PaginatedUserRoleAssignmentList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UserRoleAssignment"
            }
          }
        }
      },
      "FontSizeEnum": {
        "enum": [
          "Small",
          "Normal",
          "Large"
        ],
        "type": "string",
        "description": "* `Small` - Small\n* `Normal` - Normal\n* `Large` - Large"
      },
      "TenantNoteRequest": {
        "type": "object",
        "description": "body is plaintext in/out; body_encrypted (the actual DB column) is\nnever exposed directly \u2014 this is the RLS + envelope-encryption pilot's\nserializer, proving both mechanisms end-to-end on one small model.",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "body": {
            "type": "string",
            "writeOnly": true,
            "minLength": 1
          }
        },
        "required": [
          "body",
          "title"
        ]
      },
      "PatchedUserRoleAssignmentRequest": {
        "type": "object",
        "properties": {
          "user": {
            "type": "integer"
          },
          "scoped_role": {
            "type": "integer"
          }
        }
      },
      "PaginatedRoleList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Role"
            }
          }
        }
      },
      "AuthBackendConfig": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "backend_type": {
            "$ref": "#/components/schemas/BackendTypeEnum"
          },
          "enabled": {
            "type": "boolean"
          },
          "priority": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": -2147483648
          },
          "config": {},
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "backend_type",
          "created_at",
          "id",
          "updated_at"
        ]
      },
      "PaginatedSystemSettingsList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SystemSettings"
            }
          }
        }
      },
      "ClientToolRequest": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "description": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "content",
          "filename"
        ]
      },
      "PatchedAuthBackendConfigRequest": {
        "type": "object",
        "properties": {
          "backend_type": {
            "$ref": "#/components/schemas/BackendTypeEnum"
          },
          "enabled": {
            "type": "boolean"
          },
          "priority": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": -2147483648
          },
          "config": {}
        }
      },
      "PatchedClientToolRequest": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "description": {
            "type": "string"
          },
          "content": {
            "type": "string",
            "minLength": 1
          }
        }
      },
      "ResourceScopeRequest": {
        "type": "object",
        "properties": {
          "resource_type": {
            "$ref": "#/components/schemas/ResourceTypeEnum"
          },
          "resource_id": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": -2147483648,
            "nullable": true
          },
          "resource_name": {
            "type": "string",
            "maxLength": 255
          }
        },
        "required": [
          "resource_type"
        ]
      },
      "PatchedSystemSettingsRequest": {
        "type": "object",
        "properties": {
          "key": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "value": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "User": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "username": {
            "type": "string",
            "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
            "pattern": "^[\\w.@+-]+$",
            "maxLength": 150
          },
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email address",
            "maxLength": 254
          },
          "first_name": {
            "type": "string",
            "maxLength": 150
          },
          "last_name": {
            "type": "string",
            "maxLength": 150
          },
          "full_name": {
            "type": "string",
            "readOnly": true
          },
          "role": {
            "type": "string",
            "readOnly": true
          },
          "role_level": {
            "type": "string",
            "readOnly": true
          },
          "role_name": {
            "type": "string",
            "readOnly": true
          },
          "permissions": {
            "type": "string",
            "readOnly": true
          },
          "scoped_roles": {
            "type": "string",
            "readOnly": true
          },
          "auth_source": {
            "type": "string",
            "readOnly": true
          },
          "is_tenant_admin": {
            "type": "string",
            "readOnly": true
          },
          "is_active": {
            "type": "boolean",
            "title": "Active",
            "description": "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
          },
          "is_staff": {
            "type": "boolean",
            "title": "Staff status",
            "description": "Designates whether the user can log into this admin site."
          },
          "last_login": {
            "type": "string",
            "format": "date-time",
            "readOnly": true,
            "nullable": true
          },
          "date_joined": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "profile": {
            "allOf": [
              {
                "$ref": "#/components/schemas/UserProfile"
              }
            ],
            "readOnly": true
          }
        },
        "required": [
          "auth_source",
          "date_joined",
          "full_name",
          "id",
          "is_tenant_admin",
          "last_login",
          "permissions",
          "profile",
          "role",
          "role_level",
          "role_name",
          "scoped_roles",
          "username"
        ]
      },
      "ResourceScope": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "resource_type": {
            "$ref": "#/components/schemas/ResourceTypeEnum"
          },
          "resource_id": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": -2147483648,
            "nullable": true
          },
          "resource_name": {
            "type": "string",
            "maxLength": 255
          }
        },
        "required": [
          "id",
          "resource_type"
        ]
      },
      "PaginatedDefaultRoleList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DefaultRole"
            }
          }
        }
      },
      "PaginatedUserList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/User"
            }
          }
        }
      },
      "PaginatedClientList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Client"
            }
          }
        }
      },
      "PaginatedAuditList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Audit"
            }
          }
        }
      },
      "UserCreateRequest": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "minLength": 1,
            "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
            "pattern": "^[\\w.@+-]+$",
            "maxLength": 150
          },
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email address",
            "maxLength": 254
          },
          "first_name": {
            "type": "string",
            "maxLength": 150
          },
          "last_name": {
            "type": "string",
            "maxLength": 150
          },
          "password": {
            "type": "string",
            "writeOnly": true,
            "minLength": 1
          },
          "role": {
            "type": "string",
            "writeOnly": true,
            "minLength": 1,
            "default": "guest"
          },
          "is_staff": {
            "type": "boolean",
            "title": "Staff status",
            "description": "Designates whether the user can log into this admin site."
          }
        },
        "required": [
          "password",
          "username"
        ]
      },
      "AuthBackendConfigRequest": {
        "type": "object",
        "properties": {
          "backend_type": {
            "$ref": "#/components/schemas/BackendTypeEnum"
          },
          "enabled": {
            "type": "boolean"
          },
          "priority": {
            "type": "integer",
            "maximum": 2147483647,
            "minimum": -2147483648
          },
          "config": {}
        },
        "required": [
          "backend_type"
        ]
      },
      "TenantNote": {
        "type": "object",
        "description": "body is plaintext in/out; body_encrypted (the actual DB column) is\nnever exposed directly \u2014 this is the RLS + envelope-encryption pilot's\nserializer, proving both mechanisms end-to-end on one small model.",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "title": {
            "type": "string",
            "maxLength": 200
          },
          "body_out": {
            "type": "string",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "body_out",
          "created_at",
          "id",
          "tenant_id",
          "title"
        ]
      },
      "Audit": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "user": {
            "type": "string",
            "maxLength": 100
          },
          "action": {
            "$ref": "#/components/schemas/AuditActionEnum"
          },
          "resource_type": {
            "type": "string",
            "maxLength": 100
          },
          "resource_id": {
            "type": "string",
            "maxLength": 100
          },
          "resource_name": {
            "type": "string",
            "maxLength": 200
          },
          "details": {},
          "ip_address": {
            "type": "string",
            "nullable": true
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "action",
          "id",
          "resource_type",
          "timestamp",
          "user"
        ]
      },
      "ClientTool": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "filename": {
            "type": "string",
            "maxLength": 255
          },
          "description": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "size": {
            "type": "integer",
            "readOnly": true
          },
          "uploaded_by": {
            "type": "string",
            "readOnly": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "content",
          "created_at",
          "filename",
          "id",
          "size",
          "updated_at",
          "uploaded_by"
        ]
      },
      "ScopedRoleWrite": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceScope"
            }
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "PatchedScopedRoleWriteRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceScopeRequest"
            }
          }
        }
      },
      "BackendTypeEnum": {
        "enum": [
          "local",
          "ldap",
          "saml",
          "tacacs"
        ],
        "type": "string",
        "description": "* `local` - Local\n* `ldap` - AD / LDAP\n* `saml` - SAML / SSO\n* `tacacs` - TACACS+"
      },
      "UserProfile": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "role": {
            "$ref": "#/components/schemas/UserProfileRoleEnum"
          },
          "auth_source": {
            "type": "string",
            "maxLength": 20
          },
          "external_groups": {},
          "last_group_sync": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "phone": {
            "type": "string",
            "maxLength": 50
          },
          "department": {
            "type": "string",
            "maxLength": 100
          },
          "avatar": {
            "type": "string",
            "maxLength": 500
          },
          "font_size": {
            "$ref": "#/components/schemas/FontSizeEnum"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          },
          "user": {
            "type": "integer"
          },
          "default_role": {
            "type": "integer",
            "nullable": true
          }
        },
        "required": [
          "created_at",
          "id",
          "user"
        ]
      },
      "Role": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "name": {
            "type": "string",
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "is_admin": {
            "type": "boolean"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "created_at",
          "id",
          "name"
        ]
      },
      "SystemSettings": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "readOnly": true
          },
          "key": {
            "type": "string",
            "maxLength": 100
          },
          "value": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "readOnly": true
          }
        },
        "required": [
          "id",
          "key",
          "updated_at"
        ]
      },
      "PaginatedGroupMappingList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/GroupMapping"
            }
          }
        }
      },
      "ScopedRoleWriteRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "scopes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ResourceScopeRequest"
            }
          }
        },
        "required": [
          "name"
        ]
      },
      "GroupMappingProviderEnum": {
        "enum": [
          "ldap",
          "saml",
          "tacacs",
          "local"
        ],
        "type": "string",
        "description": "* `ldap` - AD / LDAP\n* `saml` - SAML / SSO\n* `tacacs` - TACACS+\n* `local` - Local"
      },
      "PatchedRoleRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "permissions": {},
          "is_admin": {
            "type": "boolean"
          }
        }
      },
      "ResourceTypeEnum": {
        "enum": [
          "vs",
          "partition",
          "device"
        ],
        "type": "string",
        "description": "* `vs` - Virtual Server\n* `partition` - Partition\n* `device` - Device"
      },
      "PaginatedDeviceImportJobList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeviceImportJob"
            }
          }
        }
      },
      "UserCreate": {
        "type": "object",
        "properties": {
          "username": {
            "type": "string",
            "description": "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
            "pattern": "^[\\w.@+-]+$",
            "maxLength": 150
          },
          "email": {
            "type": "string",
            "format": "email",
            "title": "Email address",
            "maxLength": 254
          },
          "first_name": {
            "type": "string",
            "maxLength": 150
          },
          "last_name": {
            "type": "string",
            "maxLength": 150
          },
          "is_staff": {
            "type": "boolean",
            "title": "Staff status",
            "description": "Designates whether the user can log into this admin site."
          }
        },
        "required": [
          "username"
        ]
      },
      "PatchedClientRequest": {
        "type": "object",
        "properties": {
          "tenant_id": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "description": {
            "type": "string"
          },
          "contact_name": {
            "type": "string",
            "maxLength": 150
          },
          "contact_email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "contact_phone": {
            "type": "string",
            "maxLength": 50
          },
          "distribution_group": {
            "type": "string",
            "description": "Email distribution list for notifications",
            "maxLength": 150
          },
          "ad_group": {
            "type": "string",
            "description": "Active Directory group for access control",
            "maxLength": 150
          }
        }
      },
      "PaginatedTenantNoteList": {
        "type": "object",
        "required": [
          "count",
          "results"
        ],
        "properties": {
          "count": {
            "type": "integer",
            "example": 123
          },
          "next": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=4"
          },
          "previous": {
            "type": "string",
            "nullable": true,
            "format": "uri",
            "example": "http://api.example.org/accounts/?page=2"
          },
          "results": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantNote"
            }
          }
        }
      }
    }
  }
}