306 lines
10 KiB
YAML
306 lines
10 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: user-engine portal API
|
|
version: 0.2.0
|
|
servers:
|
|
- url: /api/v1
|
|
security:
|
|
- verifiedOidc: []
|
|
paths:
|
|
/me:
|
|
get:
|
|
operationId: currentUser
|
|
responses:
|
|
"200":
|
|
description: Current user and linked identities
|
|
"403":
|
|
$ref: "#/components/responses/Denied"
|
|
/me/profile:
|
|
patch:
|
|
operationId: updateCurrentUserProfile
|
|
description: Updates display name and versioned consent; verified email cannot be changed here.
|
|
parameters: [{$ref: "#/components/parameters/IdempotencyKey"}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: "#/components/schemas/UpdateSelfProfile"}
|
|
responses:
|
|
"200": {description: Durable self-service profile state}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
/registrations:
|
|
post:
|
|
operationId: startRegistration
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"201":
|
|
description: Registration started
|
|
"403":
|
|
$ref: "#/components/responses/Denied"
|
|
/registrations/{registrationId}/complete:
|
|
post:
|
|
operationId: completeRegistration
|
|
parameters:
|
|
- name: registrationId
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"200":
|
|
description: Registration completed
|
|
"400":
|
|
description: Missing verified factors or invalid state
|
|
/tenants/{tenant}/users:
|
|
get:
|
|
operationId: listTenantUsers
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- {name: offset, in: query, schema: {type: integer, minimum: 0}}
|
|
- {name: limit, in: query, schema: {type: integer, minimum: 1, maximum: 100}}
|
|
responses:
|
|
"200": {description: Tenant-scoped memberships}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
post:
|
|
operationId: createTenantUser
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: "#/components/schemas/CreateUser"}
|
|
responses:
|
|
"201": {description: Tenant user and membership created}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
/tenants/{tenant}/users/{userId}:
|
|
patch:
|
|
operationId: updateTenantUserLifecycle
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- name: userId
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"200": {description: Tenant account updated}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
delete:
|
|
operationId: removeTenantUser
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- $ref: "#/components/parameters/UserId"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"200": {description: Login deprovisioned and tenant account disabled}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
/tenants/{tenant}/invitations:
|
|
get:
|
|
operationId: listInvitations
|
|
parameters: [{$ref: "#/components/parameters/Tenant"}]
|
|
responses:
|
|
"200": {description: Tenant invitations}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
post:
|
|
operationId: createInvitation
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: "#/components/schemas/CreateInvitation"}
|
|
responses:
|
|
"201": {description: Invitation created with an expiry and version}
|
|
"409": {$ref: "#/components/responses/Conflict"}
|
|
/tenants/{tenant}/invitations/{invitationId}/resend:
|
|
post:
|
|
operationId: resendInvitation
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- $ref: "#/components/parameters/InvitationId"
|
|
- $ref: "#/components/parameters/IfMatch"
|
|
responses:
|
|
"200": {description: Invitation expiry renewed and version advanced}
|
|
"409": {$ref: "#/components/responses/Conflict"}
|
|
/tenants/{tenant}/invitations/{invitationId}/expire:
|
|
post:
|
|
operationId: expireInvitation
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- $ref: "#/components/parameters/InvitationId"
|
|
- $ref: "#/components/parameters/IfMatch"
|
|
responses:
|
|
"200": {description: Invitation revoked}
|
|
"409": {$ref: "#/components/responses/Conflict"}
|
|
/invitations/{invitationId}/claim:
|
|
post:
|
|
operationId: claimInvitation
|
|
parameters:
|
|
- $ref: "#/components/parameters/InvitationId"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"200": {description: Invitation claimed and identity linked}
|
|
"400": {description: Invitation expired, revoked, or already claimed}
|
|
/onboarding/{journeyId}/steps/{stepKey}/complete:
|
|
post:
|
|
operationId: completeOnboardingStep
|
|
description: Completes an active user-engine-owned step. Provider-owned steps must use their external handoff and callback.
|
|
parameters:
|
|
- name: journeyId
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
- name: stepKey
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"200": {description: Updated resumable onboarding journey}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
"404": {description: Journey is absent or belongs to another user}
|
|
/platform/tenants:
|
|
post:
|
|
operationId: createPlatformTenant
|
|
description: Creates a tenant through the configured tenant authority and optionally prepares its first administrator.
|
|
parameters: [{$ref: "#/components/parameters/IdempotencyKey"}]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: {$ref: "#/components/schemas/CreateTenant"}
|
|
responses:
|
|
"201": {description: Tenant created or resumed and first administrator prepared}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
/platform/tenants/{tenant}/users/{userId}/recover:
|
|
post:
|
|
operationId: recoverTenantUser
|
|
description: Reconciles or recreates the provider identity and activates the tenant account without exposing provider credentials.
|
|
parameters:
|
|
- $ref: "#/components/parameters/Tenant"
|
|
- $ref: "#/components/parameters/UserId"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
responses:
|
|
"200": {description: Redacted recovery outcome}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
/platform/outbox/deliver:
|
|
post:
|
|
operationId: deliverOutbox
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
worker_id: {type: string}
|
|
max_attempts: {type: integer, minimum: 1, maximum: 20}
|
|
additionalProperties: false
|
|
responses:
|
|
"200": {description: Bounded delivery results}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
/platform/outbox/{eventId}/replay:
|
|
post:
|
|
operationId: replayOutboxEvent
|
|
parameters:
|
|
- name: eventId
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
responses:
|
|
"200": {description: Event returned to pending delivery}
|
|
"403": {$ref: "#/components/responses/Denied"}
|
|
components:
|
|
securitySchemes:
|
|
verifiedOidc:
|
|
type: openIdConnect
|
|
openIdConnectUrl: https://kc.coulomb.social/.well-known/openid-configuration
|
|
parameters:
|
|
Tenant:
|
|
name: tenant
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
required: true
|
|
schema: {type: string, minLength: 16, maxLength: 200}
|
|
UserId:
|
|
name: userId
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
InvitationId:
|
|
name: invitationId
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
IfMatch:
|
|
name: If-Match
|
|
in: header
|
|
required: true
|
|
schema: {type: string, pattern: '^"?[0-9]+"?$'}
|
|
schemas:
|
|
CreateUser:
|
|
type: object
|
|
required: [primary_email, role]
|
|
properties:
|
|
primary_email: {type: string, format: email}
|
|
display_name: {type: string, maxLength: 200}
|
|
role: {type: string, enum: [user, tenant-admin]}
|
|
additionalProperties: false
|
|
CreateInvitation:
|
|
type: object
|
|
required: [primary_email]
|
|
properties:
|
|
primary_email: {type: string, format: email}
|
|
display_name: {type: string, maxLength: 200}
|
|
role: {type: string, enum: [user, tenant-admin]}
|
|
application_id: {type: string}
|
|
scope_id: {type: string}
|
|
additionalProperties: false
|
|
CreateTenant:
|
|
type: object
|
|
required: [tenant, display_name]
|
|
properties:
|
|
tenant: {type: string, pattern: '^tenant:'}
|
|
display_name: {type: string, minLength: 1, maxLength: 200}
|
|
first_admin:
|
|
type: object
|
|
required: [primary_email]
|
|
properties:
|
|
primary_email: {type: string, format: email}
|
|
display_name: {type: string, maxLength: 200}
|
|
additionalProperties: false
|
|
additionalProperties: false
|
|
UpdateSelfProfile:
|
|
type: object
|
|
required: [display_name, consent_accepted, consent_version]
|
|
properties:
|
|
display_name: {type: string, minLength: 1, maxLength: 200}
|
|
consent_accepted: {type: boolean}
|
|
consent_version: {type: string, minLength: 1, maxLength: 100}
|
|
additionalProperties: false
|
|
Error:
|
|
type: object
|
|
required: [error, message, correlation_id]
|
|
properties:
|
|
error: {type: string}
|
|
message: {type: string}
|
|
correlation_id: {type: string}
|
|
responses:
|
|
Denied:
|
|
description: Caller is unauthenticated or unauthorized
|
|
content:
|
|
application/json:
|
|
schema: {$ref: "#/components/schemas/Error"}
|
|
Conflict:
|
|
description: Optimistic concurrency or uniqueness conflict
|
|
content:
|
|
application/json:
|
|
schema: {$ref: "#/components/schemas/Error"}
|