{"openapi":"3.0.0","info":{"title":"FlowOS Risks Module API","version":"1.0.0","description":"Organization-scoped risk register: categories, risks, assessments, mitigations, comments, alerts, and platform entity-link integration. Secured routes require gateway-forwarded context (`Authorization`, `X-Organization-Id` or `X-Organization-Uuid`, optional `X-User-Uuid`, `X-Module-Permissions`).","contact":{"name":"ScrumDesk s r.o."}},"tags":[{"name":"Health","description":"Liveness and module identity"},{"name":"Admin","description":"Platform operator status and verification"},{"name":"Seed","description":"Development seeding (non-production)"},{"name":"Categories","description":"Hierarchical risk categories (leaf-only assignment for risks)"},{"name":"Risks","description":"Risk register CRUD and search"},{"name":"Assessments","description":"Risk assessments (score 0–100)"},{"name":"Mitigations","description":"Mitigation actions and status"},{"name":"Comments","description":"Discussion threads on a risk"},{"name":"Alerts","description":"Risk alerts and severity"},{"name":"Platform","description":"Entity link browse and batch resolve"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"FlowOS access token from `/api/auth/login` (+ org selection when required)."}},"parameters":{"OrganizationIdHeader":{"in":"header","name":"X-Organization-Id","schema":{"type":"string","format":"uuid"},"required":true,"description":"Active organization UUID (gateway forwards from session)."},"OrganizationUuidHeader":{"in":"header","name":"X-Organization-Uuid","schema":{"type":"string","format":"uuid"},"description":"Alternative org header accepted by the module."},"UserUuidHeader":{"in":"header","name":"X-User-Uuid","schema":{"type":"string","format":"uuid"},"description":"Required for posting comments (author identity)."},"RiskUuid":{"in":"path","name":"uuid","required":true,"schema":{"type":"string","format":"uuid"},"description":"Risk public identifier."},"NumericId":{"in":"path","name":"id","required":true,"schema":{"type":"integer"},"description":"Numeric primary key for nested child resources."},"CategoryUuid":{"in":"path","name":"uuid","required":true,"schema":{"type":"string","format":"uuid"},"description":"Category public identifier."},"TargetType":{"in":"path","name":"targetType","required":true,"schema":{"type":"string"},"description":"Entity link target type key (e.g. platform picker registry value)."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable error message"}}},"RiskCategoryRef":{"type":"object","nullable":true,"properties":{"uuid":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"RiskCategory":{"type":"object","properties":{"id":{"type":"integer","description":"Internal numeric id"},"uuid":{"type":"string","format":"uuid"},"name":{"type":"string"},"sortOrder":{"type":"integer"},"updatedAt":{"type":"string","format":"date-time"},"parentUuid":{"type":"string","format":"uuid","nullable":true},"childCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"}}},"RiskListItem":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string","example":"open"},"categoryId":{"type":"integer","nullable":true},"updatedAt":{"type":"string","format":"date-time"},"probabilityLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"impactLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"category":{"$ref":"#/components/schemas/RiskCategoryRef"},"latestAssessmentScore":{"type":"number","nullable":true}}},"RiskDetail":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string","nullable":true},"status":{"type":"string"},"category":{"$ref":"#/components/schemas/RiskCategoryRef"},"probabilityLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"impactLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"RiskCreateBody":{"type":"object","required":["title"],"properties":{"title":{"type":"string","minLength":1,"maxLength":512},"description":{"type":"string","maxLength":50000,"nullable":true},"status":{"type":"string","maxLength":32},"categoryUuid":{"type":"string","format":"uuid","nullable":true},"probabilityLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"impactLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true}}},"RiskPatchBody":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":512},"description":{"type":"string","maxLength":50000,"nullable":true},"status":{"type":"string","maxLength":32},"categoryUuid":{"type":"string","format":"uuid","nullable":true},"probabilityLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true},"impactLevel":{"type":"integer","minimum":1,"maximum":5,"nullable":true}}},"RiskAssessment":{"type":"object","properties":{"id":{"type":"integer"},"score":{"type":"integer","minimum":0,"maximum":100,"nullable":true},"notes":{"type":"string","nullable":true},"createdAt":{"type":"string","format":"date-time"}}},"RiskMitigation":{"type":"object","properties":{"id":{"type":"integer"},"title":{"type":"string"},"status":{"type":"string","example":"planned"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"RiskComment":{"type":"object","properties":{"id":{"type":"integer"},"body":{"type":"string"},"authorAccountUuid":{"type":"string","format":"uuid"},"createdAt":{"type":"string","format":"date-time"}}},"RiskAlert":{"type":"object","properties":{"id":{"type":"integer"},"message":{"type":"string"},"severity":{"type":"string","enum":["info","warning","critical"],"example":"info"},"createdAt":{"type":"string","format":"date-time"}}},"EntityBrowseItem":{"type":"object","properties":{"uuid":{"type":"string","format":"uuid"},"title":{"type":"string"},"subtitle":{"type":"string","nullable":true}}},"EntityResolveRef":{"type":"object","required":["entityType","entityUuid"],"properties":{"entityType":{"type":"string","example":"risks.risk"},"entityUuid":{"type":"string","format":"uuid"}}},"EntityResolveResult":{"type":"object","properties":{"entityType":{"type":"string"},"entityUuid":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["resolved","unresolved"]},"title":{"type":"string"},"subtitle":{"type":"string"},"navigationPathAfterLocale":{"type":"string"},"navigationTargetUuid":{"type":"string","format":"uuid"}}}}},"security":[{"bearerAuth":[]}],"paths":{"/entity-link/browse-targets/{targetType}":{"get":{"summary":"Browse link targets for RelationsEditor","description":"Returns picker rows for the given target type (aligned with flowos-app entity-link registry).","tags":["Platform"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/TargetType"},{"in":"query","name":"q","schema":{"type":"string"},"description":"Optional search filter"},{"in":"query","name":"limit","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/EntityBrowseItem"}}}}}}}}}},"/entity-resolve":{"post":{"summary":"Batch-resolve entity references","description":"Resolves up to 100 `{ entityType, entityUuid }` refs for cross-module labels and deep links.","tags":["Platform"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["refs"],"properties":{"refs":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/EntityResolveRef"}}}}}}},"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/EntityResolveResult"}}}}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/{uuid}/assessments":{"get":{"summary":"List assessments for a risk","tags":["Assessments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RiskAssessment"}}}}}}}}},"post":{"summary":"Create assessment","tags":["Assessments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100,"nullable":true},"notes":{"type":"string","nullable":true}}}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskAssessment"}}}}}}},"/{uuid}/assessments/{id}":{"patch":{"summary":"Update assessment","tags":["Assessments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100,"nullable":true},"notes":{"type":"string","nullable":true}}}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskAssessment"}}}}}},"delete":{"summary":"Delete assessment","tags":["Assessments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"responses":{"204":{"description":"Deleted"}}}},"/{uuid}/mitigations":{"get":{"summary":"List mitigations","tags":["Mitigations"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RiskMitigation"}}}}}}}}},"post":{"summary":"Create mitigation","tags":["Mitigations"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title"],"properties":{"title":{"type":"string"},"status":{"type":"string","example":"planned"}}}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskMitigation"}}}}}}},"/{uuid}/mitigations/{id}":{"patch":{"summary":"Update mitigation","tags":["Mitigations"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskMitigation"}}}}}},"delete":{"summary":"Delete mitigation","tags":["Mitigations"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"responses":{"204":{"description":"Deleted"}}}},"/{uuid}/comments":{"get":{"summary":"List comments","tags":["Comments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RiskComment"}}}}}}}}},"post":{"summary":"Add comment","description":"Requires `X-User-Uuid` for author identity.","tags":["Comments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/UserUuidHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["body"],"properties":{"body":{"type":"string"}}}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskComment"}}}},"403":{"description":"Missing user identity"}}}},"/{uuid}/comments/{id}":{"patch":{"summary":"Edit comment body","tags":["Comments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskComment"}}}}}},"delete":{"summary":"Delete comment","tags":["Comments"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"responses":{"204":{"description":"Deleted"}}}},"/{uuid}/alerts":{"get":{"summary":"List alerts","tags":["Alerts"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RiskAlert"}}}}}}}}},"post":{"summary":"Create alert","tags":["Alerts"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"type":"string"},"severity":{"type":"string","enum":["info","warning","critical"]}}}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskAlert"}}}}}}},"/{uuid}/alerts/{id}":{"delete":{"summary":"Delete alert","tags":["Alerts"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"},{"$ref":"#/components/parameters/NumericId"}],"responses":{"204":{"description":"Deleted"}}}},"/health":{"get":{"summary":"Module health check","description":"Unauthenticated liveness probe used by Docker and the gateway.","tags":["Health"],"security":[],"responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"flowos-risks"},"timestamp":{"type":"string","format":"date-time"}}}}}}}}},"/admin/status":{"get":{"summary":"Admin status (database connectivity)","tags":["Admin"],"security":[],"responses":{"200":{"description":"ok or degraded","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"]},"service":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/admin/verify":{"post":{"summary":"Admin verify hook","tags":["Admin"],"security":[],"responses":{"200":{"description":"Verification succeeded","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"service":{"type":"string"}}}}}}}}},"/seed":{"post":{"summary":"Seed module data (dev)","tags":["Seed"],"security":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"organizationUuids":{"type":"array","items":{"type":"string","format":"uuid"}}}}}}},"responses":{"200":{"description":"Seed completed"}}}},"/seed-cleanup":{"post":{"summary":"Remove seeded data (dev)","tags":["Seed"],"security":[],"responses":{"200":{"description":"Cleanup completed"}}}},"/categories":{"get":{"summary":"List risk categories","description":"Returns the full category tree for the active organization, ordered by sortOrder and name.","tags":["Categories"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"}],"responses":{"200":{"description":"Category list","content":{"application/json":{"schema":{"type":"object","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/RiskCategory"}}}}}}},"403":{"description":"Missing risks:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Create category","tags":["Categories"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string"},"sortOrder":{"type":"integer"},"parentUuid":{"type":"string","format":"uuid","nullable":true}}}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskCategory"}}}},"422":{"description":"Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/categories/{uuid}":{"get":{"summary":"Get category by UUID","tags":["Categories"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/CategoryUuid"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskCategory"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update category","tags":["Categories"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/CategoryUuid"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string"},"sortOrder":{"type":"integer"},"parentUuid":{"type":"string","format":"uuid","nullable":true}}}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskCategory"}}}}}},"delete":{"summary":"Delete category","tags":["Categories"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/CategoryUuid"}],"responses":{"204":{"description":"Deleted"},"409":{"description":"Category in use or has children","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/":{"get":{"summary":"List risks (paginated, searchable)","description":"Organization-scoped register with optional full-text filter on title and description.","tags":["Risks"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"in":"query","name":"q","schema":{"type":"string"},"description":"Case-insensitive search on title and description"},{"in":"query","name":"skip","schema":{"type":"integer","minimum":0,"default":0}},{"in":"query","name":"take","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"total":{"type":"integer"},"items":{"type":"array","items":{"$ref":"#/components/schemas/RiskListItem"}}}}}}}}},"post":{"summary":"Create risk","description":"Assigns category by UUID; category must be a leaf (no subcategories).","tags":["Risks"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskCreateBody"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskDetail"}}}},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/{uuid}":{"get":{"summary":"Get risk by UUID","tags":["Risks"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskDetail"}}}},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"summary":"Update risk","tags":["Risks"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskPatchBody"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RiskDetail"}}}}}},"delete":{"summary":"Delete risk","tags":["Risks"],"parameters":[{"$ref":"#/components/parameters/OrganizationIdHeader"},{"$ref":"#/components/parameters/RiskUuid"}],"responses":{"204":{"description":"Deleted"}}}}},"servers":[{"url":"https://flowos.scrumdesk.com/api/risks","description":"Production (third parties — use in Postman)"},{"url":"http://localhost:3007/api/risks","description":"Local module backend (direct on module port)"}]}