From 342f9e3eb4ef76daf4dbc39cb85fabcd739c9b5f Mon Sep 17 00:00:00 2001 From: Jeffrey Smith Date: Thu, 26 Mar 2026 20:23:32 +0000 Subject: [PATCH] Feat icd openapi (#5) Co-authored-by: Jeffrey Smith Co-committed-by: Jeffrey Smith --- CHANGELOG.md | 5 + ROADMAP.md | 4 +- server/static/openapi.yaml | 4182 +++++++++++++++++++++++++++++++++++- 3 files changed, 4149 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62248cc..0523717 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ All notable changes to Switchboard Core are documented here. Settings > Default Surface dropdown. - `default_surface` global config key (JSON `{"id": "slug"}`) - Admin settings UI: Default Surface dropdown (extension surfaces only) +- **ICD (API contract)**: Full OpenAPI 3.0.3 spec covering all 160 kernel + endpoints. 22 tag groups (System, Auth, Profile, Workflows, Packages, + Connections, Teams, Groups, Extensions, and Admin subsections). Reusable + component schemas for User, Team, Group, Workflow, Package, Extension, etc. + Served at `/api/docs` (Swagger UI) and `/api/docs/openapi.yaml`. ### Changed diff --git a/ROADMAP.md b/ROADMAP.md index 2ac4814..dd1ac6c 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -27,7 +27,7 @@ platform that extensions build on. | 5. Fix compilation | βœ… | `go build ./...` clean, 300+ stale route lines cut | | 6. Fix tests | βœ… | 8 test packages pass, ~12K stale test lines pruned | | 7. Frontend gut | βœ… | Shell + SDK only, 50+ files of chat/notes/projects code removed | -| 8. New ICD | πŸ”§ | Stub in place, full kernel-only spec TBD | +| 8. New ICD | βœ… | Full OpenAPI 3.0.3 spec β€” 160 operations across 22 tag groups | | 9. CI/CD + Dockerfile | βœ… | Single unified image, FE/BE split removed, DB names updated, k8s var alignment fixes (resource quantities, image name, rollout deployment name) | | 10. Smoke test | βœ… | K8s deploy live at switchboard.gobha.ai/test, nginx BASE_PATH fixed, loginβ†’admin flow verified, branding updated | @@ -49,7 +49,7 @@ SDK stabilization, and the first rebuilt extension (tasks). | Step | Status | Description | |------|--------|-------------| | Default surface routing | βœ… | `/` redirects to configurable default surface. No surfaces β†’ admin. First install becomes default. Changeable in admin settings. | -| ICD (API contract) | πŸ”² | OpenAPI spec from registered routes, kernel-only endpoint docs | +| ICD (API contract) | βœ… | Full OpenAPI 3.0.3 spec β€” 160 operations, 22 tag groups, reusable component schemas. Served at `/api/docs`. | ### v0.2.2 β€” Event Bus + Triggers diff --git a/server/static/openapi.yaml b/server/static/openapi.yaml index a596c76..450da04 100644 --- a/server/static/openapi.yaml +++ b/server/static/openapi.yaml @@ -19,6 +19,11 @@ info: Access tokens expire in 15 minutes. Refresh tokens expire in 7 days. Use `POST /api/v1/auth/refresh` to rotate. + ## Maintenance + + This spec is maintained by hand. When adding a kernel route, add a + corresponding path entry here. Extension routes (`/s/:slug/api/*`) + and page routes are not part of this ICD. version: '${VERSION}' servers: @@ -31,21 +36,890 @@ servers: basePath: default: '' +tags: + - name: System + - name: Auth + - name: WebSocket + - name: Profile + - name: Presence + - name: Notifications + - name: Workflows + - name: Packages + - name: Connections + - name: Teams + - name: Groups + - name: Extensions + - name: 'Admin: Users' + - name: 'Admin: Settings' + - name: 'Admin: Teams' + - name: 'Admin: Groups' + - name: 'Admin: Permissions' + - name: 'Admin: Connections' + - name: 'Admin: Extensions' + - name: 'Admin: Packages' + - name: 'Admin: System' + - name: 'Admin: Workflows' + +security: + - BearerAuth: [] + +components: + securitySchemes: + BearerAuth: + type: http + scheme: bearer + bearerFormat: JWT + WsAuth: + type: apiKey + in: query + name: ticket + + schemas: + ErrorResponse: + type: object + properties: + error: + type: string + required: [error] + + TokenResponse: + type: object + properties: + access_token: + type: string + refresh_token: + type: string + token_type: + type: string + enum: [bearer] + expires_in: + type: integer + example: 900 + user: + type: object + properties: + id: + type: string + format: uuid + username: + type: string + email: + type: string + display_name: + type: string + handle: + type: string + auth_source: + type: string + enum: [builtin, oidc, mtls] + + User: + type: object + properties: + id: + type: string + format: uuid + username: + type: string + email: + type: string + display_name: + type: string + avatar_url: + type: string + nullable: true + is_active: + type: boolean + settings: + type: object + last_login_at: + type: string + format: date-time + nullable: true + auth_source: + type: string + enum: [builtin, oidc, mtls] + handle: + type: string + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + Team: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + created_by: + type: string + format: uuid + is_active: + type: boolean + settings: + type: object + member_count: + type: integer + my_role: + type: string + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + TeamMember: + type: object + properties: + id: + type: string + format: uuid + team_id: + type: string + format: uuid + user_id: + type: string + format: uuid + role: + type: string + enum: [admin, member] + joined_at: + type: string + format: date-time + email: + type: string + display_name: + type: string + username: + type: string + + Group: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + description: + type: string + scope: + type: string + enum: [global, team] + team_id: + type: string + format: uuid + nullable: true + source: + type: string + permissions: + type: array + items: + type: string + member_count: + type: integer + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + GroupMember: + type: object + properties: + id: + type: string + format: uuid + group_id: + type: string + format: uuid + user_id: + type: string + format: uuid + added_by: + type: string + format: uuid + added_at: + type: string + format: date-time + username: + type: string + email: + type: string + display_name: + type: string + + ResourceGrant: + type: object + properties: + id: + type: string + format: uuid + resource_type: + type: string + resource_id: + type: string + grant_scope: + type: string + enum: [team_only, global, groups] + granted_groups: + type: array + items: + type: string + created_by: + type: string + format: uuid + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + AuditEntry: + type: object + properties: + id: + type: string + format: uuid + actor_id: + type: string + format: uuid + nullable: true + actor_name: + type: string + nullable: true + action: + type: string + resource_type: + type: string + resource_id: + type: string + metadata: + type: object + ip_address: + type: string + user_agent: + type: string + created_at: + type: string + format: date-time + + Workflow: + type: object + properties: + id: + type: string + format: uuid + name: + type: string + slug: + type: string + entry_mode: + type: string + enum: [public_link, team_only] + scope: + type: string + team_id: + type: string + format: uuid + nullable: true + created_by: + type: string + format: uuid + version: + type: integer + stages: + type: array + items: + $ref: '#/components/schemas/Stage' + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + Stage: + type: object + properties: + id: + type: string + format: uuid + workflow_id: + type: string + format: uuid + name: + type: string + history_mode: + type: string + enum: [full, summary, fresh] + stage_mode: + type: string + enum: [custom, form_only, form_chat, review] + ordinal: + type: integer + form_template: + type: object + transition_rules: + type: object + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + WorkflowVersion: + type: object + properties: + id: + type: string + format: uuid + workflow_id: + type: string + format: uuid + version_number: + type: integer + snapshot: + type: object + created_at: + type: string + format: date-time + + Package: + type: object + properties: + id: + type: string + format: uuid + title: + type: string + type: + type: string + enum: [surface, extension, full, workflow, library] + version: + type: string + description: + type: string + author: + type: string + tier: + type: string + enum: [browser, starlark, sidecar] + scope: + type: string + enum: [global, team, personal] + team_id: + type: string + format: uuid + nullable: true + enabled: + type: boolean + source: + type: string + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + Extension: + type: object + properties: + id: + type: string + format: uuid + ext_id: + type: string + name: + type: string + version: + type: string + tier: + type: string + description: + type: string + author: + type: string + manifest: + type: object + is_system: + type: boolean + is_enabled: + type: boolean + scope: + type: string + team_id: + type: string + format: uuid + nullable: true + created_at: + type: string + format: date-time + updated_at: + type: string + format: date-time + + NotificationPreference: + type: object + properties: + user_id: + type: string + format: uuid + type: + type: string + in_app: + type: boolean + email: + type: boolean + + parameters: + limitParam: + name: limit + in: query + schema: + type: integer + default: 50 + offsetParam: + name: offset + in: query + schema: + type: integer + default: 0 + pageParam: + name: page + in: query + schema: + type: integer + default: 1 + perPageParam: + name: per_page + in: query + schema: + type: integer + default: 50 + idPath: + name: id + in: path + required: true + schema: + type: string + format: uuid + teamIdPath: + name: teamId + in: path + required: true + schema: + type: string + format: uuid + paths: + # ────────────────────────────────────────────── + # System + # ────────────────────────────────────────────── /health: get: - summary: Health check + summary: Legacy health check operationId: healthCheck tags: [System] + security: [] responses: '200': - description: OK + description: Health status + content: + application/json: + schema: + type: object + properties: + status: + type: string + version: + type: string + database: + type: string + database_name: + type: string + schema_version: + type: integer + + /healthz/live: + get: + summary: Liveness probe + operationId: livenessProbe + tags: [System] + security: [] + responses: + '200': + description: Process is alive + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: ok + + /healthz/ready: + get: + summary: Readiness probe + operationId: readinessProbe + tags: [System] + security: [] + responses: + '200': + description: Service is ready + content: + application/json: + schema: + type: object + properties: + status: + type: string + example: ok + '503': + description: Service unavailable + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /metrics: + get: + summary: Prometheus metrics + operationId: getMetrics + tags: [System] + security: [] + responses: + '200': + description: Prometheus text exposition + content: + text/plain: + schema: + type: string + + /api/v1/health: + get: + summary: API health check + operationId: apiHealthCheck + tags: [System] + security: [] + responses: + '200': + description: API health status + content: + application/json: + schema: + type: object + properties: + status: + type: string + version: + type: string + schema_version: + type: integer + database: + type: string + database_name: + type: string + registration_enabled: + type: boolean + + # ────────────────────────────────────────────── + # Auth + # ────────────────────────────────────────────── + /api/v1/auth/register: + post: + summary: Register a new user + operationId: registerUser + tags: [Auth] + security: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [username, email, password] + properties: + username: + type: string + email: + type: string + password: + type: string + display_name: + type: string + responses: + '201': + description: User created + content: + application/json: + schema: + $ref: '#/components/schemas/TokenResponse' + '400': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '409': + description: Username or email taken + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' /api/v1/auth/login: post: - summary: Login (builtin auth) - operationId: login + summary: Log in with username or email + operationId: loginUser tags: [Auth] + security: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [login, password] + properties: + login: + type: string + password: + type: string + responses: + '200': + description: Authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/TokenResponse' + '401': + description: Invalid credentials + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/v1/auth/refresh: + post: + summary: Refresh access token + operationId: refreshToken + tags: [Auth] + security: [] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [refresh_token] + properties: + refresh_token: + type: string + responses: + '200': + description: New token pair + content: + application/json: + schema: + $ref: '#/components/schemas/TokenResponse' + '401': + description: Invalid or expired refresh token + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/v1/auth/logout: + post: + summary: Log out and revoke tokens + operationId: logoutUser + tags: [Auth] + security: [] + requestBody: + content: + application/json: + schema: + type: object + properties: + refresh_token: + type: string + responses: + '200': + description: Logged out + content: + application/json: + schema: + type: object + properties: + message: + type: string + + /api/v1/auth/oidc/login: + get: + summary: Start OIDC login flow + operationId: oidcLogin + tags: [Auth] + security: [] + parameters: + - name: redirect + in: query + schema: + type: string + responses: + '302': + description: Redirect to IdP + + /api/v1/auth/oidc/callback: + get: + summary: OIDC callback endpoint + operationId: oidcCallback + tags: [Auth] + security: [] + parameters: + - name: code + in: query + required: true + schema: + type: string + - name: state + in: query + required: true + schema: + type: string + - name: error + in: query + schema: + type: string + - name: error_description + in: query + schema: + type: string + responses: + '302': + description: Redirect to app with tokens + + # ────────────────────────────────────────────── + # WebSocket + # ────────────────────────────────────────────── + /ws: + get: + summary: WebSocket connection + operationId: wsConnect + tags: [WebSocket] + security: + - WsAuth: [] + parameters: + - name: ticket + in: query + required: true + schema: + type: string + responses: + '101': + description: Switching protocols + + /api/v1/ws/ticket: + post: + summary: Get a WebSocket ticket + operationId: getWsTicket + tags: [WebSocket] + responses: + '200': + description: One-time ticket + content: + application/json: + schema: + type: object + properties: + ticket: + type: string + + # ────────────────────────────────────────────── + # Extension Assets + # ────────────────────────────────────────────── + /api/v1/extensions/{id}/assets/{path}: + get: + summary: Serve extension static asset + operationId: getExtensionAsset + tags: [Extensions] + security: [] + parameters: + - name: id + in: path + required: true + schema: + type: string + format: uuid + - name: path + in: path + required: true + schema: + type: string + responses: + '200': + description: Static file + '404': + description: Asset not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # ────────────────────────────────────────────── + # Profile + # ────────────────────────────────────────────── + /api/v1/profile: + get: + summary: Get current user profile + operationId: getProfile + tags: [Profile] + responses: + '200': + description: Current user profile + content: + application/json: + schema: + type: object + properties: + id: + type: string + format: uuid + username: + type: string + email: + type: string + display_name: + type: string + avatar: + type: string + nullable: true + settings: + type: object + created_at: + type: string + format: date-time + last_login_at: + type: string + format: date-time + nullable: true + put: + summary: Update current user profile + operationId: updateProfile + tags: [Profile] requestBody: required: true content: @@ -53,53 +927,3281 @@ paths: schema: type: object properties: - login: + display_name: + type: string + email: + type: string + responses: + '200': + description: Updated profile + content: + application/json: + schema: + type: object + properties: + id: + type: string + format: uuid + username: + type: string + email: + type: string + display_name: + type: string + avatar: + type: string + nullable: true + settings: + type: object + created_at: + type: string + format: date-time + last_login_at: + type: string + format: date-time + nullable: true + + /api/v1/profile/password: + post: + summary: Change password + operationId: changePassword + tags: [Profile] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [current_password, new_password] + properties: + current_password: + type: string + new_password: + type: string + responses: + '200': + description: Password changed + content: + application/json: + schema: + type: object + properties: + message: + type: string + '400': + description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/v1/settings: + get: + summary: Get user settings + operationId: getUserSettings + tags: [Profile] + responses: + '200': + description: User settings + content: + application/json: + schema: + type: object + properties: + settings: + type: object + put: + summary: Update user settings + operationId: updateUserSettings + tags: [Profile] + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Updated settings + content: + application/json: + schema: + type: object + properties: + settings: + type: object + + /api/v1/profile/permissions: + get: + summary: Get current user permissions + operationId: getMyPermissions + tags: [Profile] + responses: + '200': + description: Permissions for current user + content: + application/json: + schema: + type: object + properties: + permissions: + type: array + items: + type: string + groups: + type: array + items: + type: object + teams: + type: array + items: + type: object + policies: + type: object + + /api/v1/profile/bootstrap: + get: + summary: Bootstrap data for current user + operationId: getBootstrap + tags: [Profile] + responses: + '200': + description: Combined bootstrap payload + content: + application/json: + schema: + type: object + properties: + user: + type: object + permissions: + type: array + items: + type: string + groups: + type: array + items: + type: object + teams: + type: array + items: + type: object + policies: + type: object + settings: + type: object + + # ────────────────────────────────────────────── + # Presence + # ────────────────────────────────────────────── + /api/v1/presence/heartbeat: + post: + summary: Send presence heartbeat + operationId: presenceHeartbeat + tags: [Presence] + responses: + '200': + description: Heartbeat acknowledged + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/presence: + get: + summary: Get presence for users + operationId: getPresence + tags: [Presence] + parameters: + - name: users + in: query + schema: + type: string + responses: + '200': + description: Presence map + content: + application/json: + schema: + type: object + properties: + presence: + type: object + + /api/v1/users/search: + get: + summary: Search users by name or email + operationId: searchUsers + tags: [Presence] + parameters: + - name: q + in: query + required: true + schema: + type: string + responses: + '200': + description: Matching users + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + + # ────────────────────────────────────────────── + # Notifications + # ────────────────────────────────────────────── + /api/v1/notifications: + get: + summary: List notifications + operationId: listNotifications + tags: [Notifications] + parameters: + - $ref: '#/components/parameters/limitParam' + - $ref: '#/components/parameters/offsetParam' + - name: unread_only + in: query + schema: + type: boolean + responses: + '200': + description: Paginated notifications + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + total: + type: integer + limit: + type: integer + offset: + type: integer + + /api/v1/notifications/unread-count: + get: + summary: Get unread notification count + operationId: getUnreadCount + tags: [Notifications] + responses: + '200': + description: Unread count + content: + application/json: + schema: + type: object + properties: + count: + type: integer + + /api/v1/notifications/{id}/read: + patch: + summary: Mark notification as read + operationId: markNotificationRead + tags: [Notifications] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Marked as read + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/notifications/mark-all-read: + post: + summary: Mark all notifications as read + operationId: markAllNotificationsRead + tags: [Notifications] + responses: + '200': + description: All marked as read + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/notifications/{id}: + delete: + summary: Delete a notification + operationId: deleteNotification + tags: [Notifications] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/notifications/preferences: + get: + summary: Get notification preferences + operationId: getNotificationPreferences + tags: [Notifications] + responses: + '200': + description: Notification preferences + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/NotificationPreference' + + /api/v1/notifications/preferences/{type}: + put: + summary: Update notification preference + operationId: updateNotificationPreference + tags: [Notifications] + parameters: + - name: type + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + in_app: + type: boolean + email: + type: boolean + responses: + '200': + description: Updated preference + content: + application/json: + schema: + $ref: '#/components/schemas/NotificationPreference' + delete: + summary: Delete notification preference + operationId: deleteNotificationPreference + tags: [Notifications] + parameters: + - name: type + in: path + required: true + schema: + type: string + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + # ────────────────────────────────────────────── + # User Teams / Groups + # ────────────────────────────────────────────── + /api/v1/teams/mine: + get: + summary: List teams for current user + operationId: listMyTeams + tags: [Teams] + responses: + '200': + description: User teams + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Team' + + /api/v1/groups/mine: + get: + summary: List groups for current user + operationId: listMyGroups + tags: [Groups] + responses: + '200': + description: User groups + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Group' + + # ────────────────────────────────────────────── + # Public Settings + # ────────────────────────────────────────────── + /api/v1/settings/public: + get: + summary: Get public settings + operationId: getPublicSettings + tags: [System] + security: [] + responses: + '200': + description: Public settings + content: + application/json: + schema: + type: object + properties: + banner: + type: string + branding: + type: object + has_admin_prompt: + type: boolean + storage_configured: + type: boolean + paste_to_file_chars: + type: integer + policies: + type: object + + # ────────────────────────────────────────────── + # Workflows (user-scoped) + # ────────────────────────────────────────────── + /api/v1/workflows: + get: + summary: List workflows + operationId: listWorkflows + tags: [Workflows] + responses: + '200': + description: Workflow list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Workflow' + post: + summary: Create a workflow + operationId: createWorkflow + tags: [Workflows] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + entry_mode: + type: string + enum: [public_link, team_only] + responses: + '201': + description: Workflow created + content: + application/json: + schema: + $ref: '#/components/schemas/Workflow' + + /api/v1/workflows/{id}: + get: + summary: Get a workflow + operationId: getWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Workflow detail + content: + application/json: + schema: + $ref: '#/components/schemas/Workflow' + '404': + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + summary: Update a workflow + operationId: updateWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + entry_mode: + type: string + enum: [public_link, team_only] + responses: + '200': + description: Updated workflow + content: + application/json: + schema: + $ref: '#/components/schemas/Workflow' + delete: + summary: Delete a workflow + operationId: deleteWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/workflows/{id}/stages: + get: + summary: List stages for a workflow + operationId: listWorkflowStages + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Stage list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Stage' + post: + summary: Create a stage + operationId: createWorkflowStage + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + history_mode: + type: string + enum: [full, summary, fresh] + stage_mode: + type: string + enum: [custom, form_only, form_chat, review] + form_template: + type: object + transition_rules: + type: object + responses: + '201': + description: Stage created + content: + application/json: + schema: + $ref: '#/components/schemas/Stage' + + /api/v1/workflows/{id}/stages/{sid}: + put: + summary: Update a stage + operationId: updateWorkflowStage + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + - name: sid + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + history_mode: + type: string + enum: [full, summary, fresh] + stage_mode: + type: string + enum: [custom, form_only, form_chat, review] + form_template: + type: object + transition_rules: + type: object + responses: + '200': + description: Updated stage + content: + application/json: + schema: + $ref: '#/components/schemas/Stage' + delete: + summary: Delete a stage + operationId: deleteWorkflowStage + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + - name: sid + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/workflows/{id}/stages/reorder: + patch: + summary: Reorder workflow stages + operationId: reorderWorkflowStages + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [order] + properties: + order: + type: array + items: + type: string + format: uuid + responses: + '200': + description: Reordered + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/workflows/{id}/publish: + post: + summary: Publish a workflow version + operationId: publishWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Published + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowVersion' + + /api/v1/workflows/{id}/versions/{version}: + get: + summary: Get a specific workflow version + operationId: getWorkflowVersion + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/idPath' + - name: version + in: path + required: true + schema: + type: integer + responses: + '200': + description: Version snapshot + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowVersion' + '404': + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # ────────────────────────────────────────────── + # Packages (user-scoped) + # ────────────────────────────────────────────── + /api/v1/surfaces: + get: + summary: List installed surfaces + operationId: listSurfaces + tags: [Packages] + responses: + '200': + description: Surface list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + properties: + id: + type: string + format: uuid + title: + type: string + route: + type: string + + /api/v1/packages: + get: + summary: List packages visible to current user + operationId: listPackages + tags: [Packages] + responses: + '200': + description: Package list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Package' + + /api/v1/packages/install: + post: + summary: Install a package (personal scope) + operationId: installPackage + tags: [Packages] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '201': + description: Package installed + content: + application/json: + schema: + type: object + properties: + id: + type: string + format: uuid + title: + type: string + type: + type: string + version: + type: string + scope: + type: string + source: + type: string + + /api/v1/packages/{id}: + delete: + summary: Uninstall a package + operationId: deletePackage + tags: [Packages] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Connection Types + # ────────────────────────────────────────────── + /api/v1/connection-types: + get: + summary: List available connection types + operationId: listConnectionTypes + tags: [Connections] + responses: + '200': + description: Connection type list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + properties: + type: + type: string + label: + type: string + package_id: + type: string + format: uuid + package_title: + type: string + fields: + type: array + items: + type: object + scopes: + type: array + items: + type: string + + # ────────────────────────────────────────────── + # Connections (personal) + # ────────────────────────────────────────────── + /api/v1/connections: + get: + summary: List personal connections + operationId: listConnections + tags: [Connections] + responses: + '200': + description: Connection list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + post: + summary: Create a personal connection + operationId: createConnection + tags: [Connections] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [type, name, credentials] + properties: + type: + type: string + name: + type: string + credentials: + type: object + responses: + '201': + description: Connection created + content: + application/json: + schema: + type: object + + /api/v1/connections/resolve: + get: + summary: Resolve a connection by type and optional name + operationId: resolveConnection + tags: [Connections] + parameters: + - name: type + in: query + required: true + schema: + type: string + - name: name + in: query + schema: + type: string + responses: + '200': + description: Resolved connection + content: + application/json: + schema: + type: object + + /api/v1/connections/{id}: + get: + summary: Get a connection + operationId: getConnection + tags: [Connections] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Connection detail + content: + application/json: + schema: + type: object + put: + summary: Update a connection + operationId: updateConnection + tags: [Connections] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + credentials: + type: object + responses: + '200': + description: Updated connection + content: + application/json: + schema: + type: object + delete: + summary: Delete a connection + operationId: deleteConnection + tags: [Connections] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Extensions (user-scoped) + # ────────────────────────────────────────────── + /api/v1/extensions: + get: + summary: List extensions visible to current user + operationId: listExtensions + tags: [Extensions] + parameters: + - name: tier + in: query + schema: + type: string + responses: + '200': + description: Extension list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Extension' + + /api/v1/extensions/{id}/settings: + post: + summary: Update extension settings for current user + operationId: updateExtensionSettings + tags: [Extensions] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + settings: + type: object + is_enabled: + type: boolean + responses: + '200': + description: Settings updated + content: + application/json: + schema: + type: object + + /api/v1/extensions/{id}/manifest: + get: + summary: Get extension manifest + operationId: getExtensionManifest + tags: [Extensions] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Extension manifest + content: + application/json: + schema: + type: object + + /api/v1/extensions/tools: + get: + summary: List all extension tools + operationId: listExtensionTools + tags: [Extensions] + responses: + '200': + description: Tool list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + + # ────────────────────────────────────────────── + # Team-scoped endpoints + # ────────────────────────────────────────────── + /api/v1/teams/{teamId}/members: + get: + summary: List team members + operationId: listTeamMembers + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + responses: + '200': + description: Team member list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/TeamMember' + post: + summary: Add a team member + operationId: addTeamMember + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [user_id] + properties: + user_id: + type: string + format: uuid + role: + type: string + enum: [admin, member] + responses: + '201': + description: Member added + content: + application/json: + schema: + $ref: '#/components/schemas/TeamMember' + + /api/v1/teams/{teamId}/members/{memberId}: + put: + summary: Update team member role + operationId: updateTeamMember + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - name: memberId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [role] + properties: + role: + type: string + enum: [admin, member] + responses: + '200': + description: Member updated + content: + application/json: + schema: + $ref: '#/components/schemas/TeamMember' + delete: + summary: Remove team member + operationId: removeTeamMember + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - name: memberId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Member removed + content: + application/json: + schema: + type: object + properties: + removed: + type: boolean + + /api/v1/teams/{teamId}/groups: + get: + summary: List groups in a team + operationId: listTeamGroups + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + responses: + '200': + description: Team group list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Group' + + /api/v1/teams/{teamId}/connections: + get: + summary: List team connections + operationId: listTeamConnections + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + responses: + '200': + description: Team connection list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + post: + summary: Create a team connection + operationId: createTeamConnection + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [type, name, credentials] + properties: + type: + type: string + name: + type: string + credentials: + type: object + responses: + '201': + description: Connection created + content: + application/json: + schema: + type: object + + /api/v1/teams/{teamId}/connections/{id}: + put: + summary: Update a team connection + operationId: updateTeamConnection + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + credentials: + type: object + responses: + '200': + description: Updated + content: + application/json: + schema: + type: object + delete: + summary: Delete a team connection + operationId: deleteTeamConnection + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/teams/{teamId}/packages/install: + post: + summary: Install a package into a team + operationId: installTeamPackage + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '201': + description: Package installed + content: + application/json: + schema: + type: object + + /api/v1/teams/{teamId}/packages/{id}: + delete: + summary: Uninstall a team package + operationId: deleteTeamPackage + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/teams/{teamId}/packages/{id}/settings: + get: + summary: Get team package settings + operationId: getTeamPackageSettings + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package settings + content: + application/json: + schema: + type: object + put: + summary: Update team package settings + operationId: updateTeamPackageSettings + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Updated settings + content: + application/json: + schema: + type: object + delete: + summary: Delete team package settings + operationId: deleteTeamPackageSettings + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/teams/{teamId}/audit: + get: + summary: List team audit log + operationId: listTeamAuditLog + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/pageParam' + - $ref: '#/components/parameters/perPageParam' + - name: action + in: query + schema: + type: string + - name: actor_id + in: query + schema: + type: string + format: uuid + - name: resource_type + in: query + schema: + type: string + responses: + '200': + description: Audit log entries + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AuditEntry' + page: + type: integer + per_page: + type: integer + total: + type: integer + + /api/v1/teams/{teamId}/audit/actions: + get: + summary: List available audit actions for team + operationId: listTeamAuditActions + tags: [Teams] + parameters: + - $ref: '#/components/parameters/teamIdPath' + responses: + '200': + description: Audit action list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: string + + # Team Workflows + /api/v1/teams/{teamId}/workflows: + get: + summary: List team workflows + operationId: listTeamWorkflows + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + responses: + '200': + description: Team workflow list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Workflow' + post: + summary: Create a team workflow + operationId: createTeamWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + entry_mode: + type: string + enum: [public_link, team_only] + responses: + '201': + description: Workflow created + content: + application/json: + schema: + $ref: '#/components/schemas/Workflow' + + /api/v1/teams/{teamId}/workflows/{id}: + get: + summary: Get a team workflow + operationId: getTeamWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Workflow detail + content: + application/json: + schema: + $ref: '#/components/schemas/Workflow' + '404': + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + patch: + summary: Update a team workflow + operationId: updateTeamWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + entry_mode: + type: string + enum: [public_link, team_only] + responses: + '200': + description: Updated workflow + content: + application/json: + schema: + $ref: '#/components/schemas/Workflow' + delete: + summary: Delete a team workflow + operationId: deleteTeamWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/teams/{teamId}/workflows/{id}/stages: + get: + summary: List stages for a team workflow + operationId: listTeamWorkflowStages + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Stage list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Stage' + post: + summary: Create a team workflow stage + operationId: createTeamWorkflowStage + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + history_mode: + type: string + enum: [full, summary, fresh] + stage_mode: + type: string + enum: [custom, form_only, form_chat, review] + form_template: + type: object + transition_rules: + type: object + responses: + '201': + description: Stage created + content: + application/json: + schema: + $ref: '#/components/schemas/Stage' + + /api/v1/teams/{teamId}/workflows/{id}/stages/{sid}: + put: + summary: Update a team workflow stage + operationId: updateTeamWorkflowStage + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + - name: sid + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + history_mode: + type: string + enum: [full, summary, fresh] + stage_mode: + type: string + enum: [custom, form_only, form_chat, review] + form_template: + type: object + transition_rules: + type: object + responses: + '200': + description: Updated stage + content: + application/json: + schema: + $ref: '#/components/schemas/Stage' + delete: + summary: Delete a team workflow stage + operationId: deleteTeamWorkflowStage + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + - name: sid + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/teams/{teamId}/workflows/{id}/stages/reorder: + patch: + summary: Reorder team workflow stages + operationId: reorderTeamWorkflowStages + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [order] + properties: + order: + type: array + items: + type: string + format: uuid + responses: + '200': + description: Reordered + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + + /api/v1/teams/{teamId}/workflows/{id}/publish: + post: + summary: Publish a team workflow version + operationId: publishTeamWorkflow + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Published + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowVersion' + + /api/v1/teams/{teamId}/workflows/{id}/versions/{version}: + get: + summary: Get a specific team workflow version + operationId: getTeamWorkflowVersion + tags: [Workflows] + parameters: + - $ref: '#/components/parameters/teamIdPath' + - $ref: '#/components/parameters/idPath' + - name: version + in: path + required: true + schema: + type: integer + responses: + '200': + description: Version snapshot + content: + application/json: + schema: + $ref: '#/components/schemas/WorkflowVersion' + '404': + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + # ────────────────────────────────────────────── + # Admin: Users + # ────────────────────────────────────────────── + /api/v1/admin/users: + get: + summary: List all users + operationId: adminListUsers + tags: ['Admin: Users'] + responses: + '200': + description: User list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/User' + post: + summary: Create a user + operationId: adminCreateUser + tags: ['Admin: Users'] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [username, email, password] + properties: + username: + type: string + email: type: string password: type: string - required: [login, password] - responses: - '200': - description: JWT tokens returned - - /api/v1/auth/register: - post: - summary: Register new user (builtin auth) - operationId: register - tags: [Auth] + display_name: + type: string responses: '201': description: User created + content: + application/json: + schema: + $ref: '#/components/schemas/User' - /api/v1/auth/refresh: + /api/v1/admin/users/{id}/role: + put: + summary: Update user role + operationId: adminUpdateUserRole + tags: ['Admin: Users'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [role] + properties: + role: + type: string + responses: + '200': + description: Role updated + content: + application/json: + schema: + type: object + + /api/v1/admin/users/{id}/active: + put: + summary: Activate or deactivate a user + operationId: adminSetUserActive + tags: ['Admin: Users'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [is_active] + properties: + is_active: + type: boolean + responses: + '200': + description: Status updated + content: + application/json: + schema: + type: object + + /api/v1/admin/users/{id}/reset-password: post: - summary: Refresh access token - operationId: refreshToken - tags: [Auth] + summary: Reset user password + operationId: adminResetUserPassword + tags: ['Admin: Users'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [new_password] + properties: + new_password: + type: string responses: '200': - description: New token pair + description: Password reset + content: + application/json: + schema: + type: object + properties: + message: + type: string - /api/v1/auth/oidc/login: - get: - summary: Initiate OIDC login - operationId: oidcLogin - tags: [Auth] - responses: - '302': - description: Redirect to IdP - - /api/v1/auth/oidc/callback: - get: - summary: OIDC callback - operationId: oidcCallback - tags: [Auth] + /api/v1/admin/users/{id}/vault/reset: + post: + summary: Reset user vault + operationId: adminResetUserVault + tags: ['Admin: Users'] + parameters: + - $ref: '#/components/parameters/idPath' responses: '200': - description: JWT tokens returned + description: Vault reset + content: + application/json: + schema: + type: object + properties: + message: + type: string -# ═══════════════════════════════════════════════════════ -# TODO: Step 8 β€” Generate full kernel-only ICD from -# the route registrations in main.go. This stub keeps -# /api/docs functional during the transition. -# ═══════════════════════════════════════════════════════ + /api/v1/admin/users/{id}: + delete: + summary: Delete a user + operationId: adminDeleteUser + tags: ['Admin: Users'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Settings + # ────────────────────────────────────────────── + /api/v1/admin/settings: + get: + summary: List all settings + operationId: adminListSettings + tags: ['Admin: Settings'] + responses: + '200': + description: All settings + content: + application/json: + schema: + type: object + + /api/v1/admin/settings/{key}: + get: + summary: Get a setting by key + operationId: adminGetSetting + tags: ['Admin: Settings'] + parameters: + - name: key + in: path + required: true + schema: + type: string + responses: + '200': + description: Setting value + content: + application/json: + schema: + type: object + put: + summary: Update a setting by key + operationId: adminUpdateSetting + tags: ['Admin: Settings'] + parameters: + - name: key + in: path + required: true + schema: + type: string + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [value] + properties: + value: {} + responses: + '200': + description: Setting updated + content: + application/json: + schema: + type: object + + # ────────────────────────────────────────────── + # Admin: Stats + # ────────────────────────────────────────────── + /api/v1/admin/stats: + get: + summary: Get system statistics + operationId: adminGetStats + tags: ['Admin: System'] + responses: + '200': + description: System stats + content: + application/json: + schema: + type: object + properties: + users: + type: integer + + # ────────────────────────────────────────────── + # Admin: Connections + # ────────────────────────────────────────────── + /api/v1/admin/connections: + get: + summary: List all connections + operationId: adminListConnections + tags: ['Admin: Connections'] + responses: + '200': + description: Connection list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + post: + summary: Create a global connection + operationId: adminCreateConnection + tags: ['Admin: Connections'] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [type, name, credentials] + properties: + type: + type: string + name: + type: string + credentials: + type: object + responses: + '201': + description: Connection created + content: + application/json: + schema: + type: object + + /api/v1/admin/connections/{id}: + put: + summary: Update a global connection + operationId: adminUpdateConnection + tags: ['Admin: Connections'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + credentials: + type: object + responses: + '200': + description: Updated + content: + application/json: + schema: + type: object + delete: + summary: Delete a global connection + operationId: adminDeleteConnection + tags: ['Admin: Connections'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Teams + # ────────────────────────────────────────────── + /api/v1/admin/teams: + get: + summary: List all teams + operationId: adminListTeams + tags: ['Admin: Teams'] + responses: + '200': + description: Team list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Team' + post: + summary: Create a team + operationId: adminCreateTeam + tags: ['Admin: Teams'] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + description: + type: string + responses: + '201': + description: Team created + content: + application/json: + schema: + $ref: '#/components/schemas/Team' + + /api/v1/admin/teams/{id}: + get: + summary: Get a team + operationId: adminGetTeam + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Team detail + content: + application/json: + schema: + $ref: '#/components/schemas/Team' + put: + summary: Update a team + operationId: adminUpdateTeam + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: + type: string + is_active: + type: boolean + responses: + '200': + description: Updated + content: + application/json: + schema: + $ref: '#/components/schemas/Team' + delete: + summary: Delete a team + operationId: adminDeleteTeam + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/admin/teams/{id}/members: + get: + summary: List members of a team (admin) + operationId: adminListTeamMembers + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Member list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/TeamMember' + post: + summary: Add member to a team (admin) + operationId: adminAddTeamMember + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [user_id] + properties: + user_id: + type: string + format: uuid + role: + type: string + enum: [admin, member] + responses: + '201': + description: Member added + content: + application/json: + schema: + $ref: '#/components/schemas/TeamMember' + + /api/v1/admin/teams/{id}/members/{memberId}: + put: + summary: Update team member role (admin) + operationId: adminUpdateTeamMember + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + - name: memberId + in: path + required: true + schema: + type: string + format: uuid + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [role] + properties: + role: + type: string + enum: [admin, member] + responses: + '200': + description: Updated + content: + application/json: + schema: + $ref: '#/components/schemas/TeamMember' + delete: + summary: Remove team member (admin) + operationId: adminRemoveTeamMember + tags: ['Admin: Teams'] + parameters: + - $ref: '#/components/parameters/idPath' + - name: memberId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Removed + content: + application/json: + schema: + type: object + properties: + removed: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Notifications + # ────────────────────────────────────────────── + /api/v1/admin/notifications/broadcast: + post: + summary: Broadcast a notification to all users + operationId: adminBroadcastNotification + tags: ['Admin: System'] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [title, message] + properties: + title: + type: string + message: + type: string + level: + type: string + responses: + '200': + description: Broadcast sent + content: + application/json: + schema: + type: object + properties: + message: + type: string + count: + type: integer + + # ────────────────────────────────────────────── + # Admin: Audit + # ────────────────────────────────────────────── + /api/v1/admin/audit: + get: + summary: List global audit log + operationId: adminListAuditLog + tags: ['Admin: System'] + parameters: + - $ref: '#/components/parameters/pageParam' + - $ref: '#/components/parameters/perPageParam' + - name: action + in: query + schema: + type: string + - name: actor_id + in: query + schema: + type: string + format: uuid + - name: resource_type + in: query + schema: + type: string + responses: + '200': + description: Audit log entries + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/AuditEntry' + page: + type: integer + per_page: + type: integer + total: + type: integer + + /api/v1/admin/audit/actions: + get: + summary: List available audit actions + operationId: adminListAuditActions + tags: ['Admin: System'] + responses: + '200': + description: Audit action list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: string + + # ────────────────────────────────────────────── + # Admin: Groups + # ────────────────────────────────────────────── + /api/v1/admin/groups: + get: + summary: List all groups + operationId: adminListGroups + tags: ['Admin: Groups'] + responses: + '200': + description: Group list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Group' + post: + summary: Create a group + operationId: adminCreateGroup + tags: ['Admin: Groups'] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [name] + properties: + name: + type: string + description: + type: string + scope: + type: string + enum: [global, team] + team_id: + type: string + format: uuid + permissions: + type: array + items: + type: string + responses: + '201': + description: Group created + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + + /api/v1/admin/groups/{id}: + get: + summary: Get a group + operationId: adminGetGroup + tags: ['Admin: Groups'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Group detail + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + put: + summary: Update a group + operationId: adminUpdateGroup + tags: ['Admin: Groups'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: + type: string + permissions: + type: array + items: + type: string + responses: + '200': + description: Updated + content: + application/json: + schema: + $ref: '#/components/schemas/Group' + delete: + summary: Delete a group + operationId: adminDeleteGroup + tags: ['Admin: Groups'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/admin/groups/{id}/members: + get: + summary: List group members + operationId: adminListGroupMembers + tags: ['Admin: Groups'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Member list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/GroupMember' + post: + summary: Add member to a group + operationId: adminAddGroupMember + tags: ['Admin: Groups'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [user_id] + properties: + user_id: + type: string + format: uuid + responses: + '201': + description: Member added + content: + application/json: + schema: + $ref: '#/components/schemas/GroupMember' + + /api/v1/admin/groups/{id}/members/{userId}: + delete: + summary: Remove member from a group + operationId: adminRemoveGroupMember + tags: ['Admin: Groups'] + parameters: + - $ref: '#/components/parameters/idPath' + - name: userId + in: path + required: true + schema: + type: string + format: uuid + responses: + '200': + description: Removed + content: + application/json: + schema: + type: object + properties: + removed: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Permissions + # ────────────────────────────────────────────── + /api/v1/admin/permissions: + get: + summary: List all available permissions + operationId: adminListPermissions + tags: ['Admin: Permissions'] + responses: + '200': + description: Permission list + content: + application/json: + schema: + type: object + properties: + permissions: + type: array + items: + type: string + + /api/v1/admin/users/{id}/permissions: + get: + summary: Get effective permissions for a user + operationId: adminGetUserPermissions + tags: ['Admin: Permissions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: User permissions + content: + application/json: + schema: + type: object + properties: + permissions: + type: array + items: + type: string + user_id: + type: string + format: uuid + groups: + type: array + items: + type: object + + # ────────────────────────────────────────────── + # Admin: Grants + # ────────────────────────────────────────────── + /api/v1/admin/grants/{type}/{id}: + get: + summary: Get grant for a resource + operationId: adminGetGrant + tags: ['Admin: Permissions'] + parameters: + - name: type + in: path + required: true + schema: + type: string + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Resource grant + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGrant' + put: + summary: Set grant for a resource + operationId: adminSetGrant + tags: ['Admin: Permissions'] + parameters: + - name: type + in: path + required: true + schema: + type: string + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [grant_scope] + properties: + grant_scope: + type: string + enum: [team_only, global, groups] + granted_groups: + type: array + items: + type: string + responses: + '200': + description: Grant updated + content: + application/json: + schema: + $ref: '#/components/schemas/ResourceGrant' + delete: + summary: Delete grant for a resource + operationId: adminDeleteGrant + tags: ['Admin: Permissions'] + parameters: + - name: type + in: path + required: true + schema: + type: string + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Storage + # ────────────────────────────────────────────── + /api/v1/admin/storage/status: + get: + summary: Get storage backend status + operationId: adminGetStorageStatus + tags: ['Admin: System'] + responses: + '200': + description: Storage status + content: + application/json: + schema: + type: object + properties: + backend: + type: string + configured: + type: boolean + healthy: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Vault + # ────────────────────────────────────────────── + /api/v1/admin/vault/status: + get: + summary: Get vault status + operationId: adminGetVaultStatus + tags: ['Admin: System'] + responses: + '200': + description: Vault status + content: + application/json: + schema: + type: object + + # ────────────────────────────────────────────── + # Admin: Email + # ────────────────────────────────────────────── + /api/v1/admin/notifications/test-email: + post: + summary: Send a test email + operationId: adminSendTestEmail + tags: ['Admin: System'] + responses: + '200': + description: Test email sent + content: + application/json: + schema: + type: object + properties: + ok: + type: boolean + sent_to: + type: string + + # ────────────────────────────────────────────── + # Admin: Extensions + # ────────────────────────────────────────────── + /api/v1/admin/extensions: + get: + summary: List all extensions (admin) + operationId: adminListExtensions + tags: ['Admin: Extensions'] + responses: + '200': + description: Extension list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Extension' + post: + summary: Register an extension (admin) + operationId: adminCreateExtension + tags: ['Admin: Extensions'] + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '201': + description: Extension registered + content: + application/json: + schema: + $ref: '#/components/schemas/Extension' + + /api/v1/admin/extensions/{id}: + put: + summary: Update an extension (admin) + operationId: adminUpdateExtension + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Updated + content: + application/json: + schema: + $ref: '#/components/schemas/Extension' + delete: + summary: Delete an extension (admin) + operationId: adminDeleteExtension + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Extension Permissions + # ────────────────────────────────────────────── + /api/v1/admin/extensions/{id}/permissions: + get: + summary: List permissions for an extension + operationId: adminListExtensionPermissions + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Extension permissions + content: + application/json: + schema: + type: object + + /api/v1/admin/extensions/{id}/review: + get: + summary: Get extension permission review + operationId: adminReviewExtensionPermissions + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Permission review + content: + application/json: + schema: + type: object + + /api/v1/admin/extensions/{id}/permissions/{perm}/grant: + post: + summary: Grant a permission to an extension + operationId: adminGrantExtensionPermission + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + - name: perm + in: path + required: true + schema: + type: string + responses: + '200': + description: Permission granted + content: + application/json: + schema: + type: object + + /api/v1/admin/extensions/{id}/permissions/{perm}/revoke: + post: + summary: Revoke a permission from an extension + operationId: adminRevokeExtensionPermission + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + - name: perm + in: path + required: true + schema: + type: string + responses: + '200': + description: Permission revoked + content: + application/json: + schema: + type: object + + /api/v1/admin/extensions/{id}/permissions/grant-all: + post: + summary: Grant all permissions to an extension + operationId: adminGrantAllExtensionPermissions + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: All permissions granted + content: + application/json: + schema: + type: object + + # ────────────────────────────────────────────── + # Admin: Extension Secrets + # ────────────────────────────────────────────── + /api/v1/admin/extensions/{id}/secrets: + get: + summary: Get extension secrets + operationId: adminGetExtensionSecrets + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Extension secrets + content: + application/json: + schema: + type: object + put: + summary: Update extension secrets + operationId: adminUpdateExtensionSecrets + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Secrets updated + content: + application/json: + schema: + type: object + delete: + summary: Delete extension secrets + operationId: adminDeleteExtensionSecrets + tags: ['Admin: Extensions'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Secrets deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + # ────────────────────────────────────────────── + # Admin: Packages + # ────────────────────────────────────────────── + /api/v1/admin/packages/registry: + get: + summary: List registry packages + operationId: adminListRegistryPackages + tags: ['Admin: Packages'] + responses: + '200': + description: Registry package list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + + /api/v1/admin/packages/registry/install: + post: + summary: Install a package from registry + operationId: adminInstallRegistryPackage + tags: ['Admin: Packages'] + requestBody: + required: true + content: + application/json: + schema: + type: object + required: [package_id] + properties: + package_id: + type: string + responses: + '201': + description: Package installed from registry + content: + application/json: + schema: + type: object + + /api/v1/admin/packages: + get: + summary: List all installed packages (admin) + operationId: adminListPackages + tags: ['Admin: Packages'] + responses: + '200': + description: Package list + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + $ref: '#/components/schemas/Package' + + /api/v1/admin/packages/{id}: + get: + summary: Get a package (admin) + operationId: adminGetPackage + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package detail + content: + application/json: + schema: + $ref: '#/components/schemas/Package' + delete: + summary: Delete a package (admin) + operationId: adminDeletePackage + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Deleted + content: + application/json: + schema: + type: object + properties: + deleted: + type: boolean + + /api/v1/admin/packages/install: + post: + summary: Install a package (admin, multipart) + operationId: adminInstallPackage + tags: ['Admin: Packages'] + requestBody: + required: true + content: + multipart/form-data: + schema: + type: object + properties: + file: + type: string + format: binary + responses: + '201': + description: Package installed + content: + application/json: + schema: + type: object + + /api/v1/admin/packages/{id}/enable: + put: + summary: Enable a package + operationId: adminEnablePackage + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package enabled + content: + application/json: + schema: + type: object + + /api/v1/admin/packages/{id}/disable: + put: + summary: Disable a package + operationId: adminDisablePackage + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package disabled + content: + application/json: + schema: + type: object + + /api/v1/admin/packages/{id}/settings: + get: + summary: Get package settings (admin) + operationId: adminGetPackageSettings + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package settings + content: + application/json: + schema: + type: object + put: + summary: Update package settings (admin) + operationId: adminUpdatePackageSettings + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Settings updated + content: + application/json: + schema: + type: object + + /api/v1/admin/packages/{id}/dependencies: + get: + summary: Get package dependencies + operationId: adminGetPackageDependencies + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package dependencies + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + + /api/v1/admin/packages/{id}/consumers: + get: + summary: Get package consumers + operationId: adminGetPackageConsumers + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Package consumers + content: + application/json: + schema: + type: object + properties: + data: + type: array + items: + type: object + + /api/v1/admin/packages/{id}/test-tool: + post: + summary: Test a package tool + operationId: adminTestPackageTool + tags: ['Admin: Packages'] + parameters: + - $ref: '#/components/parameters/idPath' + requestBody: + required: true + content: + application/json: + schema: + type: object + responses: + '200': + description: Tool test result + content: + application/json: + schema: + type: object + + /api/v1/admin/dependencies: + get: + summary: Get global dependency graph + operationId: adminGetDependencies + tags: ['Admin: Packages'] + responses: + '200': + description: Dependency graph + content: + application/json: + schema: + type: object + + # ────────────────────────────────────────────── + # Admin: Workflows + # ────────────────────────────────────────────── + /api/v1/admin/workflows/{id}/export: + get: + summary: Export a workflow as a zip archive + operationId: adminExportWorkflow + tags: ['Admin: Workflows'] + parameters: + - $ref: '#/components/parameters/idPath' + responses: + '200': + description: Workflow zip archive + content: + application/zip: + schema: + type: string + format: binary + '404': + description: Not found + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse'