{
  "openapi": "3.1.0",
  "info": {
    "title": "walkerOS Tag Manager API",
    "version": "4.6.1",
    "description": "API for managing walkerOS flows, projects, and real-time event observation.",
    "contact": {
      "name": "elbwalker",
      "url": "https://www.elbwalker.com"
    }
  },
  "servers": [
    {
      "url": "/",
      "description": "Current server"
    }
  ],
  "tags": [
    {
      "name": "Auth",
      "description": "Authentication (magic link, session, identity)"
    },
    {
      "name": "OAuth",
      "description": "OAuth 2.1 authorization server (client registration, admin clients)"
    },
    {
      "name": "Projects",
      "description": "Project management and membership"
    },
    {
      "name": "Flows",
      "description": "Flow CRUD (project-scoped)"
    },
    {
      "name": "Versions",
      "description": "Flow version history"
    },
    {
      "name": "Deployments",
      "description": "Flow deployment management"
    },
    {
      "name": "Settings",
      "description": "Per-settings management (named flows within a Config)"
    },
    {
      "name": "Tokens",
      "description": "API token management"
    },
    {
      "name": "Service Accounts",
      "description": "Project service accounts and their tokens"
    },
    {
      "name": "Invitations",
      "description": "Project membership invitations"
    },
    {
      "name": "Billing",
      "description": "Project billing details"
    },
    {
      "name": "Bundle",
      "description": "Flow bundling utility"
    },
    {
      "name": "Observe",
      "description": "Real-time event observation"
    },
    {
      "name": "Chat",
      "description": "AI chat sessions and elicitation"
    },
    {
      "name": "Telemetry",
      "description": "Anonymous CLI/MCP usage telemetry"
    },
    {
      "name": "System",
      "description": "Health and documentation"
    },
    {
      "name": "Observer",
      "description": "Observer service (Fastify, port 3001)"
    },
    {
      "name": "Feedback",
      "description": "Public feedback submission (CLI, MCP, in-app)"
    }
  ],
  "components": {
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "example": "VALIDATION_ERROR"
              },
              "message": {
                "type": "string",
                "example": "Validation failed"
              },
              "details": {
                "type": "object",
                "properties": {
                  "field": {
                    "type": "string"
                  },
                  "reason": {
                    "type": "string"
                  },
                  "errors": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "path": {
                          "type": "string"
                        },
                        "message": {
                          "type": "string"
                        }
                      },
                      "required": ["path", "message"]
                    }
                  }
                },
                "additionalProperties": {}
              }
            },
            "required": ["code", "message"]
          }
        },
        "required": ["error"]
      },
      "ClientOutdatedError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": ["CLIENT_OUTDATED"]
              },
              "message": {
                "type": "string",
                "example": "This endpoint requires @walkeros/cli >= 3.5.0 (you are on 3.3.1)."
              },
              "minVersion": {
                "type": "string",
                "example": "3.5.0"
              },
              "clientVersion": {
                "type": "string",
                "example": "3.3.1"
              },
              "client": {
                "type": "string",
                "example": "cli"
              },
              "upgrade": {
                "type": "string",
                "example": "npm install -g @walkeros/cli@latest"
              },
              "docs": {
                "type": "string",
                "format": "uri",
                "example": "https://walkeros.io/docs/upgrading"
              }
            },
            "required": [
              "code",
              "message",
              "minVersion",
              "clientVersion",
              "client",
              "upgrade",
              "docs"
            ]
          }
        },
        "required": ["error"]
      },
      "FlowConfig": {
        "type": "object",
        "properties": {
          "version": {
            "type": "number",
            "enum": [4]
          },
          "$schema": {
            "type": "string"
          },
          "include": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "variables": {
            "type": "object",
            "additionalProperties": {}
          },
          "definitions": {
            "type": "object",
            "additionalProperties": {}
          },
          "flows": {
            "type": "object",
            "additionalProperties": {}
          },
          "contract": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "required": ["version"],
        "additionalProperties": {}
      },
      "Flow": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          },
          "config": {
            "$ref": "#/components/schemas/FlowConfig"
          },
          "settings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowSettingsSummary"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "deletedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["id", "name", "config", "createdAt", "updatedAt"]
      },
      "FlowSettingsSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cfg_[a-zA-Z0-9_-]+$",
            "example": "cfg_a1b2c3d4"
          },
          "name": {
            "type": "string"
          },
          "platform": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "name", "platform", "createdAt", "updatedAt"]
      },
      "FlowSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          },
          "summary": {
            "type": "string"
          },
          "settings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowSettingsListItem"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "deletedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["id", "name", "createdAt", "updatedAt", "deletedAt"]
      },
      "FlowSettingsListItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cfg_[a-zA-Z0-9_-]+$",
            "example": "cfg_a1b2c3d4"
          },
          "name": {
            "type": "string"
          },
          "platform": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "serving": {
            "$ref": "#/components/schemas/ServingStatus"
          },
          "latestAttempt": {
            "$ref": "#/components/schemas/LatestAttemptStatus"
          },
          "deploymentUrl": {
            "type": ["string", "null"]
          },
          "deployedAt": {
            "type": ["string", "null"]
          }
        },
        "required": [
          "id",
          "name",
          "platform",
          "serving",
          "latestAttempt",
          "deploymentUrl",
          "deployedAt"
        ]
      },
      "ServingStatus": {
        "type": "string",
        "enum": ["live", "none"]
      },
      "LatestAttemptStatus": {
        "type": ["string", "null"],
        "enum": [
          "idle",
          "deploying",
          "published",
          "active",
          "stopped",
          "failed",
          null
        ]
      },
      "Version": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 1
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string",
            "enum": ["user", "auto_save", "restore", "deploy", "preview"],
            "example": "user"
          },
          "contentHash": {
            "type": "string",
            "example": "sha256:abc123..."
          }
        },
        "required": ["version", "createdAt", "createdBy"]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^proj_[a-zA-Z0-9_-]+$",
            "example": "proj_x7y8z9"
          },
          "name": {
            "type": "string",
            "example": "My Website"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "member", "deployer", "viewer"],
            "example": "owner"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "memberCount": {
            "type": "integer",
            "example": 3
          },
          "flowCount": {
            "type": "integer",
            "example": 5
          },
          "deploymentCount": {
            "type": "integer",
            "example": 2
          },
          "isDemo": {
            "type": "boolean",
            "example": false
          }
        },
        "required": [
          "id",
          "name",
          "role",
          "createdAt",
          "updatedAt",
          "memberCount",
          "flowCount",
          "deploymentCount",
          "isDemo"
        ]
      },
      "Member": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "member", "deployer", "viewer"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["userId", "email", "role", "createdAt"]
      },
      "DeleteAccountRequest": {
        "type": "object",
        "properties": {
          "confirm": {
            "type": "string",
            "minLength": 1,
            "example": "me@example.com"
          }
        },
        "required": ["confirm"]
      },
      "DeleteAccountBlocked": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": ["SOLE_OWNER"],
                "example": "SOLE_OWNER"
              },
              "message": {
                "type": "string"
              },
              "details": {
                "type": "object",
                "properties": {
                  "projects": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "example": ["proj_abc123"]
                  }
                },
                "required": ["projects"]
              }
            },
            "required": ["code", "message", "details"]
          }
        },
        "required": ["error"]
      },
      "AccountExportResponse": {
        "type": "object",
        "properties": {
          "exportedAt": {
            "type": "string",
            "example": "2026-06-10T12:00:00.000Z"
          },
          "profile": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "example": "user_a1b2c3d4"
              },
              "email": {
                "type": "string",
                "example": "me@example.com"
              },
              "displayName": {
                "type": ["string", "null"]
              },
              "createdAt": {
                "type": "string"
              },
              "lastLoginAt": {
                "type": ["string", "null"]
              },
              "globalRole": {
                "type": "string",
                "example": "user"
              },
              "traits": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            },
            "required": [
              "id",
              "email",
              "displayName",
              "createdAt",
              "lastLoginAt",
              "globalRole",
              "traits"
            ]
          },
          "memberships": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "projectId": {
                  "type": "string"
                },
                "projectName": {
                  "type": "string"
                },
                "role": {
                  "type": "string"
                },
                "joinedAt": {
                  "type": "string"
                }
              },
              "required": ["projectId", "projectName", "role", "joinedAt"]
            }
          },
          "tokens": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "example": "automation"
                },
                "scope": {
                  "type": "string",
                  "example": "read write"
                },
                "audience": {
                  "type": "string",
                  "example": "api mcp"
                },
                "projectId": {
                  "type": ["string", "null"]
                },
                "createdAt": {
                  "type": "string"
                },
                "lastUsedAt": {
                  "type": ["string", "null"]
                },
                "expiresAt": {
                  "type": "string"
                },
                "revokedAt": {
                  "type": ["string", "null"]
                }
              },
              "required": [
                "id",
                "name",
                "kind",
                "scope",
                "audience",
                "projectId",
                "createdAt",
                "lastUsedAt",
                "expiresAt",
                "revokedAt"
              ]
            }
          },
          "sessions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "createdAt": {
                  "type": "string"
                },
                "expiresAt": {
                  "type": "string"
                },
                "lastTouchedAt": {
                  "type": "string"
                }
              },
              "required": ["id", "createdAt", "expiresAt", "lastTouchedAt"]
            }
          },
          "mcpSessions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": ["string", "null"]
                },
                "createdAt": {
                  "type": "string"
                },
                "lastActiveAt": {
                  "type": "string"
                },
                "expiresAt": {
                  "type": "string"
                },
                "messages": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "seq": {
                        "type": "number"
                      },
                      "role": {
                        "type": "string"
                      },
                      "content": {},
                      "createdAt": {
                        "type": "string"
                      }
                    },
                    "required": ["seq", "role", "createdAt"]
                  }
                }
              },
              "required": [
                "id",
                "projectId",
                "createdAt",
                "lastActiveAt",
                "expiresAt",
                "messages"
              ]
            }
          },
          "feedback": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": ["string", "null"]
                },
                "text": {
                  "type": "string"
                },
                "source": {
                  "type": "string"
                },
                "createdAt": {
                  "type": "string"
                }
              },
              "required": ["id", "projectId", "text", "source", "createdAt"]
            }
          },
          "invitations": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": "string"
                },
                "invitedEmail": {
                  "type": "string"
                },
                "role": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "createdAt": {
                  "type": "string"
                },
                "expiresAt": {
                  "type": "string"
                },
                "acceptedAt": {
                  "type": ["string", "null"]
                },
                "declinedAt": {
                  "type": ["string", "null"]
                },
                "cancelledAt": {
                  "type": ["string", "null"]
                }
              },
              "required": [
                "id",
                "projectId",
                "invitedEmail",
                "role",
                "status",
                "createdAt",
                "expiresAt",
                "acceptedAt",
                "declinedAt",
                "cancelledAt"
              ]
            }
          }
        },
        "required": [
          "exportedAt",
          "profile",
          "memberships",
          "tokens",
          "sessions",
          "mcpSessions",
          "feedback",
          "invitations"
        ]
      },
      "AutomationTokenSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "tok_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "example": "CI Pipeline"
          },
          "tokenPrefix": {
            "type": "string",
            "example": "wos_pat_a1b2"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["read", "write"]
          },
          "audience": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["api", "mcp"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "lastUsedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "revokedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "tokenPrefix",
          "scope",
          "audience",
          "createdAt",
          "lastUsedAt",
          "expiresAt",
          "revokedAt"
        ]
      },
      "FlowSettingsDetail": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cfg_[a-zA-Z0-9_-]+$",
            "example": "cfg_a1b2c3d4"
          },
          "name": {
            "type": "string"
          },
          "platform": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "config": {
            "type": "object",
            "additionalProperties": {}
          },
          "deployment": {
            "type": ["object", "null"],
            "properties": {
              "id": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "containerUrl": {
                "type": ["string", "null"]
              },
              "publicUrl": {
                "type": ["string", "null"]
              },
              "errorMessage": {
                "type": ["string", "null"]
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "example": "2026-01-26T14:30:00.000Z"
              },
              "updatedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2026-01-26T14:30:00.000Z"
              }
            },
            "required": ["id", "status", "type", "createdAt", "updatedAt"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "platform",
          "config",
          "createdAt",
          "updatedAt"
        ]
      },
      "DeploySettingsRequest": {
        "type": "object",
        "properties": {
          "flow": {
            "type": "string"
          },
          "humanText": {
            "type": "string",
            "maxLength": 4000
          }
        }
      },
      "DeploySettingsResponse": {
        "type": "object",
        "properties": {
          "deploymentId": {
            "type": "string"
          },
          "settingsId": {
            "type": "string",
            "pattern": "^cfg_[a-zA-Z0-9_-]+$",
            "example": "cfg_a1b2c3d4"
          },
          "status": {
            "type": "string"
          }
        },
        "required": ["deploymentId", "settingsId", "status"]
      },
      "FlowDetailResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          },
          "config": {
            "$ref": "#/components/schemas/FlowConfig"
          },
          "settings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowSettingsEnriched"
            }
          },
          "bundleId": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "deletedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "name",
          "config",
          "createdAt",
          "updatedAt",
          "deletedAt"
        ]
      },
      "FlowSettingsEnriched": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "platform": {
            "type": "string",
            "enum": ["web", "server"]
          },
          "deployment": {
            "type": ["object", "null"],
            "properties": {
              "id": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "type": {
                "type": "string"
              },
              "target": {
                "type": ["string", "null"]
              },
              "containerUrl": {
                "type": ["string", "null"]
              },
              "createdAt": {
                "type": "string",
                "format": "date-time",
                "example": "2026-01-26T14:30:00.000Z"
              },
              "updatedAt": {
                "type": ["string", "null"]
              }
            },
            "required": [
              "id",
              "slug",
              "status",
              "type",
              "target",
              "containerUrl",
              "createdAt",
              "updatedAt"
            ]
          },
          "serving": {
            "$ref": "#/components/schemas/ServingStatus"
          },
          "latestAttempt": {
            "$ref": "#/components/schemas/LatestAttemptStatus"
          },
          "deployedAt": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "platform",
          "deployment",
          "serving",
          "latestAttempt",
          "deployedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "FlowUpdateResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          },
          "config": {
            "$ref": "#/components/schemas/FlowConfig"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "name", "config", "createdAt", "updatedAt"]
      },
      "CreateProjectResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^proj_[a-zA-Z0-9_-]+$",
            "example": "proj_x7y8z9"
          },
          "name": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "name", "createdAt"]
      },
      "UpdateProjectResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^proj_[a-zA-Z0-9_-]+$",
            "example": "proj_x7y8z9"
          },
          "name": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "name", "updatedAt"]
      },
      "DeploymentSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]{12}$",
            "example": "k7m2x9p4q1w8"
          },
          "target": {
            "type": ["string", "null"]
          },
          "label": {
            "type": ["string", "null"]
          },
          "origin": {
            "type": "string",
            "enum": ["cloud", "self-hosted"],
            "example": "cloud"
          },
          "status": {
            "type": "string",
            "enum": [
              "idle",
              "deploying",
              "published",
              "active",
              "stopped",
              "failed"
            ],
            "example": "active"
          },
          "serving": {
            "$ref": "#/components/schemas/ServingStatus"
          },
          "currentVersionNumber": {
            "type": ["integer", "null"],
            "exclusiveMinimum": 0
          },
          "url": {
            "type": ["string", "null"]
          },
          "flowId": {
            "type": ["string", "null"],
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "flowName": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "usageSummary": {
            "type": "object",
            "properties": {
              "eventsIn24h": {
                "type": "integer",
                "minimum": 0
              },
              "healthy": {
                "type": "boolean"
              }
            },
            "required": ["eventsIn24h", "healthy"]
          }
        },
        "required": [
          "id",
          "type",
          "slug",
          "target",
          "label",
          "origin",
          "status",
          "serving",
          "currentVersionNumber",
          "url",
          "flowId",
          "flowName",
          "createdAt",
          "updatedAt"
        ]
      },
      "DeploymentDetailResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]{12}$",
            "example": "k7m2x9p4q1w8"
          },
          "target": {
            "type": ["string", "null"]
          },
          "label": {
            "type": ["string", "null"]
          },
          "origin": {
            "type": "string",
            "enum": ["cloud", "self-hosted"],
            "example": "cloud"
          },
          "status": {
            "type": "string",
            "enum": [
              "idle",
              "deploying",
              "published",
              "active",
              "stopped",
              "failed"
            ],
            "example": "active"
          },
          "currentVersion": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DeploymentVersionDetail"
              },
              {
                "type": "null"
              }
            ]
          },
          "versions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeploymentVersionHistoryEntry"
            }
          },
          "error": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/DeploymentError"
              },
              {
                "type": "null"
              }
            ]
          },
          "recentErrors": {
            "type": ["array", "null"],
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                },
                "count": {
                  "type": "integer"
                },
                "firstSeen": {
                  "type": "string"
                },
                "lastSeen": {
                  "type": "string"
                }
              },
              "required": ["message", "count", "firstSeen", "lastSeen"]
            }
          },
          "recentLogs": {
            "type": ["array", "null"],
            "items": {
              "type": "object",
              "properties": {
                "time": {
                  "type": "string"
                },
                "level": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              },
              "required": ["time", "level", "message"]
            }
          },
          "url": {
            "type": ["string", "null"]
          },
          "selfHosted": {
            "type": ["object", "null"],
            "properties": {
              "lastHeartbeatAt": {
                "type": "string",
                "format": "date-time"
              },
              "instanceId": {
                "type": ["string", "null"]
              },
              "cliVersion": {
                "type": ["string", "null"]
              },
              "healthy": {
                "type": "boolean"
              }
            },
            "required": [
              "lastHeartbeatAt",
              "instanceId",
              "cliVersion",
              "healthy"
            ]
          },
          "lastHeartbeatAt": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "type",
          "slug",
          "target",
          "label",
          "origin",
          "status",
          "currentVersion",
          "versions",
          "error",
          "url",
          "selfHosted",
          "createdAt",
          "updatedAt"
        ]
      },
      "DeploymentVersionDetail": {
        "type": "object",
        "properties": {
          "number": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "status": {
            "type": "string"
          },
          "source": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "flowId": {
                "type": "string"
              },
              "flowSettingsId": {
                "type": "string"
              },
              "configHash": {
                "type": "string"
              }
            },
            "required": ["type"]
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "errorCode": {
            "type": ["string", "null"]
          },
          "publishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "publishedBy": {
            "type": ["string", "null"]
          }
        },
        "required": [
          "number",
          "status",
          "source",
          "errorMessage",
          "errorCode",
          "publishedAt",
          "publishedBy"
        ]
      },
      "DeploymentVersionHistoryEntry": {
        "type": "object",
        "properties": {
          "versionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "status": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "errorCode": {
            "type": ["string", "null"]
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "errorPhase": {
            "type": ["string", "null"]
          },
          "errorDetail": {
            "type": ["string", "null"]
          },
          "publishedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "versionNumber",
          "status",
          "source",
          "errorCode",
          "errorMessage",
          "errorPhase",
          "publishedAt"
        ]
      },
      "DeploymentError": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "phase": {
            "type": "string",
            "enum": ["preflight", "deploy", "bundle", "publish", "provision"],
            "example": "bundle"
          },
          "detail": {
            "type": "string"
          }
        },
        "required": ["code", "message", "phase"]
      },
      "CreateDeploymentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]{12}$",
            "example": "k7m2x9p4q1w8"
          },
          "target": {
            "type": ["string", "null"]
          },
          "label": {
            "type": ["string", "null"]
          },
          "origin": {
            "type": "string",
            "enum": ["cloud", "self-hosted"],
            "example": "cloud"
          },
          "status": {
            "type": "string",
            "enum": [
              "idle",
              "deploying",
              "published",
              "active",
              "stopped",
              "failed"
            ],
            "example": "active"
          },
          "serving": {
            "$ref": "#/components/schemas/ServingStatus"
          },
          "currentVersionNumber": {
            "type": ["integer", "null"],
            "exclusiveMinimum": 0
          },
          "url": {
            "type": ["string", "null"]
          },
          "flowId": {
            "type": ["string", "null"],
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "flowName": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          },
          "usageSummary": {
            "type": "object",
            "properties": {
              "eventsIn24h": {
                "type": "integer",
                "minimum": 0
              },
              "healthy": {
                "type": "boolean"
              }
            },
            "required": ["eventsIn24h", "healthy"]
          }
        },
        "required": [
          "id",
          "type",
          "slug",
          "target",
          "label",
          "origin",
          "status",
          "serving",
          "currentVersionNumber",
          "url",
          "flowId",
          "flowName",
          "createdAt",
          "updatedAt"
        ]
      },
      "StartDeploymentResponse": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "deploymentId": {
                "type": "string",
                "pattern": "^dep_[a-zA-Z0-9_-]+$",
                "example": "dep_a1b2c3d4"
              },
              "slug": {
                "type": "string",
                "pattern": "^[a-z0-9]{12}$",
                "example": "k7m2x9p4q1w8"
              },
              "target": {
                "type": ["string", "null"]
              },
              "type": {
                "type": "string",
                "enum": ["web", "server"],
                "example": "web"
              },
              "status": {
                "type": "string",
                "enum": ["deploying"]
              },
              "settingsId": {
                "type": "string"
              },
              "versionId": {
                "type": "string"
              },
              "versionNumber": {
                "type": "integer",
                "exclusiveMinimum": 0
              }
            },
            "required": [
              "deploymentId",
              "slug",
              "target",
              "type",
              "status",
              "versionId",
              "versionNumber"
            ]
          },
          {
            "type": "object",
            "properties": {
              "deploymentId": {
                "type": "string"
              },
              "status": {
                "type": "string",
                "enum": ["already_created"]
              }
            },
            "required": ["deploymentId", "status"]
          }
        ]
      },
      "DeploymentStreamStatusEvent": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "substatus": {
            "type": ["string", "null"]
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "target": {
            "type": ["string", "null"]
          },
          "containerUrl": {
            "type": ["string", "null"]
          },
          "errorCode": {
            "type": ["string", "null"]
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "status",
          "substatus",
          "type",
          "target",
          "containerUrl",
          "errorCode",
          "errorMessage",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListDeploymentsResponse": {
        "type": "object",
        "properties": {
          "deployments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeploymentSummary"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          },
          "nextCursor": {
            "type": ["string", "null"]
          }
        },
        "required": ["deployments", "total", "limit", "offset", "nextCursor"]
      },
      "UpdateDeploymentResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"],
            "example": "web"
          },
          "slug": {
            "type": "string",
            "pattern": "^[a-z0-9]{12}$",
            "example": "k7m2x9p4q1w8"
          },
          "target": {
            "type": ["string", "null"]
          },
          "label": {
            "type": ["string", "null"]
          },
          "origin": {
            "type": "string",
            "enum": ["cloud", "self-hosted"],
            "example": "cloud"
          },
          "status": {
            "type": "string",
            "enum": [
              "idle",
              "deploying",
              "published",
              "active",
              "stopped",
              "failed"
            ],
            "example": "active"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "type",
          "slug",
          "target",
          "label",
          "origin",
          "status",
          "createdAt",
          "updatedAt"
        ]
      },
      "LatestDeploymentsByFlow": {
        "type": "object",
        "additionalProperties": {
          "type": "object",
          "properties": {
            "id": {
              "type": "string"
            },
            "flowId": {
              "type": "string"
            },
            "slug": {
              "type": "string"
            },
            "type": {
              "type": "string"
            },
            "status": {
              "type": "string"
            },
            "target": {
              "type": ["string", "null"]
            },
            "containerUrl": {
              "type": ["string", "null"]
            },
            "createdAt": {
              "type": "string"
            }
          },
          "required": [
            "id",
            "flowId",
            "slug",
            "type",
            "status",
            "target",
            "containerUrl",
            "createdAt"
          ]
        }
      },
      "PublishVersionResponse": {
        "type": "object",
        "properties": {
          "versionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "versionId": {
            "type": "string"
          },
          "deploymentId": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "status": {
            "type": "string",
            "enum": ["deploying"]
          },
          "source": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["flow"]
                  },
                  "flowId": {
                    "type": "string"
                  },
                  "flowSettingsName": {
                    "type": "string"
                  }
                },
                "required": ["type", "flowId", "flowSettingsName"]
              },
              {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["config"]
                  }
                },
                "required": ["type"]
              }
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "versionNumber",
          "versionId",
          "deploymentId",
          "status",
          "source",
          "createdAt"
        ]
      },
      "ListDeploymentVersionsResponse": {
        "type": "object",
        "properties": {
          "versions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "number": {
                  "type": "integer",
                  "exclusiveMinimum": 0
                },
                "status": {
                  "type": "string"
                },
                "source": {
                  "type": "object",
                  "properties": {
                    "type": {
                      "type": "string"
                    },
                    "flowId": {
                      "type": "string"
                    },
                    "flowSettingsId": {
                      "type": "string"
                    },
                    "configHash": {
                      "type": "string"
                    }
                  },
                  "required": ["type"]
                },
                "errorMessage": {
                  "type": ["string", "null"]
                },
                "errorCode": {
                  "type": ["string", "null"]
                },
                "bundlePath": {
                  "type": ["string", "null"]
                },
                "publishedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "publishedBy": {
                  "type": ["string", "null"]
                }
              },
              "required": [
                "number",
                "status",
                "source",
                "errorMessage",
                "errorCode",
                "bundlePath",
                "publishedAt",
                "publishedBy"
              ]
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["versions", "total", "limit", "offset"]
      },
      "ListFlowReleasesResponse": {
        "type": "object",
        "properties": {
          "releases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowRelease"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["releases", "total", "limit", "offset"]
      },
      "FlowRelease": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "deploymentId": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "deploymentSlug": {
            "type": ["string", "null"],
            "pattern": "^[a-z0-9]{12}$",
            "example": "k7m2x9p4q1w8"
          },
          "deploymentType": {
            "type": ["string", "null"],
            "enum": ["web", "server", null],
            "example": "web"
          },
          "versionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "flowVersionId": {
            "type": ["string", "null"],
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "flowVersionNumber": {
            "type": ["integer", "null"],
            "exclusiveMinimum": 0
          },
          "status": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "errorCode": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdBy": {
            "type": ["string", "null"]
          },
          "createdByLabel": {
            "type": ["string", "null"]
          },
          "rationale": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ReleaseRationaleSummary"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "id",
          "deploymentId",
          "deploymentSlug",
          "deploymentType",
          "versionNumber",
          "flowVersionId",
          "flowVersionNumber",
          "status",
          "source",
          "errorCode",
          "createdAt",
          "createdBy",
          "createdByLabel"
        ]
      },
      "ReleaseRationaleSummary": {
        "type": "object",
        "properties": {
          "hasHumanText": {
            "type": "boolean"
          },
          "hasGeneratedSummary": {
            "type": "boolean"
          },
          "firstLine": {
            "type": ["string", "null"]
          }
        },
        "required": ["hasHumanText", "hasGeneratedSummary", "firstLine"]
      },
      "ReleaseContentResponse": {
        "type": "object",
        "properties": {
          "versionId": {
            "type": "string",
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "versionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 22
          },
          "content": {
            "$ref": "#/components/schemas/FlowConfig"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string",
            "enum": ["user", "auto_save", "restore", "deploy", "preview"]
          }
        },
        "required": [
          "versionId",
          "versionNumber",
          "content",
          "createdAt",
          "createdBy"
        ]
      },
      "ReleaseDiff": {
        "type": "object",
        "properties": {
          "prevVersionId": {
            "type": "string",
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "prevVersionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "text": {
            "type": "string"
          },
          "contentIdentical": {
            "type": "boolean"
          }
        },
        "required": [
          "prevVersionId",
          "prevVersionNumber",
          "text",
          "contentIdentical"
        ]
      },
      "ReleaseDetailResponse": {
        "type": "object",
        "properties": {
          "versionId": {
            "type": "string",
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "versionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "contentHash": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string"
          },
          "rationale": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/VersionAnnotation"
              },
              {
                "type": "null"
              }
            ]
          },
          "diff": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ReleaseDiff"
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": [
          "versionId",
          "versionNumber",
          "contentHash",
          "createdAt",
          "createdBy",
          "rationale",
          "diff"
        ]
      },
      "VersionAnnotation": {
        "type": "object",
        "properties": {
          "versionId": {
            "type": "string",
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "humanText": {
            "type": ["string", "null"]
          },
          "generatedSummary": {
            "type": ["string", "null"]
          },
          "author": {
            "type": "string",
            "example": "user_a1b2c3d4"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "versionId",
          "humanText",
          "generatedSummary",
          "author",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListVersionAnnotationsResponse": {
        "type": "object",
        "properties": {
          "annotations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/VersionAnnotation"
            }
          }
        },
        "required": ["annotations"]
      },
      "UpsertVersionAnnotationResponse": {
        "type": "object",
        "properties": {
          "versionId": {
            "type": "string",
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "humanText": {
            "type": ["string", "null"]
          },
          "generatedSummary": {
            "type": ["string", "null"]
          },
          "author": {
            "type": "string",
            "example": "user_a1b2c3d4"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "versionId",
          "humanText",
          "generatedSummary",
          "author",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListHubThreadsResponse": {
        "type": "object",
        "properties": {
          "threads": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HubThread"
            }
          },
          "hasMoreThreads": {
            "type": "boolean"
          }
        },
        "required": ["threads", "hasMoreThreads"]
      },
      "HubThread": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^thr_[a-z0-9]+$",
            "example": "thr_a1b2c3d4"
          },
          "anchorType": {
            "type": "string",
            "enum": ["step", "entity_action", "release", "contract", "tag"],
            "example": "release"
          },
          "anchorKey": {
            "type": "string"
          },
          "anchorLabel": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"],
            "example": "open"
          },
          "resolvedByVersionId": {
            "type": ["string", "null"]
          },
          "resolvedByVersionNumber": {
            "type": ["integer", "null"]
          },
          "resolvedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "resolvedBy": {
            "type": ["string", "null"]
          },
          "createdBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "messageCount": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HubMessage"
            }
          },
          "hasMoreMessages": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "anchorType",
          "anchorKey",
          "anchorLabel",
          "status",
          "resolvedByVersionId",
          "resolvedByVersionNumber",
          "resolvedAt",
          "resolvedBy",
          "createdBy",
          "createdAt",
          "updatedAt",
          "messageCount"
        ]
      },
      "HubMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "author": {
            "type": "string",
            "example": "user_a1b2c3d4"
          },
          "text": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "author", "text", "createdAt"]
      },
      "HubThreadResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^thr_[a-z0-9]+$",
            "example": "thr_a1b2c3d4"
          },
          "anchorType": {
            "type": "string",
            "enum": ["step", "entity_action", "release", "contract", "tag"],
            "example": "release"
          },
          "anchorKey": {
            "type": "string"
          },
          "anchorLabel": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"],
            "example": "open"
          },
          "resolvedByVersionId": {
            "type": ["string", "null"]
          },
          "resolvedByVersionNumber": {
            "type": ["integer", "null"]
          },
          "resolvedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "resolvedBy": {
            "type": ["string", "null"]
          },
          "createdBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "messageCount": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HubMessage"
            }
          },
          "hasMoreMessages": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "anchorType",
          "anchorKey",
          "anchorLabel",
          "status",
          "resolvedByVersionId",
          "resolvedByVersionNumber",
          "resolvedAt",
          "resolvedBy",
          "createdBy",
          "createdAt",
          "updatedAt",
          "messageCount"
        ]
      },
      "ListKnowledgeResponse": {
        "type": "object",
        "properties": {
          "entries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KnowledgeEntry"
            }
          },
          "hasMoreEntries": {
            "type": "boolean"
          }
        },
        "required": ["entries", "hasMoreEntries"]
      },
      "KnowledgeEntry": {
        "oneOf": [
          {
            "$ref": "#/components/schemas/KnowledgeThread"
          },
          {
            "$ref": "#/components/schemas/KnowledgeDescription"
          }
        ],
        "discriminator": {
          "propertyName": "kind",
          "mapping": {
            "thread": "#/components/schemas/KnowledgeThread",
            "description": "#/components/schemas/KnowledgeDescription"
          }
        }
      },
      "KnowledgeThread": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "anchorKey": {
            "type": "string"
          },
          "anchorLabel": {
            "type": "string"
          },
          "frameId": {
            "type": ["string", "null"]
          },
          "frameName": {
            "type": ["string", "null"]
          },
          "flowId": {
            "type": ["string", "null"]
          },
          "subjectKey": {
            "type": ["string", "null"]
          },
          "spatial": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KnowledgeSpatial"
              },
              {
                "type": "null"
              }
            ]
          },
          "validity": {
            "$ref": "#/components/schemas/KnowledgeValidity"
          },
          "freshness": {
            "type": "string",
            "enum": ["current", "subject_changed", "unknown"]
          },
          "author": {
            "$ref": "#/components/schemas/KnowledgeAuthor"
          },
          "source": {
            "type": "string",
            "enum": ["tag_mode", "hub", "mcp"]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "kind": {
            "type": "string",
            "enum": ["thread"]
          },
          "anchorType": {
            "type": "string",
            "enum": [
              "step",
              "entity_action",
              "release",
              "contract",
              "tag",
              "page"
            ],
            "example": "tag"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"],
            "example": "open"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "messageCount": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KnowledgeMessage"
            }
          },
          "hasMoreMessages": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "anchorKey",
          "anchorLabel",
          "frameId",
          "frameName",
          "flowId",
          "subjectKey",
          "spatial",
          "validity",
          "freshness",
          "author",
          "source",
          "updatedAt",
          "kind",
          "anchorType",
          "status",
          "createdAt",
          "messageCount"
        ]
      },
      "KnowledgeSpatial": {
        "type": "object",
        "properties": {
          "at": {
            "type": "object",
            "properties": {
              "x": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              },
              "y": {
                "type": "number",
                "minimum": 0,
                "maximum": 1
              }
            },
            "required": ["x", "y"]
          },
          "element": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "required": ["at"]
      },
      "KnowledgeValidity": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "tier": {
                "type": "string",
                "enum": ["release"]
              },
              "versionId": {
                "type": "string"
              },
              "versionNumber": {
                "type": "integer"
              },
              "promoted": {
                "type": "boolean"
              }
            },
            "required": ["tier", "versionId", "versionNumber", "promoted"]
          },
          {
            "type": "object",
            "properties": {
              "tier": {
                "type": "string",
                "enum": ["draft"]
              },
              "versionId": {
                "type": "string"
              }
            },
            "required": ["tier"]
          },
          {
            "type": "object",
            "properties": {
              "tier": {
                "type": "string",
                "enum": ["none"]
              }
            },
            "required": ["tier"]
          }
        ]
      },
      "KnowledgeAuthor": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": ["user", "preview", "agent"]
          },
          "id": {
            "type": ["string", "null"]
          },
          "label": {
            "type": "string"
          }
        },
        "required": ["kind", "id", "label"]
      },
      "KnowledgeMessage": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "author": {
            "type": "string",
            "example": "user_a1b2c3d4"
          },
          "authorLabel": {
            "type": "string",
            "example": "ayla@elbwalker.com"
          },
          "text": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "clientMessageId": {
            "type": ["string", "null"]
          }
        },
        "required": [
          "id",
          "author",
          "authorLabel",
          "text",
          "createdAt",
          "clientMessageId"
        ]
      },
      "KnowledgeDescription": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "anchorKey": {
            "type": "string"
          },
          "anchorLabel": {
            "type": "string"
          },
          "frameId": {
            "type": ["string", "null"]
          },
          "frameName": {
            "type": ["string", "null"]
          },
          "flowId": {
            "type": ["string", "null"]
          },
          "subjectKey": {
            "type": ["string", "null"]
          },
          "spatial": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KnowledgeSpatial"
              },
              {
                "type": "null"
              }
            ]
          },
          "validity": {
            "$ref": "#/components/schemas/KnowledgeValidity"
          },
          "freshness": {
            "type": "string",
            "enum": ["current", "subject_changed", "unknown"]
          },
          "author": {
            "$ref": "#/components/schemas/KnowledgeAuthor"
          },
          "source": {
            "type": "string",
            "enum": ["tag_mode", "hub", "mcp"]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "kind": {
            "type": "string",
            "enum": ["description"]
          },
          "anchorType": {
            "type": "string",
            "enum": ["tag", "page"],
            "example": "tag"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "anchorKey",
          "anchorLabel",
          "frameId",
          "frameName",
          "flowId",
          "subjectKey",
          "spatial",
          "validity",
          "freshness",
          "author",
          "source",
          "updatedAt",
          "kind",
          "anchorType",
          "body"
        ]
      },
      "KnowledgeThreadResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "anchorKey": {
            "type": "string"
          },
          "anchorLabel": {
            "type": "string"
          },
          "frameId": {
            "type": ["string", "null"]
          },
          "frameName": {
            "type": ["string", "null"]
          },
          "flowId": {
            "type": ["string", "null"]
          },
          "subjectKey": {
            "type": ["string", "null"]
          },
          "spatial": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KnowledgeSpatial"
              },
              {
                "type": "null"
              }
            ]
          },
          "validity": {
            "$ref": "#/components/schemas/KnowledgeValidity"
          },
          "freshness": {
            "type": "string",
            "enum": ["current", "subject_changed", "unknown"]
          },
          "author": {
            "$ref": "#/components/schemas/KnowledgeAuthor"
          },
          "source": {
            "type": "string",
            "enum": ["tag_mode", "hub", "mcp"]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "kind": {
            "type": "string",
            "enum": ["thread"]
          },
          "anchorType": {
            "type": "string",
            "enum": [
              "step",
              "entity_action",
              "release",
              "contract",
              "tag",
              "page"
            ],
            "example": "tag"
          },
          "status": {
            "type": "string",
            "enum": ["open", "resolved"],
            "example": "open"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "messageCount": {
            "type": "integer"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/KnowledgeMessage"
            }
          },
          "hasMoreMessages": {
            "type": "boolean"
          }
        },
        "required": [
          "id",
          "anchorKey",
          "anchorLabel",
          "frameId",
          "frameName",
          "flowId",
          "subjectKey",
          "spatial",
          "validity",
          "freshness",
          "author",
          "source",
          "updatedAt",
          "kind",
          "anchorType",
          "status",
          "createdAt",
          "messageCount"
        ]
      },
      "KnowledgeDescriptionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "anchorKey": {
            "type": "string"
          },
          "anchorLabel": {
            "type": "string"
          },
          "frameId": {
            "type": ["string", "null"]
          },
          "frameName": {
            "type": ["string", "null"]
          },
          "flowId": {
            "type": ["string", "null"]
          },
          "subjectKey": {
            "type": ["string", "null"]
          },
          "spatial": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/KnowledgeSpatial"
              },
              {
                "type": "null"
              }
            ]
          },
          "validity": {
            "$ref": "#/components/schemas/KnowledgeValidity"
          },
          "freshness": {
            "type": "string",
            "enum": ["current", "subject_changed", "unknown"]
          },
          "author": {
            "$ref": "#/components/schemas/KnowledgeAuthor"
          },
          "source": {
            "type": "string",
            "enum": ["tag_mode", "hub", "mcp"]
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "kind": {
            "type": "string",
            "enum": ["description"]
          },
          "anchorType": {
            "type": "string",
            "enum": ["tag", "page"],
            "example": "tag"
          },
          "body": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "anchorKey",
          "anchorLabel",
          "frameId",
          "frameName",
          "flowId",
          "subjectKey",
          "spatial",
          "validity",
          "freshness",
          "author",
          "source",
          "updatedAt",
          "kind",
          "anchorType",
          "body"
        ]
      },
      "FrameInput": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "parentId": {
            "type": ["string", "null"],
            "pattern": "^frm_[A-Za-z0-9_-]{21}$",
            "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
          },
          "placements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FramePlacement"
            },
            "minItems": 1
          },
          "size": {
            "$ref": "#/components/schemas/PlanSize"
          },
          "marks": {
            "type": "object",
            "additionalProperties": {}
          },
          "extends": {
            "type": ["string", "null"],
            "pattern": "^frm_[A-Za-z0-9_-]{21}$",
            "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
          },
          "source": {
            "$ref": "#/components/schemas/FrameSource"
          },
          "origin": {
            "type": "string",
            "enum": ["drawn", "imported", "observed"]
          },
          "flowId": {
            "type": ["string", "null"],
            "minLength": 1,
            "maxLength": 255
          }
        },
        "required": [
          "name",
          "parentId",
          "placements",
          "size",
          "marks",
          "extends",
          "source",
          "origin",
          "flowId"
        ]
      },
      "FramePlacement": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^pl_[A-Za-z0-9_-]{21}$"
          },
          "rect": {
            "$ref": "#/components/schemas/PlanRect"
          },
          "selector": {
            "type": "string",
            "maxLength": 2048
          },
          "anchor": {
            "type": "object",
            "additionalProperties": {}
          }
        },
        "required": ["id", "rect"]
      },
      "PlanRect": {
        "type": "object",
        "properties": {
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          },
          "w": {
            "type": "number"
          },
          "h": {
            "type": "number"
          }
        },
        "required": ["x", "y", "w", "h"]
      },
      "PlanSize": {
        "type": "object",
        "properties": {
          "width": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "height": {
            "type": "number",
            "exclusiveMinimum": 0
          }
        },
        "required": ["width", "height"]
      },
      "FrameSource": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": ["page"]
              },
              "key": {
                "type": "string",
                "minLength": 1,
                "maxLength": 1024
              },
              "url": {
                "type": "string",
                "minLength": 1,
                "maxLength": 2048
              }
            },
            "required": ["kind", "key", "url"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": ["figma"]
              },
              "fileKey": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255
              },
              "nodeId": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255
              }
            },
            "required": ["kind", "fileKey", "nodeId"]
          },
          {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": ["image"]
              }
            },
            "required": ["kind"]
          },
          {
            "type": "null"
          }
        ]
      },
      "Frame": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^frm_[A-Za-z0-9_-]{21}$",
            "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
          },
          "projectId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "parentId": {
            "type": ["string", "null"]
          },
          "placements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FramePlacement"
            }
          },
          "size": {
            "$ref": "#/components/schemas/PlanSize"
          },
          "marks": {
            "type": "object",
            "additionalProperties": {}
          },
          "extends": {
            "type": ["string", "null"]
          },
          "source": {
            "$ref": "#/components/schemas/FrameSource"
          },
          "origin": {
            "type": "string",
            "enum": ["drawn", "imported", "observed"]
          },
          "flowId": {
            "type": ["string", "null"]
          },
          "screenshot": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FrameScreenshot"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string"
          },
          "updatedBy": {
            "type": "string"
          },
          "deletedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "parentId",
          "placements",
          "size",
          "marks",
          "extends",
          "source",
          "origin",
          "flowId",
          "screenshot",
          "version",
          "createdAt",
          "updatedAt",
          "createdBy",
          "updatedBy",
          "deletedAt"
        ]
      },
      "FrameScreenshot": {
        "type": "object",
        "properties": {
          "assetId": {
            "type": "string"
          },
          "capturedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "size": {
            "$ref": "#/components/schemas/PlanSize"
          },
          "dpr": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "capturedRect": {
            "$ref": "#/components/schemas/PlanRect"
          }
        },
        "required": ["assetId", "capturedAt", "size", "dpr", "capturedRect"]
      },
      "FrameLean": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^frm_[A-Za-z0-9_-]{21}$",
            "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
          },
          "projectId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "parentId": {
            "type": ["string", "null"]
          },
          "placements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FramePlacement"
            }
          },
          "size": {
            "$ref": "#/components/schemas/PlanSize"
          },
          "extends": {
            "type": ["string", "null"]
          },
          "source": {
            "$ref": "#/components/schemas/FrameSource"
          },
          "origin": {
            "type": "string",
            "enum": ["drawn", "imported", "observed"]
          },
          "flowId": {
            "type": ["string", "null"]
          },
          "screenshot": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/FrameScreenshot"
              },
              {
                "type": "null"
              }
            ]
          },
          "version": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string"
          },
          "updatedBy": {
            "type": "string"
          },
          "deletedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "parentId",
          "placements",
          "size",
          "extends",
          "source",
          "origin",
          "flowId",
          "screenshot",
          "version",
          "createdAt",
          "updatedAt",
          "createdBy",
          "updatedBy",
          "deletedAt"
        ]
      },
      "FrameListResponse": {
        "type": "object",
        "properties": {
          "frames": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Frame"
            }
          }
        },
        "required": ["frames"]
      },
      "FrameLeanListResponse": {
        "type": "object",
        "properties": {
          "frames": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FrameLean"
            }
          }
        },
        "required": ["frames"]
      },
      "PutFrameResponse": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          }
        },
        "required": ["version"]
      },
      "FrameConflictResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": ["FRAME_VERSION_CONFLICT"]
              },
              "message": {
                "type": "string"
              }
            },
            "required": ["code", "message"]
          },
          "head": {
            "$ref": "#/components/schemas/Frame"
          }
        },
        "required": ["error", "head"]
      },
      "CanvasDocument": {
        "type": "object",
        "properties": {
          "v": {
            "type": "number",
            "enum": [1]
          },
          "nodes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CanvasNodeEntry"
            },
            "maxItems": 2000
          },
          "edges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CanvasEdgeEntry"
            },
            "maxItems": 4000
          },
          "hidden": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 200
            },
            "maxItems": 4000
          }
        },
        "required": ["v", "nodes", "edges", "hidden"]
      },
      "CanvasNodeEntry": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "pattern": "^[a-z][a-z0-9-]{0,31}$"
          },
          "ref": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "position": {
            "$ref": "#/components/schemas/CanvasPoint"
          },
          "parent": {
            "type": "string",
            "maxLength": 200
          },
          "size": {
            "type": "object",
            "properties": {
              "width": {
                "type": "number",
                "exclusiveMinimum": 0
              },
              "height": {
                "type": "number",
                "exclusiveMinimum": 0
              }
            },
            "required": ["width", "height"]
          },
          "label": {
            "type": "string",
            "maxLength": 255
          }
        },
        "required": ["kind", "ref", "position"]
      },
      "CanvasPoint": {
        "type": "object",
        "properties": {
          "x": {
            "type": "number"
          },
          "y": {
            "type": "number"
          }
        },
        "required": ["x", "y"]
      },
      "CanvasEdgeEntry": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^edg_[A-Za-z0-9_-]{21}$"
          },
          "kind": {
            "type": "string",
            "enum": ["navigation"]
          },
          "from": {
            "type": "string",
            "maxLength": 200
          },
          "to": {
            "type": "string",
            "maxLength": 200
          },
          "label": {
            "type": "string",
            "maxLength": 255
          }
        },
        "required": ["id", "kind", "from", "to"]
      },
      "Canvas": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cnv_[A-Za-z0-9_-]{21}$",
            "example": "cnv_V1StGXR8Z5jdHi6BmyT7K"
          },
          "projectId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "document": {
            "$ref": "#/components/schemas/CanvasDocument"
          },
          "version": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string"
          },
          "updatedBy": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "document",
          "version",
          "createdAt",
          "updatedAt",
          "createdBy",
          "updatedBy"
        ]
      },
      "CanvasLean": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^cnv_[A-Za-z0-9_-]{21}$",
            "example": "cnv_V1StGXR8Z5jdHi6BmyT7K"
          },
          "projectId": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "version": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string"
          },
          "updatedBy": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "version",
          "createdAt",
          "updatedAt",
          "createdBy",
          "updatedBy"
        ]
      },
      "CanvasListResponse": {
        "type": "object",
        "properties": {
          "canvases": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CanvasLean"
            }
          }
        },
        "required": ["canvases"]
      },
      "PutCanvasResponse": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer"
          }
        },
        "required": ["version"]
      },
      "CanvasConflictResponse": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": ["CANVAS_VERSION_CONFLICT"]
              },
              "message": {
                "type": "string"
              }
            },
            "required": ["code", "message"]
          },
          "head": {
            "$ref": "#/components/schemas/Canvas"
          }
        },
        "required": ["error", "head"]
      },
      "SummarizeReleaseResponse": {
        "type": "object",
        "properties": {
          "mode": {
            "type": "string",
            "enum": ["draft", "check"]
          },
          "text": {
            "type": "string"
          },
          "cached": {
            "type": "boolean"
          },
          "modelId": {
            "type": "string",
            "example": "mistral/platform/mistral-large-2512"
          },
          "versionNumber": {
            "type": "integer"
          },
          "prevVersionNumber": {
            "type": "integer"
          }
        },
        "required": [
          "mode",
          "text",
          "cached",
          "modelId",
          "versionNumber",
          "prevVersionNumber"
        ]
      },
      "StepHistoryResponse": {
        "type": "object",
        "properties": {
          "step": {
            "type": "string"
          },
          "flow": {
            "type": ["string", "null"]
          },
          "entries": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StepHistoryEntry"
            }
          },
          "scanned": {
            "type": "integer"
          },
          "truncated": {
            "type": "boolean"
          },
          "entriesTruncated": {
            "type": "boolean"
          },
          "knownSteps": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "step",
          "flow",
          "entries",
          "scanned",
          "truncated",
          "entriesTruncated"
        ]
      },
      "StepHistoryEntry": {
        "type": "object",
        "properties": {
          "versionId": {
            "type": "string",
            "pattern": "^ver_[a-zA-Z0-9_-]+$",
            "example": "ver_a1b2c3d4"
          },
          "versionNumber": {
            "type": "integer"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "flow": {
            "type": ["string", "null"]
          },
          "change": {
            "type": "string",
            "enum": ["added", "removed", "changed"],
            "example": "changed"
          },
          "humanText": {
            "type": ["string", "null"]
          },
          "generatedSummary": {
            "type": ["string", "null"]
          }
        },
        "required": [
          "versionId",
          "versionNumber",
          "createdAt",
          "flow",
          "change",
          "humanText",
          "generatedSummary"
        ]
      },
      "HeartbeatResponse": {
        "type": "object",
        "properties": {
          "ack": {
            "type": "boolean",
            "enum": [true]
          },
          "deploymentId": {
            "type": "string",
            "pattern": "^dep_[a-zA-Z0-9_-]+$",
            "example": "dep_a1b2c3d4"
          },
          "action": {
            "type": "string",
            "enum": ["none", "stop", "update"]
          },
          "versionNumber": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "bundleUrl": {
            "type": "string"
          }
        },
        "required": ["ack", "deploymentId", "action"]
      },
      "ObserveTicketRequest": {
        "type": "object",
        "properties": {
          "scope": {
            "type": "object",
            "properties": {
              "kind": {
                "type": "string",
                "enum": ["session"]
              },
              "sessionId": {
                "type": "string",
                "minLength": 1
              }
            },
            "required": ["kind", "sessionId"]
          }
        }
      },
      "ObserveTicketResponse": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string",
            "minLength": 1
          },
          "observerUrl": {
            "type": "string",
            "format": "uri"
          }
        },
        "required": ["ticket", "observerUrl"]
      },
      "PreviewResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^prv_[a-z0-9]+$",
            "example": "prv_abc123xyz456"
          },
          "flowId": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "flowSettingsId": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "bundleUrl": {
            "type": "string",
            "format": "uri"
          },
          "activationUrl": {
            "type": ["string", "null"]
          },
          "tagMode": {
            "type": "boolean"
          },
          "createdBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "flowId",
          "flowSettingsId",
          "projectId",
          "bundleUrl",
          "activationUrl",
          "tagMode",
          "createdBy",
          "createdAt"
        ]
      },
      "CreatePreviewResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PreviewResponse"
          },
          {
            "type": "object",
            "properties": {
              "grant": {
                "type": ["string", "null"]
              }
            },
            "required": ["grant"]
          }
        ]
      },
      "ListPreviewsResponse": {
        "type": "object",
        "properties": {
          "previews": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PreviewResponse"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["previews", "total"]
      },
      "CreatePreviewRequest": {
        "type": "object",
        "properties": {
          "flowSettingsId": {
            "type": "string"
          },
          "source": {
            "oneOf": [
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": ["draft"]
                  }
                },
                "required": ["kind"]
              },
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": ["deployment-version"]
                  },
                  "deploymentVersionId": {
                    "type": "string"
                  }
                },
                "required": ["kind", "deploymentVersionId"]
              }
            ]
          },
          "tagMode": {
            "type": "boolean",
            "default": true
          }
        },
        "required": ["flowSettingsId"]
      },
      "MintGrantRequest": {
        "type": "object",
        "properties": {
          "origins": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 253,
              "example": "https://shop.example.com"
            },
            "minItems": 1,
            "maxItems": 5
          },
          "sessionId": {
            "type": "string"
          }
        },
        "required": ["origins"]
      },
      "MintGrantResponse": {
        "type": "object",
        "properties": {
          "grant": {
            "type": "string"
          },
          "activationUrl": {
            "type": "string",
            "format": "uri"
          },
          "sessionExpiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "sessionGrant": {
            "type": "string"
          },
          "sessionId": {
            "type": "string"
          }
        },
        "required": ["grant", "activationUrl", "sessionExpiresAt"]
      },
      "ObserveSessionResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^ses_[a-zA-Z0-9_-]+$",
            "example": "ses_abc123xyz456"
          },
          "projectId": {
            "type": "string"
          },
          "flowId": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "status": {
            "type": "string"
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "configSnapshot": {
            "type": "object",
            "additionalProperties": {}
          },
          "observedFlowName": {
            "type": ["string", "null"]
          },
          "serverFlowName": {
            "type": ["string", "null"]
          },
          "serverEndpoint": {
            "type": ["string", "null"]
          },
          "web": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ObserveSessionWeb"
              },
              {
                "type": "null"
              }
            ]
          },
          "server": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ObserveSessionServer"
              },
              {
                "type": "null"
              }
            ]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "recordsReceived": {
            "type": "integer",
            "minimum": 0
          },
          "createdBy": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "flowId",
          "status",
          "errorMessage",
          "configSnapshot",
          "observedFlowName",
          "serverFlowName",
          "serverEndpoint",
          "web",
          "server",
          "expiresAt",
          "recordsReceived",
          "createdBy",
          "createdAt"
        ]
      },
      "ObserveSessionWeb": {
        "type": "object",
        "properties": {
          "activationUrl": {
            "type": ["string", "null"],
            "format": "uri"
          },
          "credential": {
            "type": "string"
          },
          "previewEnabled": {
            "type": "boolean"
          },
          "bundleUrl": {
            "type": "string",
            "format": "uri"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "binding": {
            "type": "string"
          }
        },
        "required": [
          "activationUrl",
          "credential",
          "previewEnabled",
          "bundleUrl"
        ]
      },
      "ObserveSessionServer": {
        "type": "object",
        "properties": {
          "endpoint": {
            "type": ["string", "null"],
            "format": "uri"
          },
          "env": {
            "$ref": "#/components/schemas/ObserveSessionServerEnv"
          }
        },
        "required": ["endpoint", "env"]
      },
      "ObserveSessionServerEnv": {
        "type": "object",
        "properties": {
          "WALKEROS_OBSERVER_URL": {
            "type": "string",
            "format": "uri"
          },
          "WALKEROS_DEPLOYMENT_ID": {
            "type": "string"
          },
          "WALKEROS_INGEST_TOKEN": {
            "type": "string"
          }
        },
        "required": [
          "WALKEROS_OBSERVER_URL",
          "WALKEROS_DEPLOYMENT_ID",
          "WALKEROS_INGEST_TOKEN"
        ]
      },
      "ObserveSessionJourneysResponse": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string",
            "pattern": "^ses_[a-zA-Z0-9_-]+$",
            "example": "ses_abc123xyz456"
          },
          "flowId": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "assembledAt": {
            "type": "string",
            "format": "date-time"
          },
          "journeys": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "gaps": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "unattributed": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          }
        },
        "required": ["sessionId", "flowId", "assembledAt", "journeys", "gaps"]
      },
      "CreateObserveSessionRequest": {
        "type": "object",
        "properties": {
          "settingsName": {
            "type": "string",
            "minLength": 1
          },
          "force": {
            "type": "boolean"
          },
          "replace": {
            "type": "boolean"
          },
          "level": {
            "$ref": "#/components/schemas/ObserveLevel"
          },
          "origins": {
            "type": "array",
            "items": {
              "type": "string",
              "maxLength": 253,
              "example": "https://shop.example.com"
            },
            "maxItems": 20
          },
          "tagMode": {
            "type": "boolean"
          }
        },
        "required": ["settingsName"]
      },
      "ObserveLevel": {
        "type": "string",
        "enum": ["off", "standard", "trace"]
      },
      "ObserveSessionHeartbeatResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [true]
          }
        },
        "required": ["ok"]
      },
      "SecretName": {
        "type": "string",
        "minLength": 1,
        "maxLength": 255,
        "pattern": "^[A-Z_][A-Z0-9_]*$"
      },
      "CreateSecretRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "pattern": "^[A-Z_][A-Z0-9_]*$"
          },
          "value": {
            "type": "string",
            "minLength": 1,
            "maxLength": 65536
          }
        },
        "required": ["name", "value"]
      },
      "UpdateSecretRequest": {
        "type": "object",
        "properties": {
          "value": {
            "type": "string",
            "minLength": 1,
            "maxLength": 65536
          }
        },
        "required": ["value"]
      },
      "SecretSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "flowId": {
            "type": "string"
          },
          "createdAt": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "updatedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          }
        },
        "required": ["id", "name", "flowId", "createdAt", "updatedAt"]
      },
      "SecretListResponse": {
        "type": "object",
        "properties": {
          "secrets": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "flowId": {
                  "type": "string"
                },
                "createdAt": {
                  "type": ["string", "null"],
                  "format": "date-time"
                },
                "updatedAt": {
                  "type": ["string", "null"],
                  "format": "date-time"
                }
              },
              "required": ["id", "name", "flowId", "createdAt", "updatedAt"]
            }
          }
        },
        "required": ["secrets"]
      },
      "FeedbackRequest": {
        "type": "object",
        "properties": {
          "text": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000,
            "example": "The MCP flow_bundle tool is great but slow on large configs."
          },
          "userId": {
            "type": "string",
            "format": "email",
            "example": "alex@example.com"
          },
          "projectId": {
            "type": "string",
            "maxLength": 255,
            "example": "proj_abc123"
          },
          "version": {
            "type": "string",
            "maxLength": 100,
            "example": "0.4.2"
          }
        },
        "required": ["text"]
      },
      "FeedbackResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [true]
          },
          "id": {
            "type": "string",
            "example": "fb_abcdef1234567890"
          }
        },
        "required": ["ok", "id"]
      },
      "StepExample": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "public": {
            "type": "boolean"
          },
          "trigger": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "options": {}
            }
          },
          "mapping": {},
          "command": {
            "type": "string"
          },
          "in": {
            "$ref": "#/components/schemas/StepExampleEvent"
          },
          "out": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {}
            }
          }
        },
        "required": ["in"]
      },
      "StepExampleEvent": {
        "type": "object",
        "properties": {
          "entity": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": {}
          },
          "context": {
            "type": "object",
            "additionalProperties": {}
          },
          "globals": {
            "type": "object",
            "additionalProperties": {}
          },
          "custom": {
            "type": "object",
            "additionalProperties": {}
          },
          "id": {
            "type": "string"
          },
          "timestamp": {
            "type": "string"
          },
          "timing": {
            "type": "object",
            "additionalProperties": {}
          },
          "user": {
            "type": "object",
            "additionalProperties": {}
          },
          "version": {
            "type": "string"
          },
          "source": {
            "type": "string"
          },
          "trigger": {
            "type": "string"
          }
        }
      },
      "CreateStepExampleRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "public": {
            "type": "boolean"
          },
          "trigger": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "options": {}
            }
          },
          "mapping": {},
          "command": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "event": {
            "$ref": "#/components/schemas/StepExampleEvent"
          },
          "out": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {}
            }
          }
        },
        "required": ["name", "event"]
      },
      "EditStepExampleRequest": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "public": {
            "type": "boolean"
          },
          "trigger": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string"
              },
              "options": {}
            }
          },
          "mapping": {},
          "command": {
            "type": "string"
          },
          "name": {
            "type": "string",
            "minLength": 1
          },
          "event": {
            "$ref": "#/components/schemas/StepExampleEvent"
          },
          "out": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {}
            }
          }
        },
        "required": ["name"]
      },
      "StepExamplesResponse": {
        "type": "object",
        "properties": {
          "examples": {
            "type": "object",
            "additionalProperties": {
              "$ref": "#/components/schemas/StepExample"
            }
          }
        },
        "required": ["examples"]
      },
      "ObserveStepExample": {
        "type": "object",
        "properties": {
          "in": {},
          "out": {},
          "mapping": {},
          "title": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        }
      },
      "ObserveSaveExampleRequest": {
        "type": "object",
        "properties": {
          "stepPath": {
            "type": "string",
            "minLength": 1
          },
          "scenario": {
            "type": "string",
            "minLength": 1
          },
          "example": {
            "$ref": "#/components/schemas/ObserveStepExample"
          }
        },
        "required": ["stepPath", "scenario", "example"]
      },
      "SecretValuesResponse": {
        "type": "object",
        "properties": {
          "values": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": ["values"]
      },
      "ServiceAccountSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["member", "deployer", "viewer"]
          },
          "email": {
            "type": "string"
          },
          "description": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "name", "role", "email", "description", "createdAt"]
      },
      "CreateServiceAccountRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "role": {
            "type": "string",
            "enum": ["member", "deployer", "viewer"]
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          }
        },
        "required": ["name", "role"]
      },
      "UpdateServiceAccountRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "role": {
            "type": "string",
            "enum": ["member", "deployer", "viewer"]
          }
        }
      },
      "CreateServiceAccountResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["member", "deployer", "viewer"]
          },
          "email": {
            "type": "string"
          },
          "token": {
            "type": "string"
          },
          "tokenId": {
            "type": "string"
          },
          "tokenPrefix": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "role",
          "email",
          "token",
          "tokenId",
          "tokenPrefix",
          "createdAt"
        ]
      },
      "ListServiceAccountsResponse": {
        "type": "object",
        "properties": {
          "serviceAccounts": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ServiceAccountSummary"
            }
          },
          "total": {
            "type": "number"
          }
        },
        "required": ["serviceAccounts", "total"]
      },
      "CreateSaTokenRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "expiresInDays": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "maximum": 365
          }
        },
        "required": ["name"]
      },
      "SaTokenSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "lastUsedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "expiresAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "revokedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "prefix",
          "createdAt",
          "lastUsedAt",
          "expiresAt",
          "revokedAt"
        ]
      },
      "CreateSaTokenResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "token": {
            "type": "string"
          },
          "prefix": {
            "type": "string"
          },
          "expiresAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "name", "token", "prefix", "expiresAt", "createdAt"]
      },
      "ListSaTokensResponse": {
        "type": "object",
        "properties": {
          "tokens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SaTokenSummary"
            }
          },
          "total": {
            "type": "number"
          }
        },
        "required": ["tokens", "total"]
      },
      "Invitation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "role": {
            "type": "string",
            "enum": ["admin", "member", "deployer", "viewer"],
            "default": "member",
            "example": "member"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "accepted", "declined", "expired", "cancelled"]
          },
          "invitedBy": {
            "type": ["string", "null"]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "email",
          "status",
          "invitedBy",
          "expiresAt",
          "createdAt"
        ]
      },
      "CreateInvitationRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "role": {
            "type": "string",
            "enum": ["admin", "member", "deployer", "viewer"],
            "default": "member",
            "example": "member"
          }
        },
        "required": ["email"]
      },
      "CreateInvitationResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "role": {
            "type": "string",
            "enum": ["admin", "member", "deployer", "viewer"],
            "default": "member",
            "example": "member"
          },
          "status": {
            "type": "string",
            "enum": ["pending"]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": ["id", "email", "status", "expiresAt", "createdAt"]
      },
      "ListInvitationsResponse": {
        "type": "object",
        "properties": {
          "invitations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Invitation"
            }
          },
          "total": {
            "type": "number"
          }
        },
        "required": ["invitations", "total"]
      },
      "InvitationPreview": {
        "type": "object",
        "properties": {
          "projectName": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "role": {
            "type": "string",
            "enum": ["admin", "member", "deployer", "viewer"],
            "default": "member",
            "example": "member"
          },
          "status": {
            "type": "string",
            "enum": ["pending", "accepted", "declined", "expired", "cancelled"]
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "invitedByEmail": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          }
        },
        "required": [
          "projectName",
          "email",
          "status",
          "expiresAt",
          "invitedByEmail"
        ]
      },
      "AcceptInvitationResponse": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string"
          },
          "projectName": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "enum": ["admin", "member", "deployer", "viewer"],
            "default": "member",
            "example": "member"
          },
          "alreadyMember": {
            "type": "boolean"
          }
        },
        "required": ["projectId", "projectName", "alreadyMember"]
      },
      "TelemetryEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "entity": {
            "type": "string"
          },
          "action": {
            "type": "string"
          },
          "data": {
            "type": "object",
            "additionalProperties": {}
          },
          "context": {
            "type": "object",
            "additionalProperties": {}
          },
          "globals": {
            "type": "object",
            "additionalProperties": {}
          },
          "custom": {
            "type": "object",
            "additionalProperties": {}
          },
          "user": {
            "type": "object",
            "properties": {
              "device": {
                "type": "string"
              },
              "session": {
                "type": "string"
              },
              "os": {
                "type": "string"
              },
              "osVersion": {
                "type": "string"
              },
              "node": {
                "type": "string"
              },
              "language": {
                "type": "string"
              },
              "timezone": {
                "type": "string"
              }
            },
            "required": [
              "device",
              "os",
              "osVersion",
              "node",
              "language",
              "timezone"
            ],
            "additionalProperties": {}
          },
          "nested": {
            "type": "array",
            "items": {}
          },
          "consent": {
            "type": "object",
            "additionalProperties": {
              "type": "boolean"
            }
          },
          "trigger": {
            "type": "string"
          },
          "timestamp": {
            "type": "number"
          },
          "timing": {
            "type": "number"
          },
          "source": {
            "type": "object",
            "properties": {
              "type": {
                "type": "string",
                "enum": ["cli", "mcp"]
              },
              "platform": {
                "type": "string"
              },
              "release": {
                "type": "object",
                "additionalProperties": {
                  "type": "string"
                }
              },
              "version": {
                "type": "string"
              },
              "schema": {
                "type": "string"
              },
              "tool": {
                "type": "string"
              },
              "command": {
                "type": "string"
              }
            },
            "required": ["type"],
            "additionalProperties": {}
          }
        },
        "required": [
          "id",
          "name",
          "entity",
          "action",
          "data",
          "context",
          "globals",
          "custom",
          "user",
          "nested",
          "consent",
          "trigger",
          "timestamp",
          "timing",
          "source"
        ]
      },
      "UpsertBillingDetailsRequest": {
        "type": "object",
        "properties": {
          "companyName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "address": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "address2": {
            "type": "string",
            "maxLength": 255
          },
          "postalCode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20
          },
          "city": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "country": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2
          },
          "vatId": {
            "type": "string",
            "maxLength": 50
          },
          "invoiceEmail": {
            "type": "string",
            "format": "email"
          },
          "contactName": {
            "type": "string",
            "maxLength": 255
          }
        },
        "required": [
          "companyName",
          "address",
          "postalCode",
          "city",
          "country",
          "invoiceEmail"
        ]
      },
      "BillingDetailsResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "companyName": {
            "type": "string"
          },
          "address": {
            "type": "string"
          },
          "address2": {
            "type": ["string", "null"]
          },
          "postalCode": {
            "type": "string"
          },
          "city": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "vatId": {
            "type": ["string", "null"]
          },
          "invoiceEmail": {
            "type": "string"
          },
          "contactName": {
            "type": ["string", "null"]
          },
          "taxTreatment": {
            "type": "string",
            "enum": ["reverse_charge", "domestic", "export", "eu_standard"]
          },
          "viesStatus": {
            "type": "string",
            "enum": ["verified", "invalid", "unavailable", "not_checked"]
          },
          "viesCompanyName": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "projectId",
          "companyName",
          "address",
          "address2",
          "postalCode",
          "city",
          "country",
          "vatId",
          "invoiceEmail",
          "contactName",
          "taxTreatment",
          "viesStatus",
          "viesCompanyName",
          "createdAt",
          "updatedAt"
        ]
      },
      "DeployedContentResponse": {
        "type": "object",
        "properties": {
          "deploymentId": {
            "type": ["string", "null"]
          },
          "versionNumber": {
            "type": ["integer", "null"],
            "exclusiveMinimum": 0
          },
          "status": {
            "type": ["string", "null"]
          },
          "flowSettingsName": {
            "type": ["string", "null"]
          },
          "publishedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "content": {}
        },
        "required": [
          "deploymentId",
          "versionNumber",
          "status",
          "flowSettingsName",
          "publishedAt"
        ]
      },
      "ListHeartbeatsResponse": {
        "type": "object",
        "properties": {
          "records": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/HeartbeatRecord"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["records", "total", "limit", "offset"]
      },
      "HeartbeatRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "instanceId": {
            "type": ["string", "null"]
          },
          "cliVersion": {
            "type": ["string", "null"]
          },
          "configVersion": {
            "type": ["integer", "null"]
          },
          "mode": {
            "type": ["string", "null"]
          },
          "uptime": {
            "type": ["integer", "null"]
          },
          "eventsIn": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "eventsOut": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "eventsFailed": {
            "type": ["integer", "null"],
            "minimum": 0
          },
          "perDestinationBreakdown": {},
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "instanceId",
          "cliVersion",
          "configVersion",
          "mode",
          "uptime",
          "eventsIn",
          "eventsOut",
          "eventsFailed",
          "receivedAt"
        ]
      },
      "RotateIngestTokenResponse": {
        "type": "object",
        "properties": {
          "ingestToken": {
            "type": "string"
          }
        },
        "required": ["ingestToken"]
      },
      "DeploymentUsageResponse": {
        "type": "object",
        "properties": {
          "totalEventsIn": {
            "type": "integer",
            "minimum": 0
          },
          "totalEventsOut": {
            "type": "integer",
            "minimum": 0
          },
          "totalEventsFailed": {
            "type": "integer",
            "minimum": 0
          },
          "totalInstances": {
            "type": "integer",
            "minimum": 0
          },
          "heartbeatCount": {
            "type": "integer",
            "minimum": 0
          },
          "from": {
            "type": "string",
            "format": "date-time"
          },
          "to": {
            "type": "string",
            "format": "date-time"
          },
          "averageThroughputPerHour": {
            "type": "integer",
            "minimum": 0
          },
          "period": {
            "type": "string"
          },
          "buckets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageBucket"
            }
          },
          "destinations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/UsageDestination"
            }
          }
        },
        "required": [
          "totalEventsIn",
          "totalEventsOut",
          "totalEventsFailed",
          "totalInstances",
          "heartbeatCount",
          "from",
          "to",
          "averageThroughputPerHour",
          "period",
          "buckets"
        ]
      },
      "UsageBucket": {
        "type": "object",
        "properties": {
          "bucket": {
            "type": "string",
            "format": "date-time"
          },
          "eventsIn": {
            "type": "integer",
            "minimum": 0
          },
          "eventsOut": {
            "type": "integer",
            "minimum": 0
          },
          "eventsFailed": {
            "type": "integer",
            "minimum": 0
          },
          "instances": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "bucket",
          "eventsIn",
          "eventsOut",
          "eventsFailed",
          "instances"
        ]
      },
      "UsageDestination": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "failed": {
            "type": "integer",
            "minimum": 0
          },
          "duration": {
            "type": "number",
            "minimum": 0
          },
          "dlqSize": {
            "type": "integer",
            "minimum": 0
          },
          "dropped": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": [
          "name",
          "count",
          "failed",
          "duration",
          "dlqSize",
          "dropped"
        ]
      },
      "CreateCustomDomainRequest": {
        "type": "object",
        "properties": {
          "hostname": {
            "type": "string",
            "minLength": 1,
            "maxLength": 253
          },
          "deploymentId": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": ["hostname"]
      },
      "CustomDomain": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "deploymentId": {
            "type": "string"
          },
          "hostname": {
            "type": "string"
          },
          "kind": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "scwResourceId": {
            "type": ["string", "null"]
          },
          "certStatus": {
            "type": "string"
          },
          "verifiedAt": {
            "type": ["string", "null"],
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "deploymentId",
          "hostname",
          "kind",
          "status",
          "scwResourceId",
          "certStatus",
          "verifiedAt",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListCustomDomainsResponse": {
        "type": "object",
        "properties": {
          "domains": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CustomDomain"
            }
          }
        },
        "required": ["domains"]
      },
      "DeployTokenStatusResponse": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "hasToken": {
                "type": "boolean",
                "enum": [false]
              }
            },
            "required": ["hasToken"]
          },
          {
            "type": "object",
            "properties": {
              "hasToken": {
                "type": "boolean",
                "enum": [true]
              },
              "deploymentId": {
                "type": "string"
              },
              "status": {
                "type": "string"
              },
              "healthy": {
                "type": "boolean"
              },
              "lastHeartbeatAt": {
                "type": ["string", "null"],
                "format": "date-time"
              },
              "instanceId": {
                "type": ["string", "null"]
              },
              "cliVersion": {
                "type": ["string", "null"]
              }
            },
            "required": [
              "hasToken",
              "deploymentId",
              "status",
              "healthy",
              "lastHeartbeatAt",
              "instanceId",
              "cliVersion"
            ]
          }
        ]
      },
      "CreateDeployTokenResponse": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          },
          "deploymentId": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "flowId": {
            "type": "string"
          },
          "configName": {
            "type": "string"
          }
        },
        "required": [
          "token",
          "deploymentId",
          "projectId",
          "flowId",
          "configName"
        ]
      },
      "EntitlementsResponse": {
        "type": "object",
        "properties": {
          "planId": {
            "type": "string"
          },
          "role": {
            "type": "string"
          },
          "entitlements": {
            "type": "object",
            "additionalProperties": {
              "anyOf": [
                {
                  "type": "boolean"
                },
                {
                  "type": "number"
                }
              ]
            }
          }
        },
        "required": ["planId", "role", "entitlements"]
      },
      "SetLlmConfigRequest": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "action": {
                "type": "string",
                "enum": ["clear"]
              }
            },
            "required": ["action"]
          },
          {
            "type": "object",
            "properties": {
              "action": {
                "type": "string",
                "enum": ["set"]
              },
              "config": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": ["mistral"]
                      },
                      "modelId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "apiKey": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "required": ["provider", "modelId", "apiKey"]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": ["anthropic"]
                      },
                      "modelId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "apiKey": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "required": ["provider", "modelId", "apiKey"]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": ["openai"]
                      },
                      "modelId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "apiKey": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "required": ["provider", "modelId", "apiKey"]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": ["google"]
                      },
                      "modelId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "apiKey": {
                        "type": "string",
                        "minLength": 1
                      }
                    },
                    "required": ["provider", "modelId", "apiKey"]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": ["openai-compatible"]
                      },
                      "modelId": {
                        "type": "string",
                        "minLength": 1
                      },
                      "apiKey": {
                        "type": "string",
                        "minLength": 1
                      },
                      "baseURL": {
                        "type": "string",
                        "format": "uri"
                      }
                    },
                    "required": ["provider", "modelId", "apiKey", "baseURL"]
                  }
                ]
              }
            },
            "required": ["action", "config"]
          }
        ]
      },
      "SetLlmConfigResponse": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "cleared": {
                "type": "boolean",
                "enum": [true]
              }
            },
            "required": ["cleared"]
          },
          {
            "type": "object",
            "properties": {
              "saved": {
                "type": "boolean",
                "enum": [true]
              }
            },
            "required": ["saved"]
          }
        ]
      },
      "LlmConfigStatusResponse": {
        "type": "object",
        "properties": {
          "provider": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": ["platform", "byok", "byom"]
          }
        },
        "required": ["provider", "source"]
      },
      "ListChatSessionsResponse": {
        "type": "object",
        "properties": {
          "sessions": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatSessionSummary"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["sessions", "total"]
      },
      "ChatSessionSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastActiveAt": {
            "type": "string",
            "format": "date-time"
          },
          "messageCount": {
            "type": "integer",
            "minimum": 0
          },
          "firstUserMessage": {
            "type": "string"
          }
        },
        "required": ["id", "createdAt", "lastActiveAt", "messageCount"]
      },
      "ChatSessionDetailResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastActiveAt": {
            "type": "string",
            "format": "date-time"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ChatSessionMessage"
            }
          }
        },
        "required": ["id", "createdAt", "lastActiveAt", "messages"]
      },
      "ChatSessionMessage": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer"
          },
          "role": {
            "type": "string"
          },
          "content": {},
          "createdAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": ["seq", "role", "createdAt"]
      },
      "ElicitRequest": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "elicitationId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 128
          },
          "result": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": ["accept"]
                  },
                  "content": {
                    "type": "object",
                    "additionalProperties": {
                      "anyOf": [
                        {
                          "type": "string"
                        },
                        {
                          "type": "number"
                        },
                        {
                          "type": "boolean"
                        },
                        {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        }
                      ]
                    }
                  }
                },
                "required": ["action"]
              },
              {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": ["decline"]
                  }
                },
                "required": ["action"]
              },
              {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": ["cancel"]
                  }
                },
                "required": ["action"]
              }
            ]
          }
        },
        "required": ["sessionId", "elicitationId", "result"]
      },
      "ElicitResponse": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [true]
          }
        },
        "required": ["ok"]
      },
      "PackageCatalogResponse": {
        "type": "object",
        "properties": {
          "catalog": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PackageCatalogEntry"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["catalog", "count"]
      },
      "PackageCatalogEntry": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "type": {
            "type": "string"
          },
          "platform": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": ["name", "version", "type", "platform"]
      },
      "PackageSearchResponse": {
        "type": "object",
        "properties": {
          "packages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PackageSearchHit"
            }
          },
          "count": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["packages", "count"]
      },
      "PackageSearchHit": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "version": {
            "type": "string"
          },
          "description": {
            "type": "string"
          }
        },
        "required": ["name", "version", "description"]
      },
      "PackageSearchLogRequest": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "minLength": 1,
            "maxLength": 214
          },
          "result": {
            "type": "string",
            "enum": ["hit", "miss"]
          },
          "platform": {
            "type": "string",
            "enum": ["web", "server"]
          },
          "projectId": {
            "type": "string",
            "maxLength": 64
          }
        },
        "required": ["query", "result"]
      },
      "ListRunnersResponse": {
        "type": "object",
        "properties": {
          "runners": {
            "type": "array",
            "items": {}
          },
          "total": {
            "type": "integer",
            "minimum": 0
          }
        },
        "required": ["runners", "total"]
      },
      "RunnerHeartbeatResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "instanceId": {
            "type": "string"
          },
          "deploymentId": {
            "type": "string"
          }
        },
        "required": ["id", "instanceId", "deploymentId"]
      },
      "ObserveTimingRequest": {
        "type": "object",
        "properties": {
          "connectId": {
            "type": "string",
            "minLength": 1
          },
          "ticketMs": {
            "type": "number",
            "minimum": 0
          },
          "sseMs": {
            "type": "number",
            "minimum": 0
          },
          "totalMs": {
            "type": "number",
            "minimum": 0
          }
        },
        "required": ["connectId", "ticketMs", "sseMs", "totalMs"]
      },
      "MagicLinkResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "message": {
            "type": "string",
            "example": "Magic link sent"
          }
        },
        "required": ["success", "message"]
      },
      "MagicLinkRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "redirect_to": {
            "type": "string",
            "example": "/dashboard"
          }
        },
        "required": ["email"]
      },
      "VerifyResponse": {
        "oneOf": [
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": ["ok"]
              },
              "redirectTo": {
                "type": "string",
                "example": "/"
              }
            },
            "required": ["status", "redirectTo"]
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": ["confirm_required"]
              },
              "email": {
                "type": "string",
                "example": "user@example.com"
              }
            },
            "required": ["status", "email"]
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": ["expired", "used", "invalid", "malformed"]
              }
            },
            "required": ["status"]
          }
        ]
      },
      "VerifyRequest": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string",
            "minLength": 1
          },
          "redirect_to": {
            "type": "string",
            "example": "/dashboard"
          },
          "confirm": {
            "type": "boolean"
          }
        },
        "required": ["token"]
      },
      "WhoamiResponse": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string",
            "example": "user_a1b2c3d4"
          },
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "projectId": {
            "type": ["string", "null"],
            "example": null
          }
        },
        "required": ["userId", "email", "projectId"]
      },
      "ListSessionsResponse": {
        "type": "object",
        "properties": {
          "sessions": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "expiresAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "lastTouchedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "isCurrent": {
                  "type": "boolean"
                }
              },
              "required": [
                "id",
                "createdAt",
                "expiresAt",
                "lastTouchedAt",
                "isCurrent"
              ]
            }
          }
        },
        "required": ["sessions"]
      },
      "ListProjectsResponse": {
        "type": "object",
        "properties": {
          "projects": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Project"
            }
          },
          "total": {
            "type": "number"
          },
          "nextCursor": {
            "type": ["string", "null"]
          }
        },
        "required": ["projects", "total", "nextCursor"]
      },
      "CreateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          }
        },
        "required": ["name"]
      },
      "ProjectDetailResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "pattern": "^proj_[a-zA-Z0-9_-]+$",
            "example": "proj_x7y8z9"
          },
          "name": {
            "type": "string"
          },
          "siteUrl": {
            "type": ["string", "null"],
            "format": "uri",
            "example": "https://example.com"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "member", "deployer", "viewer"]
          }
        },
        "required": ["id", "name", "role"]
      },
      "UpdateProjectRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "siteUrl": {
            "type": ["string", "null"],
            "maxLength": 2048,
            "format": "uri",
            "example": "https://example.com"
          }
        }
      },
      "ListMembersResponse": {
        "type": "object",
        "properties": {
          "members": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Member"
            }
          },
          "total": {
            "type": "number"
          }
        },
        "required": ["members", "total"]
      },
      "AddMemberRequest": {
        "type": "object",
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "example": "user@example.com"
          },
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "member", "deployer", "viewer"],
            "default": "member"
          }
        },
        "required": ["email"]
      },
      "UpdateMemberRequest": {
        "type": "object",
        "properties": {
          "role": {
            "type": "string",
            "enum": ["owner", "admin", "member", "deployer", "viewer"]
          }
        },
        "required": ["role"]
      },
      "ListFlowsResponse": {
        "type": "object",
        "properties": {
          "flows": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowSummary"
            }
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "nextCursor": {
            "type": ["string", "null"]
          }
        },
        "required": ["flows", "total", "nextCursor"]
      },
      "CreateFlowRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          },
          "config": {
            "$ref": "#/components/schemas/FlowConfig"
          }
        },
        "required": ["name"]
      },
      "UpdateFlowRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          },
          "config": {
            "$ref": "#/components/schemas/FlowConfig"
          }
        }
      },
      "DuplicateFlowRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "example": "my-website-flow"
          }
        }
      },
      "DeploymentResponse": {
        "type": ["object", "null"],
        "properties": {
          "id": {
            "type": "string"
          },
          "flowId": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"]
          },
          "status": {
            "type": "string"
          },
          "containerUrl": {
            "type": ["string", "null"]
          },
          "publicUrl": {
            "type": ["string", "null"]
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "flowId",
          "type",
          "status",
          "containerUrl",
          "errorMessage",
          "createdAt",
          "updatedAt"
        ]
      },
      "ListSettingsResponse": {
        "type": "object",
        "properties": {
          "settings": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/FlowSettingsSummary"
            }
          }
        },
        "required": ["settings"]
      },
      "SettingsDeploymentResponse": {
        "type": ["object", "null"],
        "properties": {
          "id": {
            "type": "string"
          },
          "flowId": {
            "type": "string"
          },
          "settingsId": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"]
          },
          "status": {
            "type": "string"
          },
          "containerUrl": {
            "type": ["string", "null"]
          },
          "publicUrl": {
            "type": ["string", "null"]
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "flowId",
          "settingsId",
          "type",
          "status",
          "containerUrl",
          "publicUrl",
          "errorMessage",
          "createdAt",
          "updatedAt"
        ]
      },
      "SettingsDeploymentDetailResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "flowId": {
            "type": "string"
          },
          "settingsId": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "enum": ["web", "server"]
          },
          "containerUrl": {
            "type": ["string", "null"]
          },
          "publicUrl": {
            "type": ["string", "null"]
          },
          "errorMessage": {
            "type": ["string", "null"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "id",
          "flowId",
          "settingsId",
          "status",
          "type",
          "containerUrl",
          "publicUrl",
          "errorMessage",
          "createdAt",
          "updatedAt"
        ]
      },
      "FlowJourneysResponse": {
        "type": "object",
        "properties": {
          "sessionId": {
            "type": ["string", "null"],
            "pattern": "^ses_[a-zA-Z0-9_-]+$",
            "example": "ses_abc123xyz456"
          },
          "flowId": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "assembledAt": {
            "type": "string",
            "format": "date-time"
          },
          "journeys": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "gaps": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          },
          "unattributed": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": {}
            }
          }
        },
        "required": ["sessionId", "flowId", "assembledAt", "journeys", "gaps"]
      },
      "ListVersionsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Version"
            }
          },
          "flowId": {
            "type": "string",
            "pattern": "^flow_[a-zA-Z0-9_-]+$",
            "example": "flow_a1b2c3d4"
          },
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "limit": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "offset": {
            "type": "integer",
            "minimum": 0
          },
          "hasMore": {
            "type": "boolean"
          }
        },
        "required": ["data", "flowId", "total", "limit", "offset", "hasMore"]
      },
      "GetVersionResponse": {
        "type": "object",
        "properties": {
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 1
          },
          "content": {
            "$ref": "#/components/schemas/FlowConfig"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "createdBy": {
            "type": "string",
            "enum": ["user", "auto_save", "restore", "deploy", "preview"]
          }
        },
        "required": ["version", "content", "createdAt", "createdBy"]
      },
      "ListAutomationTokensResponse": {
        "type": "object",
        "properties": {
          "tokens": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/AutomationTokenSummary"
            }
          }
        },
        "required": ["tokens"]
      },
      "CreateAutomationTokenResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "tok_a1b2c3d4"
          },
          "name": {
            "type": "string",
            "example": "CI Pipeline"
          },
          "token": {
            "type": "string",
            "example": "wos_pat_a1b2c3d4..."
          },
          "tokenPrefix": {
            "type": "string",
            "example": "wos_pat_a1b2"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["read", "write"]
          },
          "audience": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "example": ["api", "mcp"]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "name",
          "token",
          "tokenPrefix",
          "scope",
          "audience",
          "createdAt",
          "expiresAt"
        ]
      },
      "CreateAutomationTokenRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "example": "CI Pipeline"
          },
          "scope": {
            "type": "string",
            "enum": ["read", "read write"],
            "example": "read write"
          },
          "expiresInDays": {
            "anyOf": [
              {
                "type": "number",
                "enum": [30]
              },
              {
                "type": "number",
                "enum": [90]
              },
              {
                "type": "number",
                "enum": [180]
              },
              {
                "type": "number",
                "enum": [365]
              }
            ],
            "example": 90
          }
        },
        "required": ["name", "scope", "expiresInDays"]
      },
      "BundleResponse": {
        "type": "object",
        "properties": {
          "bundleId": {
            "type": "string"
          },
          "cached": {
            "type": "boolean"
          }
        },
        "required": ["bundleId", "cached"]
      },
      "SimulateResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean"
          },
          "result": {
            "type": "object",
            "properties": {
              "step": {
                "type": "string",
                "enum": ["source", "transformer", "destination"]
              },
              "name": {
                "type": "string"
              },
              "events": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": {}
                }
              },
              "calls": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "fn": {
                      "type": "string"
                    },
                    "args": {
                      "type": "array",
                      "items": {}
                    },
                    "ts": {
                      "type": "number"
                    }
                  },
                  "required": ["fn", "args", "ts"]
                }
              },
              "duration": {
                "type": "number"
              }
            },
            "required": ["step", "name", "events", "calls", "duration"]
          }
        },
        "required": ["success"]
      },
      "SimulateRequest": {
        "type": "object",
        "properties": {
          "bundleId": {
            "type": "string",
            "pattern": "^[a-f0-9]{8,64}$"
          },
          "config": {
            "type": "object",
            "additionalProperties": {}
          },
          "event": {
            "type": "object",
            "additionalProperties": {}
          },
          "step": {
            "type": "string",
            "pattern": "^(source|transformer|destination)\\..+$"
          }
        },
        "required": ["bundleId", "config", "event", "step"]
      },
      "RegisterRuntimeRequest": {
        "type": "object",
        "properties": {
          "flowId": {
            "type": "string"
          },
          "bundlePath": {
            "type": "string"
          }
        },
        "required": ["flowId", "bundlePath"]
      },
      "ValidateTicketResponse": {
        "type": "object",
        "properties": {
          "userId": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "replay": {
            "type": "object",
            "properties": {
              "size": {
                "type": "number"
              },
              "ttlMs": {
                "type": "number"
              }
            },
            "required": ["size", "ttlMs"]
          },
          "scope": {
            "anyOf": [
              {
                "type": "object",
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": ["session"]
                  },
                  "sessionId": {
                    "type": "string"
                  }
                },
                "required": ["kind", "sessionId"]
              },
              {
                "type": "null"
              }
            ]
          }
        },
        "required": ["userId", "projectId", "replay", "scope"]
      },
      "ValidateTicketRequest": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": ["ticket"]
      },
      "HealthResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "example": "ok"
          },
          "appVersion": {
            "type": "string",
            "example": "a1b2c3d",
            "description": "Build identity of the running app (git short hash injected at build time)."
          },
          "contractVersion": {
            "type": "string",
            "example": "1.0.0",
            "description": "Semver of the API contract the server implements."
          },
          "contractHash": {
            "type": "string",
            "example": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            "description": "Deterministic sha256 of the OpenAPI contract content."
          }
        },
        "required": ["status", "appVersion", "contractVersion", "contractHash"]
      },
      "DeclineInvitationResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string"
          }
        },
        "required": ["message"]
      },
      "ScreenshotUploadResponse": {
        "type": "object",
        "properties": {
          "assetId": {
            "type": "string",
            "pattern": "^fas_[A-Za-z0-9_-]{21}$",
            "example": "fas_V1StGXR8Z5jdHi6BmyT7K"
          },
          "reused": {
            "type": "boolean"
          }
        },
        "required": ["assetId", "reused"]
      },
      "FrameScreenshotMeta": {
        "type": "object",
        "properties": {
          "capturedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "size": {
            "$ref": "#/components/schemas/PlanSize"
          },
          "dpr": {
            "type": "number",
            "exclusiveMinimum": 0
          },
          "capturedRect": {
            "$ref": "#/components/schemas/PlanRect"
          }
        },
        "required": ["capturedAt", "size", "dpr", "capturedRect"]
      },
      "HeartbeatRequest": {
        "type": "object",
        "properties": {
          "instanceId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "example": "a1b2c3d4e5f6"
          },
          "flowId": {
            "type": "string",
            "example": "flow_abc123"
          },
          "configVersion": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": ["local", "collect", "serve"]
          },
          "cliVersion": {
            "type": "string",
            "example": "1.3.0"
          },
          "uptime": {
            "type": "integer",
            "minimum": 0
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {}
          },
          "deploymentId": {
            "type": "string",
            "example": "dpl_abc123"
          },
          "counters": {
            "type": "object",
            "properties": {
              "eventsIn": {
                "type": "integer",
                "minimum": 0
              },
              "eventsOut": {
                "type": "integer",
                "minimum": 0
              },
              "eventsFailed": {
                "type": "integer",
                "minimum": 0
              },
              "destinations": {
                "type": "object",
                "additionalProperties": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "failed": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "duration": {
                      "type": "number",
                      "minimum": 0
                    },
                    "dlqSize": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "dropped": {
                      "type": "integer",
                      "minimum": 0
                    }
                  },
                  "required": ["count", "failed", "duration"]
                }
              }
            },
            "required": [
              "eventsIn",
              "eventsOut",
              "eventsFailed",
              "destinations"
            ]
          },
          "recentErrors": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string",
                  "maxLength": 256
                },
                "count": {
                  "type": "integer",
                  "minimum": 1
                },
                "firstSeen": {
                  "type": "string",
                  "format": "date-time"
                },
                "lastSeen": {
                  "type": "string",
                  "format": "date-time"
                }
              },
              "required": ["message", "count", "firstSeen", "lastSeen"]
            },
            "maxItems": 50
          },
          "recentLogs": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "time": {
                  "type": "string",
                  "format": "date-time"
                },
                "level": {
                  "type": "string",
                  "enum": ["error", "warn", "info", "debug"]
                },
                "message": {
                  "type": "string",
                  "maxLength": 256
                }
              },
              "required": ["time", "level", "message"]
            },
            "maxItems": 100
          }
        },
        "required": ["instanceId", "flowId"]
      },
      "OAuthClientRegistrationResponse": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "example": "client_abc"
          },
          "client_id_issued_at": {
            "type": "integer",
            "example": 1725400000
          },
          "client_name": {
            "type": "string"
          },
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": ["none"]
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "client_id",
          "client_id_issued_at",
          "client_name",
          "redirect_uris",
          "token_endpoint_auth_method",
          "grant_types",
          "response_types"
        ]
      },
      "OAuthRegistrationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "enum": ["invalid_client_metadata", "invalid_redirect_uri"]
          },
          "error_description": {
            "type": "string"
          }
        },
        "required": ["error", "error_description"]
      },
      "OAuthClientRegistrationRequest": {
        "type": "object",
        "properties": {
          "redirect_uris": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri"
            },
            "minItems": 1,
            "maxItems": 10,
            "example": ["https://claude.ai/api/mcp/auth_callback"]
          },
          "client_name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "token_endpoint_auth_method": {
            "type": "string",
            "enum": ["none"]
          },
          "grant_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["authorization_code", "refresh_token"]
            },
            "minItems": 1
          },
          "response_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["code"]
            }
          },
          "client_uri": {
            "type": "string",
            "format": "uri"
          },
          "logo_uri": {
            "type": "string",
            "format": "uri"
          },
          "scope": {
            "type": "string"
          },
          "software_id": {
            "type": "string"
          },
          "software_version": {
            "type": "string"
          }
        },
        "required": ["redirect_uris"]
      },
      "DeviceAuthorizationResponse": {
        "type": "object",
        "properties": {
          "device_code": {
            "type": "string"
          },
          "user_code": {
            "type": "string",
            "example": "WDJB-MJHT"
          },
          "verification_uri": {
            "type": "string"
          },
          "verification_uri_complete": {
            "type": "string"
          },
          "expires_in": {
            "type": "integer",
            "example": 900
          },
          "interval": {
            "type": "integer",
            "example": 5
          }
        },
        "required": [
          "device_code",
          "user_code",
          "verification_uri",
          "verification_uri_complete",
          "expires_in",
          "interval"
        ]
      },
      "OAuthError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "example": "invalid_client"
          },
          "error_description": {
            "type": "string"
          }
        },
        "required": ["error", "error_description"]
      },
      "DeviceAuthorizationRequest": {
        "type": "object",
        "properties": {
          "client_id": {
            "type": "string",
            "example": "walkeros-cli"
          },
          "scope": {
            "type": "string",
            "example": "read write offline_access"
          },
          "resource": {
            "type": "string",
            "example": "https://app.walkeros.io/api"
          }
        },
        "required": ["client_id"]
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "token_type": {
            "type": "string",
            "enum": ["Bearer"]
          },
          "expires_in": {
            "type": "integer",
            "example": 3600
          },
          "refresh_token": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "example": "read write offline_access"
          }
        },
        "required": ["access_token", "token_type", "expires_in", "scope"]
      },
      "TokenRequest": {
        "type": "object",
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "authorization_code",
              "refresh_token",
              "urn:ietf:params:oauth:grant-type:device_code"
            ],
            "example": "authorization_code"
          },
          "client_id": {
            "type": "string",
            "example": "walkeros-cli"
          },
          "client_secret": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "redirect_uri": {
            "type": "string"
          },
          "code_verifier": {
            "type": "string"
          },
          "refresh_token": {
            "type": "string"
          },
          "device_code": {
            "type": "string"
          },
          "scope": {
            "type": "string",
            "example": "read offline_access"
          },
          "resource": {
            "type": "string",
            "example": "https://app.walkeros.io/api"
          }
        },
        "required": ["grant_type"]
      },
      "RevocationRequest": {
        "type": "object",
        "properties": {
          "token": {
            "type": "string"
          },
          "token_type_hint": {
            "type": "string",
            "enum": ["access_token", "refresh_token"]
          },
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": "string"
          }
        },
        "required": ["token"]
      },
      "DeviceApprovalResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "enum": [true]
          },
          "decision": {
            "type": "string",
            "enum": ["approve", "deny"]
          }
        },
        "required": ["success", "decision"]
      },
      "DeviceApprovalRequest": {
        "type": "object",
        "properties": {
          "userCode": {
            "type": "string",
            "minLength": 1,
            "example": "WDJB-MJHT"
          },
          "decision": {
            "type": "string",
            "enum": ["approve", "deny"]
          }
        },
        "required": ["userCode", "decision"]
      },
      "OAuthConsentDecisionResponse": {
        "type": "object",
        "properties": {
          "redirectTo": {
            "type": "string",
            "example": "https://claude.ai/api/mcp/auth_callback?code=abc&state=xyz"
          }
        },
        "required": ["redirectTo"]
      },
      "OAuthConsentDecisionRequest": {
        "type": "object",
        "properties": {
          "ticket": {
            "type": "string",
            "minLength": 1
          },
          "decision": {
            "type": "string",
            "enum": ["allow", "deny"]
          }
        },
        "required": ["ticket", "decision"]
      },
      "ListOAuthGrantsResponse": {
        "type": "object",
        "properties": {
          "grants": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OAuthGrantSummary"
            }
          }
        },
        "required": ["grants"]
      },
      "OAuthGrantSummary": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "clientId": {
            "type": "string"
          },
          "clientName": {
            "type": "string"
          },
          "scope": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "lastUsedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "id",
          "clientId",
          "clientName",
          "scope",
          "createdAt",
          "lastUsedAt"
        ]
      },
      "ListOAuthClientsResponse": {
        "type": "object",
        "properties": {
          "clients": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OAuthClientSummary"
            }
          }
        },
        "required": ["clients"]
      },
      "OAuthClientSummary": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": ["dcr", "cimd", "confidential", "builtin"]
          },
          "name": {
            "type": "string"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tokenEndpointAuthMethod": {
            "type": "string",
            "enum": ["none", "client_secret_basic", "client_secret_post"]
          },
          "allowedResources": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["mcp", "api"]
            }
          },
          "revokedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          }
        },
        "required": [
          "clientId",
          "kind",
          "name",
          "redirectUris",
          "grantTypes",
          "tokenEndpointAuthMethod",
          "allowedResources",
          "revokedAt"
        ]
      },
      "CreateOAuthClientResponse": {
        "type": "object",
        "properties": {
          "clientId": {
            "type": "string"
          },
          "kind": {
            "type": "string",
            "enum": ["dcr", "cimd", "confidential", "builtin"]
          },
          "name": {
            "type": "string"
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "tokenEndpointAuthMethod": {
            "type": "string",
            "enum": ["none", "client_secret_basic", "client_secret_post"]
          },
          "allowedResources": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["mcp", "api"]
            }
          },
          "revokedAt": {
            "type": ["string", "null"],
            "format": "date-time",
            "example": "2026-01-26T14:30:00.000Z"
          },
          "clientSecret": {
            "type": "string"
          }
        },
        "required": [
          "clientId",
          "kind",
          "name",
          "redirectUris",
          "grantTypes",
          "tokenEndpointAuthMethod",
          "allowedResources",
          "revokedAt",
          "clientSecret"
        ]
      },
      "CreateOAuthClientRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "redirectUris": {
            "type": "array",
            "items": {
              "type": "string",
              "minLength": 1
            },
            "minItems": 1,
            "maxItems": 10
          },
          "grantTypes": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["authorization_code", "refresh_token"]
            },
            "minItems": 1,
            "default": ["authorization_code", "refresh_token"]
          },
          "allowedResources": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": ["mcp", "api"]
            },
            "minItems": 1,
            "default": ["mcp", "api"]
          },
          "authMethod": {
            "type": "string",
            "enum": ["client_secret_basic", "client_secret_post"],
            "default": "client_secret_basic"
          }
        },
        "required": ["name", "redirectUris"]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/api/auth/magic-link": {
      "post": {
        "tags": ["Auth"],
        "summary": "Request magic link",
        "description": "Send a magic link to the provided email address for passwordless authentication. Always returns success to prevent email enumeration.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MagicLinkRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Magic link sent (or would be sent if email exists)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MagicLinkResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/auth/verify": {
      "post": {
        "tags": ["Auth"],
        "summary": "Redeem magic link token",
        "description": "Redeem a magic link token and create an authenticated session. Redeems immediately when the browser-nonce cookie from the magic-link request matches; otherwise answers confirm_required and expects a follow-up call with confirm: true.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/VerifyRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Redemption result. status=ok sets the session cookie and carries the redirect target.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": ["Auth"],
        "summary": "Legacy magic link entry point",
        "description": "Side-effect-free redirector to the /auth/verify page for links minted before the page-URL change. Never consumes the token; redemption happens via POST.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "example": "abc123...",
              "description": "Magic link token"
            },
            "required": true,
            "description": "Magic link token",
            "name": "token",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "example": "/dashboard",
              "description": "Redirect URL after verification"
            },
            "required": false,
            "description": "Redirect URL after verification",
            "name": "redirect_to",
            "in": "query"
          }
        ],
        "responses": {
          "307": {
            "description": "Redirect to the /auth/verify page with the token forwarded"
          }
        }
      }
    },
    "/api/auth/logout": {
      "post": {
        "tags": ["Auth"],
        "summary": "End session",
        "description": "Destroy the current session and clear the session cookie.",
        "responses": {
          "302": {
            "description": "Redirect to login page"
          }
        }
      }
    },
    "/api/auth/whoami": {
      "get": {
        "tags": ["Auth"],
        "summary": "Current identity",
        "description": "Return the identity of the authenticated user. Supports session cookie and Bearer token.",
        "responses": {
          "200": {
            "description": "Current user identity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WhoamiResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/account": {
      "delete": {
        "tags": ["Account"],
        "summary": "Delete own account",
        "description": "Soft-delete the authenticated account, starting the 30-day grace window. Requires a confirmation of the account email in the body. Revokes all sessions, API tokens, and MCP tokens. Blocked with 409 when the caller is the sole owner of a project that still has other members.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeleteAccountRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Account scheduled for deletion"
          },
          "400": {
            "description": "Confirmation email does not match",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Sole owner of a shared project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeleteAccountBlocked"
                }
              }
            }
          }
        }
      }
    },
    "/api/account/export": {
      "get": {
        "tags": ["Account"],
        "summary": "Export own account data",
        "description": "Download a portable JSON export of everything the platform holds about the authenticated account: profile, memberships, token and session metadata, MCP sessions with messages, feedback, and invitations. Metadata only; token hashes and secret values are never included. Served as a file attachment.",
        "responses": {
          "200": {
            "description": "Account data export (file attachment)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AccountExportResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions": {
      "get": {
        "tags": ["Auth"],
        "summary": "List sessions",
        "description": "List all active sessions for the authenticated user. The current session is marked with isCurrent: true.",
        "responses": {
          "200": {
            "description": "List of active sessions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSessionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/sessions/{id}": {
      "delete": {
        "tags": ["Auth"],
        "summary": "Revoke session",
        "description": "Revoke a session by ID. Cannot revoke the current session (use logout instead).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "ses_abc123"
            },
            "required": true,
            "name": "id",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Session revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects": {
      "get": {
        "tags": ["Projects"],
        "summary": "List my projects",
        "description": "List all projects where the authenticated user is a member.",
        "parameters": [
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of projects",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListProjectsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Projects"],
        "summary": "Create project",
        "description": "Create a new project. The authenticated user becomes the owner.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateProjectResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}": {
      "get": {
        "tags": ["Projects"],
        "summary": "Get project",
        "description": "Get a single project by ID. Requires membership.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Project details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProjectDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Projects"],
        "summary": "Update project",
        "description": "Update project details. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateProjectResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Projects"],
        "summary": "Delete project",
        "description": "Delete a project and all its resources. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Project deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/members": {
      "get": {
        "tags": ["Projects"],
        "summary": "List members",
        "description": "List all members of a project. Requires membership.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of members",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListMembersResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Projects"],
        "summary": "Add member",
        "description": "Add a member to the project by email. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddMemberRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Member added",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/members/{userId}": {
      "patch": {
        "tags": ["Projects"],
        "summary": "Update member role",
        "description": "Update a member's role. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "user_a1b2c3"
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMemberRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Role updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Member"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Projects"],
        "summary": "Remove member",
        "description": "Remove a member from the project. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "user_a1b2c3"
            },
            "required": true,
            "name": "userId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Member removed"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows": {
      "get": {
        "tags": ["Flows"],
        "summary": "List flows",
        "description": "List all flows for a project.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["name", "updated_at", "created_at"],
              "example": "updated_at"
            },
            "required": false,
            "name": "sort",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["asc", "desc"],
              "example": "desc"
            },
            "required": false,
            "name": "order",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["true", "false"],
              "example": "false"
            },
            "required": false,
            "name": "include_deleted",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of flows",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListFlowsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Flows"],
        "summary": "Create flow",
        "description": "Create a new flow in the project. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateFlowRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Flow created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Flow"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}": {
      "get": {
        "tags": ["Flows"],
        "summary": "Get flow",
        "description": "Get a single flow by ID. Use ?fields to select specific sections (reduces response size).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Comma-separated dot-paths to select specific fields (e.g., \"config.variables,config.flows.tracking.sources\"). Always includes id, createdAt, updatedAt.",
              "example": "config.variables,config.flows.tracking.sources"
            },
            "required": false,
            "description": "Comma-separated dot-paths to select specific fields (e.g., \"config.variables,config.flows.tracking.sources\"). Always includes id, createdAt, updatedAt.",
            "name": "fields",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Flow details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Flows"],
        "summary": "Update flow",
        "description": "Update an existing flow. Creates a version snapshot before applying changes. Requires member role. Use Content-Type: application/merge-patch+json to send only changed fields (RFC 7386).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "ETag from a previous GET. Returns 412 if flow was modified since.",
              "example": "\"a1b2c3d4e5f6g7h8\""
            },
            "required": false,
            "description": "ETag from a previous GET. Returns 412 if flow was modified since.",
            "name": "if-match",
            "in": "header"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFlowRequest"
              }
            },
            "application/merge-patch+json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateFlowRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Flow updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowUpdateResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "412": {
            "description": "ETag mismatch — flow was modified since last read"
          }
        }
      },
      "delete": {
        "tags": ["Flows"],
        "summary": "Soft-delete flow",
        "description": "Soft delete a flow (sets deleted_at timestamp). Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "ETag from a previous GET. Returns 412 if flow was modified since.",
              "example": "\"a1b2c3d4e5f6g7h8\""
            },
            "required": false,
            "description": "ETag from a previous GET. Returns 412 if flow was modified since.",
            "name": "if-match",
            "in": "header"
          }
        ],
        "responses": {
          "204": {
            "description": "Flow deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "412": {
            "description": "ETag mismatch — flow was modified since last read"
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/duplicate": {
      "post": {
        "tags": ["Flows"],
        "summary": "Duplicate flow",
        "description": "Create a copy of an existing flow with a new ID and no version history. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DuplicateFlowRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Flow duplicated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Flow"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/secrets": {
      "get": {
        "tags": ["Secrets"],
        "summary": "List secrets",
        "description": "List a flow's secrets as metadata only (name, id, timestamps). Values are never returned. Requires member role and the secrets entitlement.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Secret metadata list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "secrets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "flowId": {
                            "type": "string"
                          },
                          "createdAt": {
                            "type": ["string", "null"],
                            "format": "date-time"
                          },
                          "updatedAt": {
                            "type": ["string", "null"],
                            "format": "date-time"
                          }
                        },
                        "required": [
                          "id",
                          "name",
                          "flowId",
                          "createdAt",
                          "updatedAt"
                        ]
                      }
                    }
                  },
                  "required": ["secrets"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Secrets"],
        "summary": "Create secret",
        "description": "Create a secret for a flow. The value is encrypted at rest and never returned. Requires member role and the secrets entitlement.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "pattern": "^[A-Z_][A-Z0-9_]*$"
                  },
                  "value": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 65536
                  }
                },
                "required": ["name", "value"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Secret created (metadata only)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "flowId": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": ["string", "null"],
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": ["string", "null"],
                      "format": "date-time"
                    }
                  },
                  "required": ["id", "name", "flowId", "createdAt", "updatedAt"]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/secrets/{secretId}": {
      "put": {
        "tags": ["Secrets"],
        "summary": "Update secret value",
        "description": "Rotate a secret's value (re-encrypts). The value is never returned. Requires member role and the secrets entitlement.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sec_abc123"
            },
            "required": true,
            "name": "secretId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 65536
                  }
                },
                "required": ["value"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Secret updated (metadata only)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "flowId": {
                      "type": "string"
                    },
                    "createdAt": {
                      "type": ["string", "null"],
                      "format": "date-time"
                    },
                    "updatedAt": {
                      "type": ["string", "null"],
                      "format": "date-time"
                    }
                  },
                  "required": ["id", "name", "flowId", "createdAt", "updatedAt"]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Secrets"],
        "summary": "Delete secret",
        "description": "Soft-delete a secret. Idempotent: deleting a missing secret returns 204. Requires member role and the secrets entitlement.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sec_abc123"
            },
            "required": true,
            "name": "secretId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Secret deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/secrets/values": {
      "get": {
        "tags": ["Secrets"],
        "summary": "Get decrypted secret values",
        "description": "Return decrypted secret values for a flow as a name-to-value map. Dual auth: a runtime container Bearer token bound to (projectId, flowId) with the `runner:read-secrets` scope returns only the bundle-referenced subset; a session cookie with member role returns all of the flow's secrets for administration. Responses are never cached.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Decrypted secret values keyed by name",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "values": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "string"
                      }
                    }
                  },
                  "required": ["values"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/steps/{stepPath}/examples": {
      "post": {
        "tags": ["Flows"],
        "summary": "Add step example",
        "description": "Add a named example to a step. Examples are stored as an object map keyed by name. Rejects duplicate names with 409.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Dot-segmented step path (sectionKey.stepName), e.g. \"destinations.gtag\".",
              "example": "destinations.gtag"
            },
            "required": true,
            "description": "Dot-segmented step path (sectionKey.stepName), e.g. \"destinations.gtag\".",
            "name": "stepPath",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateStepExampleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated examples object map",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StepExamplesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable entity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": ["Flows"],
        "summary": "Edit step example",
        "description": "Edit an existing named example in place, merging provided fields onto the stored entry. Returns 404 when the named example does not exist.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Dot-segmented step path (sectionKey.stepName), e.g. \"destinations.gtag\".",
              "example": "destinations.gtag"
            },
            "required": true,
            "description": "Dot-segmented step path (sectionKey.stepName), e.g. \"destinations.gtag\".",
            "name": "stepPath",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EditStepExampleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated examples object map",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StepExamplesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable entity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Flows"],
        "summary": "Remove step example",
        "description": "Remove a named example from a step. Returns 404 when the named example does not exist.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Dot-segmented step path (sectionKey.stepName), e.g. \"destinations.gtag\".",
              "example": "destinations.gtag"
            },
            "required": true,
            "description": "Dot-segmented step path (sectionKey.stepName), e.g. \"destinations.gtag\".",
            "name": "stepPath",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Name of the example to remove.",
              "example": "product view"
            },
            "required": true,
            "description": "Name of the example to remove.",
            "name": "name",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Updated examples object map",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StepExamplesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable entity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/observe-examples": {
      "post": {
        "tags": ["Observe Sessions"],
        "summary": "Save an observed hop as a step example",
        "description": "Persist an observed journey hop as a named example on a step of the DRAFT flow config. Gated by the 'observe' feature. The step path and scenario come from the body; `example.in` is stored verbatim (post-redaction). Rejects a duplicate scenario name with 409.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ObserveSaveExampleRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated examples object map",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StepExamplesResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable entity",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/deploy": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Get latest deployment",
        "description": "Get the latest deployment for a flow.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Latest deployment (or null)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Deployments"],
        "summary": "Start deployment",
        "description": "Start a new deployment for a flow. The bundle runs asynchronously on the worker. Returns 400 AMBIGUOUS_CONFIG when the flow has multiple named settings (use the per-settings deploy endpoint instead). When an Idempotency-Key replays a prior request, returns 200 with status `already_created`.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deployment started, or idempotent replay of a prior request",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartDeploymentResponse"
                }
              }
            }
          },
          "201": {
            "description": "Deployment started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StartDeploymentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Deployment already in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited or concurrent deploy limit (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/deploy/{deploymentId}": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Get deployment",
        "description": "Get a specific deployment by ID.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deployment details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Deployments"],
        "summary": "Delete deployment",
        "description": "Delete a deployment and its container. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deployment deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": ["deleted"]
                    }
                  },
                  "required": ["id", "status"]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings": {
      "get": {
        "tags": ["Settings"],
        "summary": "List settings",
        "description": "List active named settings for a flow.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of settings",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSettingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings/{settingsId}": {
      "get": {
        "tags": ["Settings"],
        "summary": "Get settings",
        "description": "Get a single settings entry with its latest deployment.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Settings details with deployment",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowSettingsDetail"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/json": {
      "get": {
        "tags": ["Settings"],
        "summary": "Download settings JSON",
        "description": "Download the named flow settings as a self-contained Config JSON file. Includes parent variables and definitions.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Flow Config JSON file",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowConfig"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/bundle": {
      "get": {
        "tags": ["Settings"],
        "summary": "Download settings bundle",
        "description": "Download the compiled JS/MJS for the settings' latest deployment. Redirects to a presigned download URL.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "responses": {
          "302": {
            "description": "Redirect to presigned bundle URL"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deploy": {
      "post": {
        "tags": ["Settings"],
        "summary": "Deploy settings",
        "description": "Start a deployment for a specific settings entry. Detects platform from the settings. The body is optional and carries only `humanText`, the reason for the change, which becomes the description of the release this deploy produces; it is ignored when the release already has one.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeploySettingsRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Deployment started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploySettingsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Deployment already in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "422": {
            "description": "Settings orphaned",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": ["Settings"],
        "summary": "Get latest settings deployment",
        "description": "Get the latest deployment for a specific settings entry.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Latest deployment (or null)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsDeploymentResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deployments/{deploymentId}": {
      "get": {
        "tags": ["Settings"],
        "summary": "Get settings deployment detail",
        "description": "Get a specific deployment by ID, scoped to a settings entry.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deployment details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SettingsDeploymentDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/previews": {
      "post": {
        "tags": ["Previews"],
        "summary": "Create preview",
        "description": "Create a new preview for a web flow settings entry. Bundles the flow and publishes to a unique token-based URL.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePreviewRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Preview created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreatePreviewResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Quota exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Bundle or upload failed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": ["Previews"],
        "summary": "List previews",
        "description": "List all previews for a flow, ordered by creation date descending.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of previews",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListPreviewsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/previews/{previewId}": {
      "get": {
        "tags": ["Previews"],
        "summary": "Get preview",
        "description": "Get a single preview by ID.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^prv_[a-z0-9]+$",
              "example": "prv_abc123xyz456"
            },
            "required": true,
            "name": "previewId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Preview details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PreviewResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Previews"],
        "summary": "Delete preview",
        "description": "Delete a preview and its S3 bundle. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^prv_[a-z0-9]+$",
              "example": "prv_abc123xyz456"
            },
            "required": true,
            "name": "previewId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Preview deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/previews/{previewId}/grant": {
      "post": {
        "tags": ["Previews"],
        "summary": "Mint preview activation grant",
        "description": "Mint a fresh, origin-bound activation grant for an existing preview. Grants are origin-bound, so a preview needs one grant per host origin — re-mint whenever the target origin changes.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^prv_[a-z0-9]+$",
              "example": "prv_abc123xyz456"
            },
            "required": true,
            "name": "previewId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MintGrantRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Grant minted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MintGrantResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "No active web deployment / host bundle not preview-enabled",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/observe-sessions": {
      "post": {
        "tags": ["Observe Sessions"],
        "summary": "Start observe session",
        "description": "Start an Observe session for a flow. Validates the flow topology, inserts the row, and kicks off detached provisioning. Returns the row immediately as arming.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateObserveSessionRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Observe session started",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObserveSessionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Flow topology not supported",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}": {
      "get": {
        "tags": ["Observe Sessions"],
        "summary": "Get observe session",
        "description": "Get an observe session: status, error message, config snapshot, web activation info, and the live server endpoint when live.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^ses_[a-zA-Z0-9_-]+$",
              "example": "ses_abc123xyz456"
            },
            "required": true,
            "name": "sessionId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Observe session details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObserveSessionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Observe Sessions"],
        "summary": "End observe session",
        "description": "End an observe session: tear down the container, revoke credentials, delete the web preview, delete the row. Idempotent.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^ses_[a-zA-Z0-9_-]+$",
              "example": "ses_abc123xyz456"
            },
            "required": true,
            "name": "sessionId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Observe session ended"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}/journeys": {
      "get": {
        "tags": ["Observe Sessions"],
        "summary": "Get observe session journeys",
        "description": "Assemble the session's cross-runtime journeys server-side: fetch the raw records from the observer, derive the pipeline topology from the config snapshot, and run the pure assembler. Returns the journeys and per-platform loss gaps wrapped with the session scope.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^ses_[a-zA-Z0-9_-]+$",
              "example": "ses_abc123xyz456"
            },
            "required": true,
            "name": "sessionId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Assembled journeys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObserveSessionJourneysResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Observer unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/journeys": {
      "get": {
        "tags": ["Observe Sessions"],
        "summary": "Get flow journeys",
        "description": "Resolve the flow's single active Observe session and assemble its cross-runtime journeys server-side. `observe_sessions.flow_id` is UNIQUE, so a flow has at most one session; when none is active the response carries `sessionId: null` with empty journeys rather than a 404. Narrow with `traceId` (one trace) and `limit` (page cap, most recent kept). This is the MCP `observe_journeys` REST contract.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1
            },
            "required": false,
            "name": "traceId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Assembled flow journeys",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FlowJourneysResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Observer unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}/heartbeat": {
      "post": {
        "tags": ["Observe Sessions"],
        "summary": "Heartbeat observe session",
        "description": "Keep an observe session warm. The window posts this every 30s while open; a stale session is reaped by the janitor.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^ses_[a-zA-Z0-9_-]+$",
              "example": "ses_abc123xyz456"
            },
            "required": true,
            "name": "sessionId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Heartbeat recorded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObserveSessionHeartbeatResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/observe-sessions/{sessionId}/end": {
      "post": {
        "tags": ["Observe Sessions"],
        "summary": "End observe session (beacon)",
        "description": "The navigator.sendBeacon end target for page unload. Mirrors the DELETE end route because sendBeacon cannot send a DELETE. Idempotent.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^ses_[a-zA-Z0-9_-]+$",
              "example": "ses_abc123xyz456"
            },
            "required": true,
            "name": "sessionId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Observe session ended"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/versions": {
      "get": {
        "tags": ["Versions"],
        "summary": "List versions",
        "description": "List all versions for a flow.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of versions",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListVersionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/versions/{versionNumber}": {
      "get": {
        "tags": ["Versions"],
        "summary": "Get version",
        "description": "Get a specific version of a flow.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "example": 1
            },
            "required": true,
            "name": "versionNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Version details with content",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetVersionResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/versions/{versionNumber}/restore": {
      "post": {
        "tags": ["Versions"],
        "summary": "Restore version",
        "description": "Restore a flow to a specific version. Creates a new version snapshot. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "example": 1
            },
            "required": true,
            "name": "versionNumber",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Flow restored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Flow"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/tokens": {
      "get": {
        "tags": ["Tokens"],
        "summary": "List my automation tokens",
        "description": "The caller's live automation tokens, with the scope and audience each carries. No raw token value is ever returned; `tokenPrefix` is the only fragment of one that survives issuance. A connected app's access token lives in the same store and is deliberately absent: it is taken back by disconnecting the app.",
        "responses": {
          "200": {
            "description": "List of automation tokens",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAutomationTokensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Tokens"],
        "summary": "Create automation token",
        "description": "Mint an automation token for the authenticated user. The audience is `api` and `mcp`, so one token works against REST and against `/api/mcp`, and the chosen scope decides how far it gets at either: `read` is refused every non-safe REST method with 403 `INSUFFICIENT_SCOPE`. The raw token is returned once and cannot be retrieved again, so the answer carries `Cache-Control: no-store`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAutomationTokenRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token created (raw token shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateAutomationTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/tokens/revoke-all": {
      "post": {
        "tags": ["Tokens"],
        "summary": "Revoke all access",
        "description": "Revoke every grant this person holds, the tokens hanging from them, and every automation token they hold. Runner tokens survive: those are the credentials deployed flow containers run with, so revoking them would stop every container the person is running. Session only: a bearer credential is refused with 401 `SESSION_REQUIRED`, so a machine token cannot disconnect everything its owner has connected.",
        "responses": {
          "204": {
            "description": "Access revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/tokens/{tokenId}": {
      "delete": {
        "tags": ["Tokens"],
        "summary": "Revoke automation token",
        "description": "Revoke one of the caller's tokens. Idempotent and scoped to the caller: an unknown id, another person's token and an already revoked one all answer 204, since a distinguishable answer would tell the caller which ids exist.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^tok_[a-zA-Z0-9_-]+$",
              "example": "tok_a1b2c3d4"
            },
            "required": true,
            "name": "tokenId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Token revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/bundle": {
      "post": {
        "tags": ["Bundle"],
        "summary": "Bundle flow",
        "description": "Bundle a flow using CLI. Returns bundleId (content-hash). Use ?output=download to redirect to presigned S3 URL.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "my-web-flow",
              "description": "Named flow to bundle (required for multi-settings flows)"
            },
            "required": false,
            "description": "Named flow to bundle (required for multi-settings flows)",
            "name": "flow",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["download"],
              "description": "Set to \"download\" to redirect to the bundle file"
            },
            "required": false,
            "description": "Set to \"download\" to redirect to the bundle file",
            "name": "output",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Bundle result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BundleResponse"
                }
              }
            }
          },
          "302": {
            "description": "Redirect to presigned bundle URL (when output=download)"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/simulate": {
      "post": {
        "tags": ["Simulate"],
        "summary": "Simulate a flow step",
        "description": "Execute a simulation against a pre-built bundle. Requires bundleId from the bundle endpoint.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SimulateRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Simulation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SimulateResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Simulation container error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List deployments",
        "description": "List deployments for a project. Supports filtering by status, type, origin, and flowId, plus pagination.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "idle",
                "deploying",
                "published",
                "active",
                "stopped",
                "failed"
              ]
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["web", "server"]
            },
            "required": false,
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["cloud", "self-hosted"]
            },
            "required": false,
            "name": "origin",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": false,
            "name": "flowId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["created_at", "updated_at"]
            },
            "required": false,
            "name": "sort",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["asc", "desc"]
            },
            "required": false,
            "name": "order",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": ["integer", "null"],
              "minimum": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of deployments",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListDeploymentsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Deployments"],
        "summary": "Create deployment",
        "description": "Create a new deployment slot. Supports an Idempotency-Key header — a repeated key returns the original deployment id with status `already_created`. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Optional client key to make creation idempotent."
            },
            "required": false,
            "description": "Optional client key to make creation idempotent.",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": ["web", "server"],
                    "example": "web"
                  },
                  "label": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "flowId": {
                    "type": "string"
                  },
                  "flowSettingsId": {
                    "type": "string"
                  }
                },
                "required": ["type"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Deployment created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateDeploymentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/latest": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List latest deployments",
        "description": "List the latest deployment for each flow in the project.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Latest deployment per flow",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LatestDeploymentsByFlow"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/runtimes/register": {
      "post": {
        "tags": ["Deployments"],
        "summary": "Register runtime",
        "description": "Register a server-side runtime container and get a presigned bundle URL.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterRuntimeRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Presigned bundle URL"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/observe/ticket": {
      "post": {
        "tags": ["Observe"],
        "summary": "Create SSE ticket",
        "description": "Generate a one-time ticket for authenticating an SSE connection to the Observer service. Requires project membership. An optional scope narrows the ticket to a subset of the project feed (e.g. one Observe session).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ObserveTicketRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ticket generated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ObserveTicketResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/observe/validate-ticket": {
      "post": {
        "tags": ["Observe"],
        "summary": "Validate ticket",
        "description": "Internal endpoint for the Observer service to validate and consume a ticket.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ValidateTicketRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Ticket payload",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidateTicketResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Invalid or expired ticket",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": ["System"],
        "summary": "Health check",
        "description": "Check the health of the API and its dependencies.",
        "responses": {
          "200": {
            "description": "Health status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/openapi.json": {
      "get": {
        "tags": ["System"],
        "summary": "OpenAPI spec",
        "description": "Return the OpenAPI 3.1 specification for this API.",
        "responses": {
          "200": {
            "description": "OpenAPI document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {},
                  "additionalProperties": {}
                }
              }
            }
          }
        }
      }
    },
    "/ingest/v1/{projectId}": {
      "post": {
        "tags": ["Observer"],
        "summary": "Event ingestion",
        "description": "Ingest walkerOS events for a project. Served by the Observer service (port 3001).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted"
          }
        }
      }
    },
    "/stream/v1": {
      "get": {
        "tags": ["Observer"],
        "summary": "SSE stream",
        "description": "Server-Sent Events stream for real-time event observation. Requires a valid ticket. Served by the Observer service (port 3001).",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "One-time ticket from /api/projects/{projectId}/observe/ticket"
            },
            "required": true,
            "description": "One-time ticket from /api/projects/{projectId}/observe/ticket",
            "name": "ticket",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "description": "Project ID for scoped validation"
            },
            "required": true,
            "description": "Project ID for scoped validation",
            "name": "project",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "SSE event stream"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": ["Observer"],
        "summary": "Observer health",
        "description": "Health check for the Observer service (port 3001).",
        "responses": {
          "200": {
            "description": "Health status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    }
                  },
                  "required": ["status"]
                }
              }
            }
          }
        }
      }
    },
    "/api/feedback": {
      "post": {
        "tags": ["Feedback"],
        "summary": "Submit user feedback",
        "description": "Accepts free-form feedback from the walkerOS CLI, MCP, or a future in-app form. Public endpoint — no authentication required. The body `userId` is stored verbatim as a best-effort contact email and is not validated against the app users table.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedbackRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Feedback stored",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedbackResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/service-accounts": {
      "get": {
        "tags": ["Service Accounts"],
        "summary": "List service accounts",
        "description": "List service accounts for a project. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of service accounts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListServiceAccountsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Service Accounts"],
        "summary": "Create service account",
        "description": "Create a service account and its first token. The raw token is returned once and cannot be retrieved again. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateServiceAccountRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Service account created (raw token shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateServiceAccountResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/service-accounts/{serviceAccountId}": {
      "get": {
        "tags": ["Service Accounts"],
        "summary": "Get service account",
        "description": "Get a single service account by ID. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sa_abc123"
            },
            "required": true,
            "name": "serviceAccountId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Service account details",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAccountSummary"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Service Accounts"],
        "summary": "Update service account",
        "description": "Update a service account's name, description, or role. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sa_abc123"
            },
            "required": true,
            "name": "serviceAccountId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateServiceAccountRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Service account updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ServiceAccountSummary"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Service Accounts"],
        "summary": "Delete service account",
        "description": "Soft-delete a service account and revoke all its tokens. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sa_abc123"
            },
            "required": true,
            "name": "serviceAccountId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Service account deleted"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/service-accounts/{serviceAccountId}/tokens": {
      "get": {
        "tags": ["Service Accounts"],
        "summary": "List service account tokens",
        "description": "List tokens for a service account. Returns summaries (no raw token values). Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sa_abc123"
            },
            "required": true,
            "name": "serviceAccountId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "List of tokens",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListSaTokensResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Service Accounts"],
        "summary": "Create service account token",
        "description": "Create a new token for a service account. The raw token is returned once and cannot be retrieved again. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sa_abc123"
            },
            "required": true,
            "name": "serviceAccountId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSaTokenRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Token created (raw token shown once)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateSaTokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/service-accounts/{serviceAccountId}/tokens/{tokenId}": {
      "delete": {
        "tags": ["Service Accounts"],
        "summary": "Revoke service account token",
        "description": "Revoke a service account token. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sa_abc123"
            },
            "required": true,
            "name": "serviceAccountId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "tok_abc123"
            },
            "required": true,
            "name": "tokenId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Token revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/invitations": {
      "get": {
        "tags": ["Invitations"],
        "summary": "List invitations",
        "description": "List invitations for a project. Defaults to pending; pass ?status=all for every status. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "accepted",
                "declined",
                "expired",
                "cancelled",
                "all"
              ],
              "example": "pending"
            },
            "required": false,
            "name": "status",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "List of invitations",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListInvitationsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Invitations"],
        "summary": "Create invitation",
        "description": "Create an invitation and send the invite email. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateInvitationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invitation created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateInvitationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Invitation limit reached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/invitations/{inviteId}": {
      "delete": {
        "tags": ["Invitations"],
        "summary": "Cancel invitation",
        "description": "Cancel a pending invitation. Requires admin role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "inv_abc123"
            },
            "required": true,
            "name": "inviteId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Invitation cancelled"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/{token}": {
      "get": {
        "tags": ["Invitations"],
        "summary": "Preview invitation",
        "description": "Preview invitation details. No authentication required — the token is the credential.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Opaque invitation token (the credential).",
              "example": "a1b2c3d4e5f6"
            },
            "required": true,
            "description": "Opaque invitation token (the credential).",
            "name": "token",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation preview",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvitationPreview"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/{token}/accept": {
      "post": {
        "tags": ["Invitations"],
        "summary": "Accept invitation",
        "description": "Accept an invitation. Requires authentication; the authenticated user's email must match the invitation email.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Opaque invitation token (the credential).",
              "example": "a1b2c3d4e5f6"
            },
            "required": true,
            "description": "Opaque invitation token (the credential).",
            "name": "token",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AcceptInvitationResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/invitations/{token}/decline": {
      "post": {
        "tags": ["Invitations"],
        "summary": "Decline invitation",
        "description": "Decline an invitation. No authentication required — the token is the credential.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Opaque invitation token (the credential).",
              "example": "a1b2c3d4e5f6"
            },
            "required": true,
            "description": "Opaque invitation token (the credential).",
            "name": "token",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Invitation declined",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeclineInvitationResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/telemetry": {
      "post": {
        "tags": ["Telemetry"],
        "summary": "Submit telemetry event",
        "description": "Accept a single walkerOS v4 event from the CLI or MCP telemetry emitter. Public endpoint — no authentication. `source.type` is constrained to `cli` or `mcp`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TelemetryEvent"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Telemetry event accepted"
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/billing": {
      "get": {
        "tags": ["Billing"],
        "summary": "Get billing details",
        "description": "Get billing details for a project, or null when none are set. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Billing details (or null when unset)",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/BillingDetailsResponse"
                    },
                    {
                      "type": "null"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": ["Billing"],
        "summary": "Upsert billing details",
        "description": "Create or update billing details for a project. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpsertBillingDetailsRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Billing details saved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingDetailsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Get deployment detail",
        "description": "Get deployment detail. Accepts a dep_ID or a slug. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deployment detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "patch": {
        "tags": ["Deployments"],
        "summary": "Update deployment",
        "description": "Update a deployment's label, or stop/resume it. Stop and resume require admin role; label updates require member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "label": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "action": {
                    "type": "string",
                    "enum": ["stop", "resume"]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Deployment updated",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateDeploymentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Deployment state changed concurrently",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Deployments"],
        "summary": "Delete deployment",
        "description": "Tear down and soft-delete a deployment. Idempotent. Requires owner role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Deployment deleted (or already absent)"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/publish": {
      "post": {
        "tags": ["Deployments"],
        "summary": "Publish deployment version",
        "description": "Push a new version to a deployment, either from an existing flow setting or from a direct config upload. Bundles in-process and transitions the deployment to `deploying`. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "Optional client key to make publishing idempotent."
            },
            "required": false,
            "description": "Optional client key to make publishing idempotent.",
            "name": "idempotency-key",
            "in": "header"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "object",
                    "properties": {
                      "source": {
                        "type": "string",
                        "enum": ["flow"]
                      },
                      "flowId": {
                        "type": "string",
                        "pattern": "^flow_[a-zA-Z0-9_-]+$"
                      },
                      "flowSettingsName": {
                        "type": "string",
                        "minLength": 1,
                        "maxLength": 100
                      }
                    },
                    "required": ["source", "flowId", "flowSettingsName"]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "source": {
                        "type": "string",
                        "enum": ["config"]
                      },
                      "config": {
                        "type": "object",
                        "additionalProperties": {}
                      }
                    },
                    "required": ["source", "config"]
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Version published (bundling/deploying)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublishVersionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Publish already in progress",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited or concurrent deploy limit",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "Build service unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/stream": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Stream deployment status (SSE)",
        "description": "Server-Sent Events (`text/event-stream`) stream of a deployment's live status. Emits named events: `status` (a snapshot payload, schema below), `done` (terminal, no body), and `timeout`. The CLI consumes this with a raw fetch while waiting for a deploy to finish. Requires member role. The schema documents the JSON `data:` of a `status` event; `errorCode`/`errorMessage` carry the persisted, redacted classification of a failed deploy.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "SSE stream; `status` event payload shape documented here.",
            "content": {
              "text/event-stream": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentStreamStatusEvent"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/versions": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List deployment versions",
        "description": "List the version history for a deployment, paginated. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": ["integer", "null"],
              "minimum": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Version history",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListDeploymentVersionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/releases": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List flow releases",
        "description": "List the release history for a flow across all of its deployment lineages, newest first, paginated. Each entry is a deployed version joined to its parent deployment (slug and type). `rationale=true` joins each row's stored rationale summary on, which requires the `hub` feature; without it the `rationale` key is absent from every row rather than null, and no feature beyond member role is needed. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": ["integer", "null"],
              "minimum": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["true", "false"]
            },
            "required": false,
            "name": "rationale",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Flow release history",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListFlowReleasesResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/releases/{versionId}": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Read one release in full",
        "description": "One release of this flow with its rationale and its diff. The path segment is either the spine version id (`ver_...`) or the flow-unique spine number, and the route decides which it was, so a caller holding only the number needs no lookup first. The diff is computed server-side from the two stored snapshots and is never accepted from a caller; its predecessor is the next LOWER spine number, not the previous row by time, because spine rows are reused across redeploys of identical content. `diff.text` is rendered from masked content, so an empty string can still mean the releases differ inside an inline secret: `diff.contentIdentical`, compared over the unmasked hashes, is the trustworthy answer. `diff` is null for the flow's oldest release. An unknown address, a sibling flow's version, and an autosave revision all answer 404 alike. Requires member role and the `hub` feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^(ver_[a-zA-Z0-9_-]+|[1-9][0-9]*)$",
              "example": "ver_a1b2c3d4",
              "description": "Spine version id of the release (ver_...) or its spine number"
            },
            "required": true,
            "description": "Spine version id of the release (ver_...) or its spine number",
            "name": "versionId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The release, its rationale, and its diff",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseDetailResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid release reference",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/releases/{versionId}/content": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Read a release snapshot",
        "description": "The flow config one release of this flow froze, addressed by its spine version id. This is the only route that serves a release snapshot: the positional `/versions/{versionNumber}` route numbers the autosave revisions, a disjoint set of rows, so a release number handed to it addresses an unrelated revision or nothing. Inline secret literals are masked. An unknown id, a sibling flow's version, and an autosave revision all answer 404 alike. Requires member role and the `hub` feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^ver_[a-zA-Z0-9_-]+$",
              "example": "ver_a1b2c3d4",
              "description": "Spine version ID of the release (ver_...)"
            },
            "required": true,
            "description": "Spine version ID of the release (ver_...)",
            "name": "versionId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The release snapshot",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReleaseContentResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid version id",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/releases/annotations": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List release rationale",
        "description": "Read the rationale attached to the given releases of a flow. `versionIds` is a comma-separated list of spine version ids (at most 100), all of which must belong to this flow. Releases without rationale are absent from the response. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "ver_a1b2c3d4,ver_e5f6g7h8"
            },
            "required": true,
            "name": "versionIds",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Rationale for the requested releases",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListVersionAnnotationsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid version ids",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": ["Deployments"],
        "summary": "Write release rationale",
        "description": "Create or update the human rationale for one release of this flow. A null `humanText` clears it. The generated summary is machine-written and cannot be set through this route. The target must be a numbered release version of this flow, not an autosave revision. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "versionId": {
                    "type": "string",
                    "pattern": "^ver_[a-zA-Z0-9_-]+$",
                    "example": "ver_a1b2c3d4"
                  },
                  "humanText": {
                    "type": ["string", "null"],
                    "maxLength": 4000
                  }
                },
                "required": ["versionId", "humanText"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored rationale",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpsertVersionAnnotationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or the target is not a release",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/threads": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List discussion threads on a flow",
        "description": "Threads anchored to things in this flow, most recently active first. `anchorType` and `anchorKey` narrow to one anchor and are only meaningful together. `includeMessages=true` attaches the messages; otherwise each thread carries `messageCount` alone. Attaching them holds the page to a smaller ceiling than the lean index and caps each thread at its newest 50 messages, with `hasMoreMessages` set when a thread holds more. Because that ceiling is below the `limit` a caller may pass, the response carries `hasMoreThreads`: a full page is not proof of a complete list. A resolved thread carries the release that settled it, and `resolvedByVersionId` is null once that release is gone, which is what `anchorLabel` is kept for. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["step", "entity_action", "release", "contract", "tag"],
              "example": "release"
            },
            "required": false,
            "name": "anchorType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "example": "ver_a1b2c3d4"
            },
            "required": false,
            "name": "anchorKey",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["open", "resolved"],
              "example": "open"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["true", "false"]
            },
            "required": false,
            "name": "includeMessages",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "example": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Threads on this flow",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListHubThreadsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Deployments"],
        "summary": "Open a discussion thread",
        "description": "Open a thread on one anchor, with its first message. A thread never exists empty, so `text` is required and may not be blank. A `release` anchor must name a numbered release of this flow: the server verifies it and derives the label, so `anchorLabel` is ignored for that type. For any other anchor type `anchorLabel` is a display snapshot of the anchor as it reads now, stored so a later rename leaves the thread readable instead of unlabeled, and defaults to the anchor key. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "anchorType": {
                    "type": "string",
                    "enum": [
                      "step",
                      "entity_action",
                      "release",
                      "contract",
                      "tag"
                    ],
                    "example": "release"
                  },
                  "anchorKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "anchorLabel": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "required": ["anchorType", "anchorKey", "text"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The opened thread, with its first message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HubThreadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or the anchor is not a release",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Flow not found, or the anchor names no release of it",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/threads/{threadId}/messages": {
      "post": {
        "tags": ["Deployments"],
        "summary": "Reply to a thread",
        "description": "Append a message to a thread. `text` may not be blank: a message cannot be cleared, so empty is invalid rather than a way to erase one. Replying does not reopen a resolved thread: the resolve link is a statement about a release and is never retracted implicitly. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^thr_[a-z0-9]+$",
              "example": "thr_a1b2c3d4",
              "description": "Thread ID (thr_...)"
            },
            "required": true,
            "description": "Thread ID (thr_...)",
            "name": "threadId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "required": ["text"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The thread, with the new message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HubThreadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/threads/{threadId}": {
      "patch": {
        "tags": ["Deployments"],
        "summary": "Resolve or reopen a thread",
        "description": "Resolving records the release that settled the thread: pass `resolvedByVersionId`, or omit it to record the flow’s newest release. The target must be a numbered release of this flow, never an autosave revision. Reopening drops the link. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^thr_[a-z0-9]+$",
              "example": "thr_a1b2c3d4",
              "description": "Thread ID (thr_...)"
            },
            "required": true,
            "description": "Thread ID (thr_...)",
            "name": "threadId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": ["open", "resolved"],
                    "example": "open"
                  },
                  "resolvedByVersionId": {
                    "type": "string",
                    "pattern": "^ver_[a-zA-Z0-9_-]+$",
                    "example": "ver_a1b2c3d4"
                  }
                },
                "required": ["status"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated thread",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HubThreadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or the target is not a release",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/knowledge": {
      "get": {
        "tags": ["Projects"],
        "summary": "List knowledge captured in this project",
        "description": "What people wrote on the frames of a page, most recently active first. Two kinds come back together and `kind` separates them: a `thread` carries its text in messages, a `description` carries one body and cannot be replied to. `pageKey` narrows to a whole page, resolved server-side to every frame that page holds at any depth; `frameId` narrows to one frame; `markId` narrows to one mark within it and is refused without `frameId`, since a mark id alone addresses nothing. `includeMessages=true` attaches message bodies and holds the page to a much smaller ceiling, so `hasMoreEntries` is what separates a complete answer from a truncated one. `validity` says when an entry was true and `freshness` compares that against the flow’s newest release; neither is a verdict. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "https://shop.example/checkout"
            },
            "required": false,
            "name": "pageKey",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^frm_[A-Za-z0-9_-]{21}$",
              "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
            },
            "required": false,
            "name": "frameId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "example": "mark_add_to_cart"
            },
            "required": false,
            "name": "markId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["true", "false"]
            },
            "required": false,
            "name": "includeMessages",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "example": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Knowledge in this project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListKnowledgeResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid query, or a mark filter with no frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Projects"],
        "summary": "Open a thread on a mark or a frame",
        "description": "Open a thread on one mark of one frame, or on the frame itself with `anchorType` `page` and no `markId`, with its first message. A thread never exists empty, so `text` is required and may not be blank. `clientThreadId` and `clientMessageId` are minted by the client at compose time and are what make a replay idempotent: repeating a known `clientThreadId` hands back the existing thread and writes nothing, so an offline queue can drain repeatedly without duplicating what a person wrote once. `flowId` binds the capture to a flow or is explicitly null; a flow this project cannot see answers 404, never 403. A frame this project does not hold answers 404 with `FRAME_NOT_FOUND`, which a draining client waits on and retries, because the frame’s own write may not have landed yet. The server decides the composed anchor key, the born release, the author and the source: a client cannot assert any of them. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "anchorType": {
                    "type": "string",
                    "enum": ["tag", "page"],
                    "example": "tag"
                  },
                  "frameId": {
                    "type": "string",
                    "pattern": "^frm_[A-Za-z0-9_-]{21}$",
                    "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
                  },
                  "markId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "anchorLabel": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "flowId": {
                    "type": ["string", "null"],
                    "minLength": 1
                  },
                  "subjectKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "spatial": {
                    "$ref": "#/components/schemas/KnowledgeSpatial"
                  },
                  "clientThreadId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "example": "ct_7f3a91"
                  },
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "clientMessageId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "example": "ct_7f3a91"
                  }
                },
                "required": [
                  "anchorType",
                  "frameId",
                  "flowId",
                  "clientThreadId",
                  "text",
                  "clientMessageId"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The thread, with its first message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeThreadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The named flow or frame is not in this project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/knowledge/{threadId}/messages": {
      "post": {
        "tags": ["Projects"],
        "summary": "Reply to a knowledge thread",
        "description": "Append a message to a thread and get the whole thread back, so a surface renders the new exchange without a second read. `text` may not be blank: a message cannot be cleared, so empty is invalid rather than a way to erase one. Repeating a `clientMessageId` already on the thread appends nothing and leaves `updatedAt` alone, so a retrying drain never keeps bumping a thread to the top of every list. A description has no conversation and cannot be replied to; addressing one answers 404. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^thr_[a-z0-9]+$",
              "example": "thr_a1b2c3d4",
              "description": "Thread ID (thr_...)"
            },
            "required": true,
            "description": "Thread ID (thr_...)",
            "name": "threadId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  },
                  "clientMessageId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 64,
                    "example": "ct_7f3a91"
                  }
                },
                "required": ["text", "clientMessageId"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The thread, with the new message",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeThreadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/knowledge/description": {
      "put": {
        "tags": ["Projects"],
        "summary": "Write the description of a mark or a frame",
        "description": "Write the one description of one anchor, a mark or the frame itself, replacing whatever it said before. There is no id to mint: the anchor is the key, so a replayed write lands on the same row by construction, which is why this is a PUT. An empty `body` is refused rather than stored, so a drain that arrives with nothing to say can never erase what a person wrote. The response is 200 whether the description was opened or replaced. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "anchorType": {
                    "type": "string",
                    "enum": ["tag", "page"],
                    "example": "tag"
                  },
                  "frameId": {
                    "type": "string",
                    "pattern": "^frm_[A-Za-z0-9_-]{21}$",
                    "example": "frm_V1StGXR8Z5jdHi6BmyT7K"
                  },
                  "markId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 200
                  },
                  "anchorLabel": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "flowId": {
                    "type": ["string", "null"],
                    "minLength": 1
                  },
                  "subjectKey": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  },
                  "spatial": {
                    "$ref": "#/components/schemas/KnowledgeSpatial"
                  },
                  "body": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "required": ["anchorType", "frameId", "flowId", "body"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored description",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KnowledgeDescriptionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "The named flow or frame is not in this project",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/frames": {
      "get": {
        "tags": ["Projects"],
        "summary": "List the frames of a page, or of the whole project",
        "description": "A frame is a named rectangle with marks inside it, the spatial unit of a measurement plan. Naming a `pageKey` returns that page’s frames at any depth, marks and all, newest updated first: the walk starts at the page’s top-level frames and descends containment, so a child is reachable through its parent rather than by carrying a page of its own. Naming no page returns every live frame of the project WITHOUT its marks, which is what makes that read cheap enough to answer \"what does this project have\": the marks are the bulk of a frame and a listing never renders them. That lean read asks nothing about containment, so a frame whose parent cannot be resolved still appears. `include=marks` asks that project-wide read for the marks anyway, for a surface that spans pages and cannot fetch a page at a time; it is a second, heavier read of the same rows, taken after the lean list has already painted, and omitting it returns exactly the lean rows. It says nothing to the page read, which carries marks either way. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 1024
            },
            "required": false,
            "name": "pageKey",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["marks"]
            },
            "required": false,
            "name": "include",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The page’s frames with their marks, or the project’s frames without them",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/FrameListResponse"
                    },
                    {
                      "$ref": "#/components/schemas/FrameLeanListResponse"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/frames/{frameId}": {
      "get": {
        "tags": ["Projects"],
        "summary": "Read one frame",
        "description": "One frame with its marks. A frame of another project reads back as nothing and answers 404, never 403, so this route cannot become an oracle for what exists elsewhere. A deleted frame is gone to every read. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^frm_[A-Za-z0-9_-]{21}$",
              "description": "Frame ID (frm_...)"
            },
            "required": true,
            "description": "Frame ID (frm_...)",
            "name": "frameId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Frame"
                }
              }
            }
          },
          "400": {
            "description": "The path segment does not address a frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": ["Projects"],
        "summary": "Create or replace one frame",
        "description": "The path is the identity, so the body carries no id: a create is a write to an absent row at `baseVersion` 0 and everything else is a replace. `clientWriteId` is minted at compose time and is what makes a replayed drain exact: a write whose id already produced the stored version landed once and is answered with that version, writing nothing, so an offline queue drains repeatedly without turning one edit into two versions. A write against a version someone else has moved past answers 409 `FRAME_VERSION_CONFLICT` carrying the head, which is what lets a client raise keep-mine against load-theirs on the one frame that conflicted instead of dropping what a person drew. A name another live frame already holds is a distinct 409 `FRAME_NAME_EXISTS`. A relation naming a frame this project does not hold, or one that would place a frame inside itself, is 400 `INVALID_FRAME`. The screenshot is never touched here: a frame write carries no capture. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^frm_[A-Za-z0-9_-]{21}$",
              "description": "Frame ID (frm_...)"
            },
            "required": true,
            "description": "Frame ID (frm_...)",
            "name": "frameId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "frame": {
                    "$ref": "#/components/schemas/FrameInput"
                  },
                  "baseVersion": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "clientWriteId": {
                    "type": "string",
                    "pattern": "^cw_[A-Za-z0-9_-]{21}$"
                  }
                },
                "required": ["frame", "baseVersion", "clientWriteId"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PutFrameResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, a bad relation, or a path segment that addresses no frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A stale base version, carrying the head, or a name another live frame already holds. Only the version conflict carries `head`: a name clash needs no frame to resolve, since the client already knows the name it sent.",
            "content": {
              "application/json": {
                "schema": {
                  "anyOf": [
                    {
                      "$ref": "#/components/schemas/FrameConflictResponse"
                    },
                    {
                      "$ref": "#/components/schemas/ErrorResponse"
                    }
                  ]
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["Projects"],
        "summary": "Delete one frame",
        "description": "Soft-delete the frame and, transitively, every variation of what this delete removes. Children are not variations and survive: each live frame under a removed one is re-parented to its nearest live ancestor in the same transaction, and one left with no live ancestor becomes top-level and inherits the page it hung under, so nothing is left unreachable. Those re-parents are server writes that bump their own versions, so a client still holding a pre-delete version meets a conflict carrying the new parent. A frame this project does not hold answers 404: a delete that removed nothing is not a delete that succeeded. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^frm_[A-Za-z0-9_-]{21}$",
              "description": "Frame ID (frm_...)"
            },
            "required": true,
            "description": "Frame ID (frm_...)",
            "name": "frameId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "The frame is deleted"
          },
          "400": {
            "description": "The path segment does not address a frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/frames/{frameId}/screenshot": {
      "post": {
        "tags": ["Projects"],
        "summary": "Store the capture of one frame",
        "description": "Store one screenshot and set it on its frame. The image arrives as base64 rather than multipart, because the extension relay carries string bodies only. The server decides everything about the bytes: it decodes them, counts the DECODED length against a 4 MB cap, reads the type from the file’s own magic bytes, and hashes them, so nothing the client claims about size or type is consulted. Captures are deduplicated by content within a project: identical pixels resolve to one asset and one upload, and `reused` says whether that happened, which is the common answer rather than the rare one because re-capturing an unchanged frame produces identical bytes. A body past the cap is 413 `PAYLOAD_TOO_LARGE` and one that is not a PNG is 415 `UNSUPPORTED_MEDIA_TYPE`. The capture bumps no frame version: it is not an edit, so an upload never conflicts with the frame write the client queued beside it. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^frm_[A-Za-z0-9_-]{21}$",
              "description": "Frame ID (frm_...)"
            },
            "required": true,
            "description": "Frame ID (frm_...)",
            "name": "frameId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "imageBase64": {
                    "type": "string",
                    "minLength": 1
                  },
                  "meta": {
                    "$ref": "#/components/schemas/FrameScreenshotMeta"
                  }
                },
                "required": ["imageBase64", "meta"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The asset the bytes resolved to, and whether it already existed",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ScreenshotUploadResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or a path segment that addresses no frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "This project does not hold the named frame",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "413": {
            "description": "The decoded image is past the 4 MB cap",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "415": {
            "description": "The bytes are not a PNG",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/assets/{assetId}": {
      "get": {
        "tags": ["Projects"],
        "summary": "Read one stored capture",
        "description": "The bytes of one frame screenshot, for the app canvas. The extension keeps its own capture locally and never reads assets back. Same-origin and session-authenticated: the response carries `Cross-Origin-Resource-Policy: same-origin`, so no other site can embed a tenant capture off the reader’s session. The bytes are immutable by construction, since the object key is their own content hash, which is why they are cacheable for a year, and `private` keeps a shared cache from serving one tenant’s capture to the next request for the same URL. An asset another project holds answers 404, never 403. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^fas_[A-Za-z0-9_-]{21}$",
              "description": "Asset ID (fas_...)"
            },
            "required": true,
            "description": "Asset ID (fas_...)",
            "name": "assetId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The image bytes",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "400": {
            "description": "The path segment does not address an asset",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/canvases": {
      "get": {
        "tags": ["Projects"],
        "summary": "List the canvases of the project",
        "description": "A canvas is a named, freely arranged board over a project’s frames, the surface on which a plan is laid out across pages rather than within one. This returns every live canvas by name WITHOUT its document: the document is the bulk of a canvas and a listing renders none of it, so opening a board is the single-canvas read. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The project’s canvases, without their documents",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CanvasListResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Projects"],
        "summary": "Create one canvas",
        "description": "Create one empty canvas at version 1. The id is the client’s, so a board drawn before the first save keeps its identity when it arrives. A canvas comes into existence here and nowhere else: a document write to an id the project does not hold is a 404 rather than a create, which is what keeps a stray write from minting a board. A name another live canvas already holds is 409 `CANVAS_NAME_EXISTS`; the partial unique index is over live rows, so a name a deleted canvas still carries is free. An id that is not a canvas id is refused by the body schema as 400 `VALIDATION_ERROR`. An id that is not available, because a canvas, in this project or another, already holds it, is 400 `INVALID_CANVAS`, whose message says nothing about the project that holds it. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string",
                    "pattern": "^cnv_[A-Za-z0-9_-]{21}$",
                    "example": "cnv_V1StGXR8Z5jdHi6BmyT7K"
                  },
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  }
                },
                "required": ["id", "name"]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created canvas, with its empty document",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Canvas"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or an id that is not available",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A name another live canvas already holds",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/canvases/{canvasId}": {
      "get": {
        "tags": ["Projects"],
        "summary": "Read one canvas",
        "description": "One canvas with its whole document: the nodes with their positions, the edges, and the node keys the board suppresses. A canvas of another project reads back as nothing and answers 404, never 403, so this route cannot become an oracle for what exists elsewhere. A deleted canvas is gone to every read. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cnv_[A-Za-z0-9_-]{21}$",
              "example": "cnv_V1StGXR8Z5jdHi6BmyT7K",
              "description": "Canvas ID (cnv_...)"
            },
            "required": true,
            "description": "Canvas ID (cnv_...)",
            "name": "canvasId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "The canvas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Canvas"
                }
              }
            }
          },
          "400": {
            "description": "The path segment does not address a canvas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "tags": ["Projects"],
        "summary": "Replace the document of one canvas",
        "description": "The whole board every time: a canvas is read and written as a unit, so there is no partial write to reconcile. `clientWriteId` is minted at compose time and is what makes a replayed drain exact: a write whose id already produced the stored version landed once and is answered with that version, writing nothing, so an offline queue drains repeatedly without turning one edit into two versions. A write against a version someone else has moved past answers 409 `CANVAS_VERSION_CONFLICT` carrying the head, which is what lets a client raise keep-mine against load-theirs on the board that conflicted instead of dropping what a person drew. A canvas this project does not hold, or one that was removed, is 404 `CANVAS_NOT_FOUND`: this door replaces a document and never creates one. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cnv_[A-Za-z0-9_-]{21}$",
              "example": "cnv_V1StGXR8Z5jdHi6BmyT7K",
              "description": "Canvas ID (cnv_...)"
            },
            "required": true,
            "description": "Canvas ID (cnv_...)",
            "name": "canvasId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "document": {
                    "$ref": "#/components/schemas/CanvasDocument"
                  },
                  "baseVersion": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "clientWriteId": {
                    "type": "string",
                    "pattern": "^cw_[A-Za-z0-9_-]{21}$"
                  }
                },
                "required": ["document", "baseVersion", "clientWriteId"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The stored version",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PutCanvasResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, or a path segment that addresses no canvas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "This project does not hold the named canvas",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "A stale base version, carrying the head",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CanvasConflictResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/releases/step-history": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List the releases that touched one step",
        "description": "The releases of this flow that added, changed, or removed one step, newest first, each carrying the rationale stored for it. `step` is a `type.name` key over source, transformer, destination, store, and contract. `flow` narrows the scan to one named flow inside the config and is ignored for a contract key. `limit` bounds the releases scanned, not the entries returned. When nothing matched, `knownSteps` lists the addressable keys of the newest scanned release. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "destination.ga4"
            },
            "required": true,
            "name": "step",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "example": "web"
            },
            "required": false,
            "name": "flow",
            "in": "query"
          },
          {
            "schema": {
              "type": ["integer", "null"],
              "example": 25
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The releases that touched the step",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StepHistoryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid step key or query",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/releases/summarize": {
      "post": {
        "tags": ["Deployments"],
        "summary": "Summarize or check a release",
        "description": "Describe what one release of this flow changed against an earlier release, or check a written note against that same change. In `draft` mode the generated text is stored as the release's generated summary; in `check` mode nothing is stored and the response says whether the note matches. The diff is always recomputed from the two stored snapshots, with secret literals masked, and is never taken from the request. Both versions must be numbered releases of this flow, and `prevVersionId` must be the earlier of the two. Requires member role and the `hub` feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "versionId": {
                    "type": "string",
                    "pattern": "^ver_[a-zA-Z0-9_-]+$",
                    "example": "ver_a1b2c3d4"
                  },
                  "prevVersionId": {
                    "type": "string",
                    "pattern": "^ver_[a-zA-Z0-9_-]+$",
                    "example": "ver_a1b2c3d4"
                  },
                  "mode": {
                    "type": "string",
                    "enum": ["draft", "check"]
                  },
                  "currentText": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 4000
                  }
                },
                "required": ["versionId", "prevVersionId", "mode"]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The generated summary or the check verdict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SummarizeReleaseResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body, a target is not a release, the pair is out of order, or no LLM provider is configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "The model call failed or returned no usable text",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/versions/current/content": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Get current deployed content",
        "description": "Get the active deployed per-setting content for a deployment, used to diff changes since deploy. Content is masked and display-only; every field is null when there is no deployed baseline. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deployed content (or a null baseline)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeployedContentResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/heartbeats": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List deployment heartbeats",
        "description": "List heartbeat records for a deployment with optional from/to time-range filtering and pagination. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "description": "ISO start of the time range."
            },
            "required": false,
            "description": "ISO start of the time range.",
            "name": "from",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "ISO end of the time range."
            },
            "required": false,
            "description": "ISO end of the time range.",
            "name": "to",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": ["integer", "null"],
              "minimum": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Heartbeat history",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListHeartbeatsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/rotate-ingest-token": {
      "post": {
        "tags": ["Deployments"],
        "summary": "Rotate ingest token",
        "description": "Rotate the ingest token for a deployment. Owner-only. No grace window: the previous token is immediately invalidated and the new token is returned once.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "New ingest token",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RotateIngestTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/deployments/{deploymentId}/usage": {
      "get": {
        "tags": ["Deployments"],
        "summary": "Deployment usage",
        "description": "Aggregate usage summary plus bucketed chart data for a deployment over the requested period. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dep_abc123"
            },
            "required": true,
            "name": "deploymentId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "enum": ["1h", "24h", "7d", "30d"],
              "description": "Time window for the usage summary."
            },
            "required": false,
            "description": "Time window for the usage summary.",
            "name": "period",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Usage summary and chart buckets",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeploymentUsageResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/custom-domains": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List custom domains",
        "description": "List custom domains attached to any deployment of this flow. Requires member role and the customDomains feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Custom domains for the flow",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListCustomDomainsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Deployments"],
        "summary": "Attach custom domain",
        "description": "Attach a custom domain to the flow's latest server deployment, or to an explicit deployment supplied in the body. Requires member role and the customDomains feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCustomDomainRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Custom domain attached",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomDomain"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/custom-domains/{domainId}": {
      "delete": {
        "tags": ["Deployments"],
        "summary": "Detach custom domain",
        "description": "Detach a custom domain from its deployment and remove the Scaleway record. Idempotent: a missing domain still returns 204.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "dom_abc123"
            },
            "required": true,
            "name": "domainId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Custom domain detached"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/flows/{flowId}/settings/{settingsId}/deploy-token": {
      "get": {
        "tags": ["Settings"],
        "summary": "Self-hosted deploy-token status",
        "description": "Report whether a self-hosted deploy token exists for this config, plus the deployment health summary when present. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Deploy-token status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeployTokenStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Settings"],
        "summary": "Mint self-hosted deploy token",
        "description": "Create a self-hosted deployment (if none exists) and mint a flow+deployment-bound runner token. Admin-only. The raw token is returned once and never stored in plaintext.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^flow_[a-zA-Z0-9_-]+$",
              "example": "flow_a1b2c3d4"
            },
            "required": true,
            "name": "flowId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^cfg_[a-zA-Z0-9_-]+$",
              "example": "cfg_a1b2c3d4"
            },
            "required": true,
            "name": "settingsId",
            "in": "path"
          }
        ],
        "responses": {
          "201": {
            "description": "Deploy token minted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateDeployTokenResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/entitlements": {
      "get": {
        "tags": ["Projects"],
        "summary": "Resolved entitlements",
        "description": "Return resolved feature entitlements for the authenticated user and project. Used by CLI/API clients; the web UI uses SSR-resolved entitlements. Requires viewer role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Resolved entitlements",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EntitlementsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/settings/llm": {
      "get": {
        "tags": ["Settings"],
        "summary": "Active LLM provider",
        "description": "Report which LLM provider is currently active for the project and where billing is sourced. Never returns the apiKey. Requires member role and the chat feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Active LLM provider status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LlmConfigStatusResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "503": {
            "description": "No platform LLM provider configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LlmConfigStatusResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["Settings"],
        "summary": "Set LLM provider",
        "description": "Set or clear the project LLM provider override. Admin-only, gated by the chat feature. The apiKey is write-only: it is encrypted and never returned.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SetLlmConfigRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "LLM config saved or cleared",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetLlmConfigResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/chat/sessions": {
      "get": {
        "tags": ["Chat"],
        "summary": "List chat sessions",
        "description": "List the caller's recent chat sessions for a project, ordered by last activity. Requires member role and the chat feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": ["integer", "null"],
              "minimum": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Chat session list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListChatSessionsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/chat/sessions/{sessionId}": {
      "get": {
        "tags": ["Chat"],
        "summary": "Get chat session",
        "description": "Return a chat session and its full message history when the caller owns it. Foreign or unknown sessions return 404 (never 403) so existence is not leaked. Requires member role and the chat feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          },
          {
            "schema": {
              "type": "string",
              "example": "sess_abc123"
            },
            "required": true,
            "name": "sessionId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Chat session with messages",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChatSessionDetailResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/chat/elicit": {
      "post": {
        "tags": ["Chat"],
        "summary": "Answer elicitation prompt",
        "description": "Answer a pending MCP elicitation prompt (accept, decline, or cancel), unblocking the waiting tool invocation. Requires member role and the chat feature.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ElicitRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Elicitation resolved",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ElicitResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/runners": {
      "get": {
        "tags": ["Deployments"],
        "summary": "List runners (deprecated)",
        "description": "Deprecated: runners migrated to deployments (origin=self-hosted). Always returns an empty list for backward compatibility. Requires member role.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "responses": {
          "200": {
            "description": "Empty runner list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListRunnersResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/projects/{projectId}/runners/heartbeat": {
      "post": {
        "tags": ["Deployments"],
        "summary": "Runner heartbeat",
        "description": "Accept a self-hosted runner heartbeat with usage counters. Authenticated by a flow+deployment-bound runner token. Updates deployment liveness and records an immutable usage row.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^proj_[a-zA-Z0-9_-]+$",
              "example": "proj_x7y8z9"
            },
            "required": true,
            "name": "projectId",
            "in": "path"
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HeartbeatRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Heartbeat accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RunnerHeartbeatResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/packages": {
      "get": {
        "tags": ["System"],
        "summary": "Package catalog",
        "description": "Resolved `@walkeros/*` package catalog for the add-step picker, optionally filtered by type and platform.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "description": "Filter by package type."
            },
            "required": false,
            "description": "Filter by package type.",
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "description": "Filter by platform."
            },
            "required": false,
            "description": "Filter by platform.",
            "name": "platform",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Package catalog",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackageCatalogResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "502": {
            "description": "Package catalog unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/packages/search": {
      "get": {
        "tags": ["System"],
        "summary": "Search packages",
        "description": "Returns the full @walkeros/* package catalog; clients filter locally.",
        "responses": {
          "200": {
            "description": "Search results",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PackageSearchResponse"
                }
              }
            }
          },
          "502": {
            "description": "Package search unavailable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["System"],
        "summary": "Log a settled search",
        "description": "Records one settled search outcome (the term the user paused on and whether the catalog matched it). Fire-and-forget; returns 204.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PackageSearchLogRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Search logged"
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/observe/timing": {
      "post": {
        "tags": ["Observe"],
        "summary": "Report connect timing",
        "description": "Fire-and-forget beacon for client-side connect timing SLIs. No auth required; carries no secrets. Returns 204.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ObserveTimingRequest"
              }
            }
          }
        },
        "responses": {
          "204": {
            "description": "Timing recorded"
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/register": {
      "post": {
        "tags": ["OAuth"],
        "summary": "Register a client",
        "description": "RFC 7591 dynamic client registration. Unauthenticated: a client registers itself before it holds any credential. Issues public clients only (`token_endpoint_auth_method: none`), which prove themselves with PKCE. Errors use the RFC 7591 section 3.2.2 shape, not the standard error envelope.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthClientRegistrationRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client registered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthClientRegistrationResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid client metadata or redirect URI",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthRegistrationError"
                }
              }
            }
          },
          "429": {
            "description": "Registration ceiling reached (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/device_authorization": {
      "post": {
        "tags": ["OAuth"],
        "summary": "Start a device authorization",
        "description": "RFC 8628 section 3.1. A client that cannot host a browser redirect asks for a device code and a user code here, then polls the token endpoint while the person approves the user code at `/oauth/device`. Unauthenticated, and public clients only: the code is worth nothing until a signed-in person approves it. Body is `application/x-www-form-urlencoded`; errors use the RFC 6749 section 5.2 shape, not the standard error envelope.",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/DeviceAuthorizationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Device authorization opened",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceAuthorizationResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request, unauthorized_client, invalid_scope or invalid_target",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "invalid_client: unknown, revoked or confidential client",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/token": {
      "post": {
        "tags": ["OAuth"],
        "summary": "Exchange a grant for tokens",
        "description": "RFC 6749 section 3.2. Runs the authorization code, refresh token and device code grants. The client authenticates here: a public client with PKCE, a confidential one with HTTP Basic or a form secret. Body is `application/x-www-form-urlencoded` only; errors use the RFC 6749 section 5.2 shape, not the standard error envelope, and a failed Basic authentication is answered with a `WWW-Authenticate: Basic` challenge. Responses are never cacheable. Rate limited per `client_id`.",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Tokens issued",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalid_request, invalid_grant, invalid_scope, invalid_target, unsupported_grant_type, or a device grant status (authorization_pending, slow_down, access_denied, expired_token)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "invalid_client: unknown, revoked, or bad credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "429": {
            "description": "Per-client token budget reached (Retry-After header)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/revoke": {
      "post": {
        "tags": ["OAuth"],
        "summary": "Revoke a token",
        "description": "RFC 7009. Client authentication is the same as at the token endpoint. A refresh token revokes its whole rotation family, an access token only itself. An authenticated request always answers 200 with an empty body, unknown tokens included: a distinguishable answer would be an oracle. Body is `application/x-www-form-urlencoded`.",
        "requestBody": {
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/RevocationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Revoked, or nothing matched"
          },
          "400": {
            "description": "invalid_request or unsupported_token_type",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          },
          "401": {
            "description": "invalid_client: unknown, revoked, or bad credentials",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthError"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/device/approve": {
      "post": {
        "tags": ["OAuth"],
        "summary": "Decide a device authorization",
        "description": "The person's approve or deny decision on a pending device authorization. Session only: a bearer credential is refused with 401 `SESSION_REQUIRED`, so a machine token can never approve its own device. Requires the `X-CSRF-Token` minted with the consent page, bound to this user code.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceApprovalRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decision recorded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceApprovalResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/authorize": {
      "post": {
        "tags": ["OAuth"],
        "summary": "Decide a consent request",
        "description": "The person's allow or deny decision on the consent screen at `/oauth/authorize`. The ticket is the HMAC-signed authorization request that screen was rendered from, so the decision cannot alter what was validated, and it is bound to the person it was minted for. Session only: a bearer credential is refused with 401 `SESSION_REQUIRED`, so a machine token can never approve a consent. The response says where to send the browser: the client's registered redirect URI, carrying `code` on allow and `error=access_denied` on deny.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OAuthConsentDecisionRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Decision recorded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OAuthConsentDecisionResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/grants": {
      "get": {
        "tags": ["OAuth"],
        "summary": "List connected apps",
        "description": "The apps the signed-in person has consented to, as the Connected apps page renders them. Revoked grants are absent. Session only: a bearer credential is refused with 401 `SESSION_REQUIRED`, so a machine token cannot read the connections its owner holds.",
        "responses": {
          "200": {
            "description": "Connected apps",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListOAuthGrantsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "tags": ["OAuth"],
        "summary": "Disconnect every app",
        "description": "Revoke every grant this person holds and the tokens hanging from them. Automation tokens hang from no grant and survive. Session only: a bearer credential is refused with 401 `SESSION_REQUIRED`, so a read-scoped machine token cannot disconnect everything its owner has connected.",
        "responses": {
          "204": {
            "description": "Apps disconnected"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/oauth/grants/{grantId}": {
      "delete": {
        "tags": ["OAuth"],
        "summary": "Disconnect one app",
        "description": "Revoke one grant and the tokens hanging from it. Idempotent: an unknown grant, another person's grant and an already revoked one all answer 204, and the token sweep runs either way, so pressing Disconnect twice cleans up a token minted inside the first press's window. Session only: a bearer credential is refused with 401 `SESSION_REQUIRED`.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "grant_abc123"
            },
            "required": true,
            "name": "grantId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "App disconnected"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/oauth/clients": {
      "get": {
        "tags": ["OAuth"],
        "summary": "List OAuth clients",
        "description": "Every registered OAuth client, revoked ones included. No secret material is returned. Admin only: a non-admin caller gets 404, not 403, so the endpoint does not confirm its own existence.",
        "responses": {
          "200": {
            "description": "OAuth client list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListOAuthClientsResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "tags": ["OAuth"],
        "summary": "Create a confidential OAuth client",
        "description": "Create an OAuth client that authenticates with a secret. The raw secret is returned exactly once and is never retrievable afterwards. Admin only: a non-admin caller gets 404, not 403.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateOAuthClientRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Client created",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateOAuthClientResponse"
                }
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/api/admin/oauth/clients/{clientId}": {
      "delete": {
        "tags": ["OAuth"],
        "summary": "Revoke an OAuth client",
        "description": "Revoke a client together with the grants consented to it and the tokens minted under them. Admin only: a non-admin caller gets 404, not 403, the same answer an unknown client id gets.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": "client_abc123"
            },
            "required": true,
            "name": "clientId",
            "in": "path"
          }
        ],
        "responses": {
          "204": {
            "description": "Client revoked"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "404": {
            "description": "Not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}
