{
  "openapi": "3.1.0",
  "info": {
    "title": "RSX Projects",
    "version": "v1",
    "description": "RSX's internal project and work management system: projects, work items, roadmaps, specifications, and the activity behind them."
  },
  "servers": [
    {
      "url": "https://api.rsx.group"
    }
  ],
  "components": {
    "schemas": {
      "PurgeResult": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "slug": {
            "type": "string"
          },
          "deleted": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "example": {
              "work_items": 42,
              "specifications": 3,
              "activity": 118
            }
          }
        },
        "required": [
          "id",
          "slug",
          "deleted"
        ]
      },
      "Problem": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string",
            "example": "https://docs.rsx.group/errors/not-found"
          },
          "title": {
            "type": "string",
            "example": "Not found"
          },
          "status": {
            "type": "integer",
            "example": 404
          },
          "detail": {
            "type": "string"
          },
          "instance": {
            "type": "string",
            "example": "/access/v1/installations/get"
          },
          "requestId": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "title",
          "status"
        ]
      },
      "PurgeProject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "confirm": {
            "type": "string",
            "example": "rsx-node"
          }
        },
        "required": [
          "id",
          "confirm"
        ]
      },
      "Label": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "example": null
          },
          "name": {
            "type": "string",
            "example": "security"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "createdAt"
        ]
      },
      "AdminCreateLabel": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 48,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "needs-review"
          }
        },
        "required": [
          "name"
        ]
      },
      "UpdateLabel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 48,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "needs-review"
          }
        },
        "required": [
          "id",
          "name"
        ]
      },
      "RemoveLabel": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "ProjectsAdminAuditEvent": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "018f3b1c-9a2e-7c31-8f4d-2a6b5c7e9d12"
          },
          "actor": {
            "type": "string",
            "example": "ops@rsx.group"
          },
          "action": {
            "type": "string",
            "enum": [
              "project.purged",
              "label.added",
              "label.updated",
              "label.removed"
            ]
          },
          "targetType": {
            "type": "string",
            "enum": [
              "project",
              "label"
            ]
          },
          "targetId": {
            "type": "string"
          },
          "targetLabel": {
            "type": [
              "string",
              "null"
            ]
          },
          "at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-12T10:16:30.000Z"
          },
          "detail": {
            "type": [
              "string",
              "null"
            ]
          }
        },
        "required": [
          "id",
          "actor",
          "action",
          "targetType",
          "targetId",
          "targetLabel",
          "at",
          "detail"
        ]
      },
      "PublishedDocument": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "collection": {
            "type": "string",
            "enum": [
              "guides",
              "products",
              "support"
            ],
            "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
            "example": "guides"
          },
          "section": {
            "type": [
              "string",
              "null"
            ]
          },
          "position": {
            "type": "integer"
          },
          "title": {
            "type": "string"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ]
          },
          "content": {
            "type": "string"
          },
          "publishedVersion": {
            "type": "integer",
            "exclusiveMinimum": 0
          },
          "publishedAt": {
            "type": "string",
            "format": "date-time"
          },
          "revisedAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "slug",
          "collection",
          "section",
          "position",
          "title",
          "summary",
          "content",
          "publishedVersion",
          "publishedAt",
          "revisedAt"
        ]
      },
      "Project": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "name": {
            "type": "string",
            "example": "RSX Node"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "example": "Control plane for RSX-managed compute."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed"
            ],
            "example": "active"
          },
          "ownerId": {
            "type": "string",
            "format": "uuid",
            "description": "The account answerable for the project. Also holds an 'owner' membership row.",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "builtin": {
            "type": "boolean",
            "description": "A platform project such as 'docs'. Cannot be archived or purged; every staff account may write in it.",
            "example": false
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "archivedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Set when the project is archived. An archived project is read only.",
            "example": null
          }
        },
        "required": [
          "id",
          "slug",
          "name",
          "description",
          "status",
          "ownerId",
          "builtin",
          "createdAt",
          "updatedAt",
          "archivedAt"
        ]
      },
      "CreateProject": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "example": "RSX Node"
          },
          "description": {
            "type": "string",
            "maxLength": 2000,
            "example": "Control plane for RSX-managed compute."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed"
            ],
            "description": "Defaults to 'active'.",
            "example": "active"
          }
        },
        "required": [
          "slug",
          "name"
        ]
      },
      "ProjectsPageMeta": {
        "type": "object",
        "properties": {
          "cursor": {
            "type": [
              "string",
              "null"
            ],
            "example": null
          }
        },
        "required": [
          "cursor"
        ]
      },
      "UpdateProject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed"
            ],
            "example": "active"
          }
        },
        "required": [
          "id"
        ]
      },
      "RemoveProject": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "ProjectMember": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "maintainer",
              "contributor",
              "reader"
            ],
            "description": "owner: everything, including archiving and changing owners. maintainer: manage members, labels, milestones and lifecycle. contributor: create and edit content. reader: an explicit watcher, granting no writes.",
            "example": "contributor"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "projectId",
          "accountId",
          "role",
          "createdAt"
        ]
      },
      "AddProjectMember": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "maintainer",
              "contributor",
              "reader"
            ],
            "description": "owner: everything, including archiving and changing owners. maintainer: manage members, labels, milestones and lifecycle. contributor: create and edit content. reader: an explicit watcher, granting no writes.",
            "example": "contributor"
          }
        },
        "required": [
          "projectId",
          "accountId",
          "role"
        ]
      },
      "UpdateProjectMember": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "role": {
            "type": "string",
            "enum": [
              "owner",
              "maintainer",
              "contributor",
              "reader"
            ],
            "description": "owner: everything, including archiving and changing owners. maintainer: manage members, labels, milestones and lifecycle. contributor: create and edit content. reader: an explicit watcher, granting no writes.",
            "example": "contributor"
          }
        },
        "required": [
          "projectId",
          "accountId",
          "role"
        ]
      },
      "RemoveProjectMember": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "accountId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          }
        },
        "required": [
          "projectId",
          "accountId"
        ]
      },
      "ProjectActivity": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "actorId": {
            "type": "string",
            "description": "An RSX account id when actorType is 'account', an API key id when it is 'key'.",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "actorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "entityType": {
            "type": "string",
            "enum": [
              "project",
              "work",
              "specification",
              "document",
              "milestone",
              "member",
              "comment"
            ],
            "example": "work"
          },
          "entityId": {
            "type": "string",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "action": {
            "type": "string",
            "example": "created"
          },
          "metadata": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": {},
            "example": null
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "projectId",
          "actorId",
          "actorType",
          "entityType",
          "entityId",
          "action",
          "metadata",
          "createdAt"
        ]
      },
      "WorkSpecificationLink": {
        "type": "object",
        "properties": {
          "specificationId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "relationship": {
            "type": "string",
            "enum": [
              "governed_by",
              "implements",
              "references"
            ],
            "example": "governed_by"
          }
        },
        "required": [
          "specificationId",
          "relationship"
        ]
      },
      "WorkItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "number": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 142
          },
          "type": {
            "type": "string",
            "enum": [
              "task",
              "bug",
              "work_order",
              "idea"
            ],
            "example": "task"
          },
          "title": {
            "type": "string",
            "example": "Implement container runtime"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "example": null
          },
          "status": {
            "type": "string",
            "enum": [
              "backlog",
              "planned",
              "in_progress",
              "blocked",
              "review",
              "done",
              "cancelled"
            ],
            "example": "planned"
          },
          "priority": {
            "type": "string",
            "enum": [
              "none",
              "low",
              "normal",
              "high",
              "critical"
            ],
            "description": "Defaults to 'none'. The roadmap bucket expresses urgency.",
            "example": "none"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "none",
              "now",
              "next",
              "later",
              "someday"
            ],
            "description": "Roadmap placement. 'none' is not on the roadmap.",
            "example": "next"
          },
          "creatorId": {
            "type": "string",
            "description": "An RSX account id when creatorType is 'account', an API key id when it is 'key'.",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "creatorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "assigneeIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "example": []
          },
          "labelIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "example": []
          },
          "specifications": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkSpecificationLink"
            },
            "example": []
          },
          "milestoneId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "example": null
          },
          "dueAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "completedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          },
          "archivedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          }
        },
        "required": [
          "id",
          "projectId",
          "number",
          "type",
          "title",
          "description",
          "status",
          "priority",
          "bucket",
          "creatorId",
          "creatorType",
          "assigneeIds",
          "labelIds",
          "specifications",
          "milestoneId",
          "dueAt",
          "createdAt",
          "updatedAt",
          "completedAt",
          "archivedAt"
        ]
      },
      "CreateWorkItem": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "type": {
            "type": "string",
            "enum": [
              "task",
              "bug",
              "work_order",
              "idea"
            ],
            "example": "task"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "example": "Implement container runtime"
          },
          "description": {
            "type": "string",
            "maxLength": 50000
          },
          "status": {
            "type": "string",
            "enum": [
              "backlog",
              "planned",
              "in_progress",
              "blocked",
              "review",
              "done",
              "cancelled"
            ],
            "description": "Defaults to 'backlog'.",
            "example": "planned"
          },
          "priority": {
            "type": "string",
            "enum": [
              "none",
              "low",
              "normal",
              "high",
              "critical"
            ],
            "description": "Defaults to 'none'.",
            "example": "none"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "none",
              "now",
              "next",
              "later",
              "someday"
            ],
            "description": "Defaults to 'none'.",
            "example": "next"
          },
          "assigneeIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "maxItems": 20
          },
          "labelIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "maxItems": 50
          },
          "specifications": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkSpecificationLink"
            },
            "maxItems": 20
          },
          "milestoneId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "dueAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "projectId",
          "type",
          "title"
        ]
      },
      "UpdateWorkItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "type": {
            "type": "string",
            "enum": [
              "task",
              "bug",
              "work_order",
              "idea"
            ],
            "example": "task"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 50000
          },
          "status": {
            "type": "string",
            "enum": [
              "backlog",
              "planned",
              "in_progress",
              "blocked",
              "review",
              "done",
              "cancelled"
            ],
            "example": "planned"
          },
          "priority": {
            "type": "string",
            "enum": [
              "none",
              "low",
              "normal",
              "high",
              "critical"
            ],
            "description": "Defaults to 'none'. The roadmap bucket expresses urgency.",
            "example": "none"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "none",
              "now",
              "next",
              "later",
              "someday"
            ],
            "description": "Roadmap placement. 'none' is not on the roadmap.",
            "example": "next"
          },
          "assigneeIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "maxItems": 20
          },
          "labelIds": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "maxItems": 50
          },
          "specifications": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WorkSpecificationLink"
            },
            "maxItems": 20
          },
          "milestoneId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "dueAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id"
        ]
      },
      "RemoveWorkItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "WorkRelationship": {
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "targetId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "relationship": {
            "type": "string",
            "enum": [
              "blocks",
              "related_to",
              "duplicates",
              "supersedes"
            ],
            "example": "blocks"
          },
          "createdBy": {
            "type": "string",
            "format": "uuid",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "sourceId",
          "targetId",
          "relationship",
          "createdBy",
          "createdAt"
        ]
      },
      "AddWorkRelationship": {
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "targetId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "relationship": {
            "type": "string",
            "enum": [
              "blocks",
              "depends_on",
              "related_to",
              "duplicates",
              "supersedes"
            ],
            "description": "blocks and supersedes are directional. related_to and duplicates are symmetric and stored once. depends_on is accepted and normalised to a blocks row in the opposite direction.",
            "example": "blocks"
          }
        },
        "required": [
          "sourceId",
          "targetId",
          "relationship"
        ]
      },
      "RemoveWorkRelationship": {
        "type": "object",
        "properties": {
          "sourceId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "targetId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "relationship": {
            "type": "string",
            "enum": [
              "blocks",
              "depends_on",
              "related_to",
              "duplicates",
              "supersedes"
            ],
            "description": "blocks and supersedes are directional. related_to and duplicates are symmetric and stored once. depends_on is accepted and normalised to a blocks row in the opposite direction.",
            "example": "blocks"
          }
        },
        "required": [
          "sourceId",
          "targetId",
          "relationship"
        ]
      },
      "CreateLabel": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 48,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "needs-review"
          }
        },
        "required": [
          "name"
        ]
      },
      "Milestone": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "name": {
            "type": "string",
            "example": "Container runtime"
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "example": null
          },
          "status": {
            "type": "string",
            "enum": [
              "planned",
              "active",
              "completed",
              "cancelled"
            ],
            "example": "planned"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "none",
              "now",
              "next",
              "later",
              "someday"
            ],
            "description": "Roadmap placement. 'none' is not on the roadmap.",
            "example": "next"
          },
          "targetAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "archivedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          }
        },
        "required": [
          "id",
          "projectId",
          "name",
          "description",
          "status",
          "bucket",
          "targetAt",
          "createdAt",
          "updatedAt",
          "archivedAt"
        ]
      },
      "CreateMilestone": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120,
            "example": "Container runtime"
          },
          "description": {
            "type": "string",
            "maxLength": 10000
          },
          "status": {
            "type": "string",
            "enum": [
              "planned",
              "active",
              "completed",
              "cancelled"
            ],
            "description": "Defaults to 'planned'.",
            "example": "planned"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "none",
              "now",
              "next",
              "later",
              "someday"
            ],
            "description": "Defaults to 'none'.",
            "example": "next"
          },
          "targetAt": {
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "projectId",
          "name"
        ]
      },
      "UpdateMilestone": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 120
          },
          "description": {
            "type": "string",
            "maxLength": 10000
          },
          "status": {
            "type": "string",
            "enum": [
              "planned",
              "active",
              "completed",
              "cancelled"
            ],
            "example": "planned"
          },
          "bucket": {
            "type": "string",
            "enum": [
              "none",
              "now",
              "next",
              "later",
              "someday"
            ],
            "description": "Roadmap placement. 'none' is not on the roadmap.",
            "example": "next"
          },
          "targetAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        },
        "required": [
          "id"
        ]
      },
      "RemoveMilestone": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "Specification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "example": "Container Applications"
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "review",
              "approved",
              "implemented",
              "superseded"
            ],
            "example": "draft"
          },
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 3
          },
          "content": {
            "type": "string",
            "example": "# Container Applications\n\n..."
          },
          "creatorId": {
            "type": "string",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "creatorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "supersededAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          },
          "supersededBy": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "example": null
          },
          "archivedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          }
        },
        "required": [
          "id",
          "projectId",
          "title",
          "slug",
          "status",
          "version",
          "content",
          "creatorId",
          "creatorType",
          "createdAt",
          "updatedAt",
          "supersededAt",
          "supersededBy",
          "archivedAt"
        ]
      },
      "CreateSpecification": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "example": "Container Applications"
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "content": {
            "type": "string",
            "maxLength": 500000,
            "example": "# Container Applications\n\n..."
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "review",
              "approved",
              "implemented",
              "superseded"
            ],
            "description": "Defaults to 'draft'.",
            "example": "draft"
          },
          "summary": {
            "type": "string",
            "maxLength": 500,
            "description": "Recorded on revision 1."
          }
        },
        "required": [
          "projectId",
          "title",
          "slug",
          "content"
        ]
      },
      "UpdateSpecification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "content": {
            "type": "string",
            "maxLength": 500000
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "review",
              "approved",
              "implemented"
            ],
            "description": "Use specifications/supersede to retire one."
          },
          "summary": {
            "type": "string",
            "maxLength": 500,
            "description": "What changed, recorded on the revision this save creates."
          }
        },
        "required": [
          "id"
        ]
      },
      "SupersedeSpecification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "supersededBy": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "summary": {
            "type": "string",
            "maxLength": 500
          }
        },
        "required": [
          "id",
          "supersededBy"
        ]
      },
      "RemoveSpecification": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "SpecificationRevision": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "specificationId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 2
          },
          "title": {
            "type": "string",
            "example": "Container Applications"
          },
          "content": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "review",
              "approved",
              "implemented",
              "superseded"
            ],
            "example": "draft"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "example": "Added the storage section."
          },
          "authorId": {
            "type": "string",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "authorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "specificationId",
          "version",
          "title",
          "content",
          "status",
          "summary",
          "authorId",
          "authorType",
          "createdAt"
        ]
      },
      "Document": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "example": "Restoring a node"
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "type": {
            "type": "string",
            "enum": [
              "rfc",
              "runbook",
              "note",
              "design"
            ],
            "example": "runbook"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "example": null
          },
          "content": {
            "type": "string"
          },
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 3
          },
          "collection": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "guides",
              "products",
              "support"
            ],
            "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
            "example": null
          },
          "section": {
            "type": [
              "string",
              "null"
            ],
            "example": null
          },
          "position": {
            "type": "integer",
            "example": 0
          },
          "publishedVersion": {
            "type": [
              "integer",
              "null"
            ],
            "exclusiveMinimum": 0,
            "example": null
          },
          "publishedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          },
          "creatorId": {
            "type": "string",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "creatorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "archivedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          }
        },
        "required": [
          "id",
          "projectId",
          "title",
          "slug",
          "type",
          "summary",
          "content",
          "version",
          "collection",
          "section",
          "position",
          "publishedVersion",
          "publishedAt",
          "creatorId",
          "creatorType",
          "createdAt",
          "updatedAt",
          "archivedAt"
        ]
      },
      "CreateDocument": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "example": "Restoring a node"
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "type": {
            "type": "string",
            "enum": [
              "rfc",
              "runbook",
              "note",
              "design"
            ],
            "example": "runbook"
          },
          "content": {
            "type": "string",
            "maxLength": 500000
          },
          "summary": {
            "type": "string",
            "maxLength": 300,
            "description": "One line, for registers and navigation. Not the first paragraph.",
            "example": "Auth, rate limits, errors, idempotency and pagination, once."
          },
          "collection": {
            "type": "string",
            "enum": [
              "guides",
              "products",
              "support"
            ],
            "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
            "example": "guides"
          },
          "section": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80,
            "description": "A group within the collection, by exact name. A product's documentation uses the product's name.",
            "example": "RSX Node"
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Order within the section, lowest first. Ties fall back to the title.",
            "example": 10
          }
        },
        "required": [
          "projectId",
          "title",
          "slug",
          "type",
          "content"
        ]
      },
      "UpdateDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "type": {
            "type": "string",
            "enum": [
              "rfc",
              "runbook",
              "note",
              "design"
            ],
            "example": "runbook"
          },
          "content": {
            "type": "string",
            "maxLength": 500000
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 300,
            "description": "One line, for registers and navigation. Not the first paragraph.",
            "example": "Auth, rate limits, errors, idempotency and pagination, once."
          },
          "collection": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "guides",
              "products",
              "support"
            ],
            "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
            "example": "guides"
          },
          "section": {
            "type": [
              "string",
              "null"
            ],
            "minLength": 1,
            "maxLength": 80,
            "description": "A group within the collection, by exact name. A product's documentation uses the product's name.",
            "example": "RSX Node"
          },
          "position": {
            "type": "integer",
            "minimum": 0,
            "maximum": 10000,
            "description": "Order within the section, lowest first. Ties fall back to the title.",
            "example": 10
          },
          "note": {
            "type": "string",
            "maxLength": 300,
            "description": "What changed, in the author's words. Stored on the revision.",
            "example": "Corrected the rate-limit figures."
          }
        },
        "required": [
          "id"
        ]
      },
      "RemoveDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "PublishDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "description": "The revision to publish. Omitted means the current head.",
            "example": 2
          }
        },
        "required": [
          "id"
        ]
      },
      "UnpublishDocument": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "DocumentRevision": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "documentId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "version": {
            "type": "integer",
            "exclusiveMinimum": 0,
            "example": 2
          },
          "title": {
            "type": "string",
            "example": "Restoring a node"
          },
          "summary": {
            "type": [
              "string",
              "null"
            ],
            "example": null
          },
          "content": {
            "type": "string"
          },
          "note": {
            "type": [
              "string",
              "null"
            ],
            "example": "Corrected the rate-limit figures."
          },
          "authorId": {
            "type": "string",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "authorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "documentId",
          "version",
          "title",
          "summary",
          "content",
          "note",
          "authorId",
          "authorType",
          "createdAt"
        ]
      },
      "Comment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "entityType": {
            "type": "string",
            "enum": [
              "work",
              "specification",
              "document"
            ],
            "example": "specification"
          },
          "entityId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "authorId": {
            "type": "string",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "authorType": {
            "type": "string",
            "enum": [
              "account",
              "key"
            ],
            "example": "account"
          },
          "content": {
            "type": "string",
            "example": "This needs a section on rollback."
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          },
          "deletedAt": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "example": null
          }
        },
        "required": [
          "id",
          "entityType",
          "entityId",
          "projectId",
          "authorId",
          "authorType",
          "content",
          "createdAt",
          "updatedAt",
          "deletedAt"
        ]
      },
      "AddComment": {
        "type": "object",
        "properties": {
          "entityType": {
            "type": "string",
            "enum": [
              "work",
              "specification",
              "document"
            ],
            "example": "specification"
          },
          "entityId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50000
          }
        },
        "required": [
          "entityType",
          "entityId",
          "content"
        ]
      },
      "UpdateComment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50000
          }
        },
        "required": [
          "id",
          "content"
        ]
      },
      "RemoveComment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "ExternalReference": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "entityType": {
            "type": "string",
            "enum": [
              "project",
              "work",
              "specification",
              "document",
              "milestone",
              "member",
              "comment"
            ],
            "example": "work"
          },
          "entityId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "label": {
            "type": "string",
            "example": "Pull request #482"
          },
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://github.com/rsx/node/pull/482"
          },
          "createdBy": {
            "type": "string",
            "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "example": "2026-09-08T12:00:00.000Z"
          }
        },
        "required": [
          "id",
          "projectId",
          "entityType",
          "entityId",
          "label",
          "url",
          "createdBy",
          "createdAt"
        ]
      },
      "AddExternalReference": {
        "type": "object",
        "properties": {
          "entityType": {
            "type": "string",
            "enum": [
              "project",
              "work",
              "specification",
              "document",
              "milestone"
            ],
            "example": "work"
          },
          "entityId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "label": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "example": "Pull request #482"
          },
          "url": {
            "type": "string",
            "maxLength": 2000,
            "format": "uri",
            "example": "https://github.com/rsx/node/pull/482"
          }
        },
        "required": [
          "entityType",
          "entityId",
          "label",
          "url"
        ]
      },
      "RemoveExternalReference": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      },
      "SearchHit": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "project",
              "work",
              "specification",
              "document",
              "comment"
            ],
            "example": "specification"
          },
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "projectSlug": {
            "type": "string",
            "example": "rsx-node"
          },
          "entityId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "title": {
            "type": "string",
            "example": "Container Applications"
          },
          "snippet": {
            "type": "string",
            "example": "…the container runtime must reconcile…"
          },
          "number": {
            "type": [
              "integer",
              "null"
            ],
            "example": 142
          },
          "slug": {
            "type": [
              "string",
              "null"
            ],
            "example": "container-applications"
          },
          "parentType": {
            "type": [
              "string",
              "null"
            ],
            "example": "specification"
          },
          "parentId": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "example": null
          }
        },
        "required": [
          "kind",
          "projectId",
          "projectSlug",
          "entityId",
          "title",
          "snippet",
          "number",
          "slug",
          "parentType",
          "parentId"
        ]
      },
      "SearchMeta": {
        "type": "object",
        "properties": {
          "query": {
            "type": "string",
            "example": "container"
          },
          "count": {
            "type": "integer",
            "example": 4
          },
          "truncated": {
            "type": "boolean",
            "example": false
          }
        },
        "required": [
          "query",
          "count",
          "truncated"
        ]
      },
      "ExportResult": {
        "type": "object",
        "properties": {
          "filename": {
            "type": "string",
            "example": "container-applications.md"
          },
          "contentType": {
            "type": "string",
            "enum": [
              "text/markdown"
            ]
          },
          "content": {
            "type": "string",
            "example": "---\ntitle: Container Applications\n---\n\n# ..."
          }
        },
        "required": [
          "filename",
          "contentType",
          "content"
        ]
      },
      "ImportResult": {
        "type": "object",
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "specification",
              "document"
            ]
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "title": {
            "type": "string"
          },
          "hadFrontMatter": {
            "type": "boolean",
            "example": true
          }
        },
        "required": [
          "kind",
          "id",
          "slug",
          "title",
          "hadFrontMatter"
        ]
      },
      "ImportMarkdown": {
        "type": "object",
        "properties": {
          "projectId": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          },
          "kind": {
            "type": "string",
            "enum": [
              "specification",
              "document"
            ],
            "example": "specification"
          },
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 500000
          },
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "slug": {
            "type": "string",
            "minLength": 1,
            "maxLength": 64,
            "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
            "example": "rsx-node"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "review",
              "approved",
              "implemented",
              "superseded"
            ],
            "description": "Specifications only.",
            "example": "draft"
          },
          "type": {
            "type": "string",
            "enum": [
              "rfc",
              "runbook",
              "note",
              "design"
            ],
            "description": "Documents only.",
            "example": "runbook"
          }
        },
        "required": [
          "projectId",
          "kind",
          "content"
        ]
      },
      "RestoreRecord": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid",
            "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
          }
        },
        "required": [
          "id"
        ]
      }
    },
    "parameters": {}
  },
  "paths": {
    "/projects/v1/admin/projects/purge": {
      "post": {
        "operationId": "adminPurgeProject",
        "summary": "Permanently delete an archived project",
        "description": "Destroys the project and every record under it: work, specifications and their revisions, documents, milestones, comments, references, memberships and the project's activity. This cannot be undone.\n\nTwo guards. The project must **already be archived**, so a purge is never the first thing that happens to live data, and `confirm` must repeat the project's slug, so it cannot be done by sending the wrong id.\n\nThe project's own activity goes with it rather than surviving it: a history of work nobody can open any more would be rows pointing at nothing. What survives is one row on the operator trail (`admin/audit/list`) saying the project was purged, by whom, and how much went with it.",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PurgeProject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "What was destroyed, counted per table",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PurgeResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/admin/labels/add": {
      "post": {
        "operationId": "adminAddLabel",
        "summary": "Create a platform-wide label",
        "description": "Attachable from every project. Names are lowercase and hyphenated, and are unique across the platform-wide set.",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreateLabel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/admin/labels/update": {
      "post": {
        "operationId": "adminUpdateLabel",
        "summary": "Rename a platform-wide label",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLabel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label renamed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/admin/labels/remove": {
      "post": {
        "operationId": "adminRemoveLabel",
        "summary": "Delete a platform-wide label",
        "description": "Detaches it from every work item carrying it, in every project. A label is a filter rather than a record of something that happened, so there is nothing here for history to want.",
        "tags": [
          "admin"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveLabel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/admin/audit/list": {
      "get": {
        "operationId": "adminListProjectsAudit",
        "summary": "What the operator surface has done",
        "description": "Purges and platform-wide label changes, newest first, with the operator who made them. Kept apart from a project's own activity, which a purge deletes along with the project, so this is the one record that a purged project existed.",
        "tags": [
          "admin"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "label"
              ]
            },
            "required": false,
            "name": "targetType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 128
            },
            "required": false,
            "name": "targetId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "maxLength": 320
            },
            "required": false,
            "name": "actor",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "project.purged",
                "label.added",
                "label.updated",
                "label.removed"
              ]
            },
            "required": false,
            "name": "action",
            "in": "query"
          },
          {
            "schema": {
              "type": [
                "integer",
                "null"
              ],
              "minimum": 0,
              "default": 0,
              "example": 0
            },
            "required": false,
            "name": "offset",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50,
              "example": 50
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Audit events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectsAdminAuditEvent"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "offset": {
                          "type": "integer"
                        },
                        "limit": {
                          "type": "integer"
                        },
                        "more": {
                          "type": "boolean"
                        }
                      },
                      "required": [
                        "offset",
                        "limit",
                        "more"
                      ]
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/internal/docs/list": {
      "get": {
        "operationId": "internalListPublishedDocuments",
        "summary": "The published pages of the built-in docs project",
        "description": "Binding calls only. Every non-archived document in the built-in project that has a published revision and a collection, as that revision, ordered by collection, position and title. Never a working head, never an unpublished document.",
        "tags": [
          "internal"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "guides",
                "products",
                "support"
              ],
              "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
              "example": "guides"
            },
            "required": false,
            "name": "collection",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Published pages",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublishedDocument"
                      }
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/internal/docs/get": {
      "get": {
        "operationId": "internalGetPublishedDocument",
        "summary": "One published page of the built-in docs project",
        "description": "Binding calls only. An unpublished or archived document is not found, whatever is asked.",
        "tags": [
          "internal"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "guides",
                "products",
                "support"
              ],
              "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
              "example": "guides"
            },
            "required": true,
            "name": "collection",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
              "example": "rsx-node"
            },
            "required": true,
            "name": "slug",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Published page",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PublishedDocument"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/projects/add": {
      "post": {
        "operationId": "addProject",
        "summary": "Create a project",
        "description": "The calling account becomes the project's owner and gets an 'owner' membership row in the same write. A key-authenticated caller cannot create a project: it holds no membership, so the project would have nobody answerable for it.",
        "tags": [
          "projects"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateProject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Project"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/projects/list": {
      "get": {
        "operationId": "listProjects",
        "summary": "List projects",
        "description": "Every project, not only the caller's: read access on this surface is the staff gate rather than project membership. Pass `memberOf` to narrow to one account's projects. Archived projects are excluded by default.",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "completed"
              ],
              "example": "active"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "exclude",
                "include",
                "only"
              ],
              "default": "exclude",
              "description": "Whether archived projects appear.",
              "example": "exclude"
            },
            "required": false,
            "name": "archived",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": false,
            "name": "memberOf",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Projects, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Project"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/projects/get": {
      "get": {
        "operationId": "getProject",
        "summary": "Fetch one project",
        "description": "By id or by slug, exactly one of the two. The application routes on slug; everything internal holds an id.",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
              "example": "rsx-node"
            },
            "required": false,
            "name": "slug",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Project",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Project"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/projects/update": {
      "post": {
        "operationId": "updateProject",
        "summary": "Update a project",
        "description": "Needs the maintainer role. An omitted field is left alone. There is deliberately no way to change a slug: it is the project's URL identity and renaming it would break every saved link.",
        "tags": [
          "projects"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Project"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/projects/remove": {
      "post": {
        "operationId": "removeProject",
        "summary": "Archive a project",
        "description": "Needs the owner role. This archives rather than deletes: the row stays, every reference to it keeps resolving, and an archived project is read only. Purging is an admin operation and is not on this surface.",
        "tags": [
          "projects"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveProject"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project archived",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Project"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/members/add": {
      "post": {
        "operationId": "addProjectMember",
        "summary": "Add a project member",
        "description": "Needs the maintainer role, and the owner role to grant 'owner'. Adding an account that is already a member changes its role.",
        "tags": [
          "members"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddProjectMember"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member added",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectMember"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/members/update": {
      "post": {
        "operationId": "updateProjectMember",
        "summary": "Change a member's role",
        "description": "Needs the maintainer role, and the owner role to grant or revoke 'owner'. Demoting the last owner is refused.",
        "tags": [
          "members"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateProjectMember"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectMember"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/members/list": {
      "get": {
        "operationId": "listProjectMembers",
        "summary": "List a project's members",
        "description": "Account ids, not names. Resolve them through RSX ID: this service never stores a handle or display name, because handles are mutable and a copy here would drift.",
        "tags": [
          "members"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "owner",
                "maintainer",
                "contributor",
                "reader"
              ],
              "description": "owner: everything, including archiving and changing owners. maintainer: manage members, labels, milestones and lifecycle. contributor: create and edit content. reader: an explicit watcher, granting no writes.",
              "example": "contributor"
            },
            "required": false,
            "name": "role",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Members, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectMember"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/members/get": {
      "get": {
        "operationId": "getProjectMember",
        "summary": "Fetch one membership",
        "tags": [
          "members"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": true,
            "name": "accountId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Membership",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectMember"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/members/remove": {
      "post": {
        "operationId": "removeProjectMember",
        "summary": "Remove a project member",
        "description": "Needs the maintainer role, and the owner role to remove an owner. Removing the last owner is refused. This is a real delete rather than an archive, because a membership is a grant: the record of it being granted and revoked lives in activity, which is where it belongs.",
        "tags": [
          "members"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveProjectMember"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Member removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "projectId": {
                          "type": "string"
                        },
                        "accountId": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "projectId",
                        "accountId"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/activity/list": {
      "get": {
        "operationId": "listProjectActivity",
        "summary": "List activity",
        "description": "Append-only audit history, newest first. Filterable by project, by entity, or by actor. Activity is not the source of truth for the record it describes: reconstructing current state by replaying it is not supported.",
        "tags": [
          "activity"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "work",
                "specification",
                "document",
                "milestone",
                "member",
                "comment"
              ],
              "example": "work"
            },
            "required": false,
            "name": "entityType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string"
            },
            "required": false,
            "name": "entityId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": false,
            "name": "actorId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Activity, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ProjectActivity"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/activity/get": {
      "get": {
        "operationId": "getProjectActivity",
        "summary": "Fetch one activity entry",
        "tags": [
          "activity"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Activity entry",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ProjectActivity"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/work/add": {
      "post": {
        "operationId": "addWork",
        "summary": "Create a work item",
        "description": "Needs the contributor role. The item's number is allocated by the service, per project, and is what a person cites as #142. Assignees and labels are set here rather than through groups of their own.",
        "tags": [
          "work"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWorkItem"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Work item created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkItem"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Well-formed, but not a thing that can exist",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/work/list": {
      "get": {
        "operationId": "listWork",
        "summary": "List work items",
        "description": "Filterable by project, type, status, priority, roadmap bucket, milestone, assignee and label. Archived items are excluded by default. Reads need no project membership.",
        "tags": [
          "work"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "task",
                "bug",
                "work_order",
                "idea"
              ],
              "example": "task"
            },
            "required": false,
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "backlog",
                "planned",
                "in_progress",
                "blocked",
                "review",
                "done",
                "cancelled"
              ],
              "example": "planned"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "low",
                "normal",
                "high",
                "critical"
              ],
              "description": "Defaults to 'none'. The roadmap bucket expresses urgency.",
              "example": "none"
            },
            "required": false,
            "name": "priority",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "now",
                "next",
                "later",
                "someday"
              ],
              "description": "Roadmap placement. 'none' is not on the roadmap.",
              "example": "next"
            },
            "required": false,
            "name": "bucket",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "milestoneId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f2b1-6c2a-7c9e-9d3a-1e2f3a4b5c6d"
            },
            "required": false,
            "name": "assigneeId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "labelId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "specificationId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "exclude",
                "include",
                "only"
              ],
              "default": "exclude"
            },
            "required": false,
            "name": "archived",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Work items, newest first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WorkItem"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/work/get": {
      "get": {
        "operationId": "getWork",
        "summary": "Fetch one work item",
        "description": "By id, or by the project and number a person cites. Numbers are per project, so #142 alone is ambiguous and projectId is required alongside it.",
        "tags": [
          "work"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "example": 142
            },
            "required": false,
            "name": "number",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Work item",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkItem"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/work/update": {
      "post": {
        "operationId": "updateWork",
        "summary": "Update a work item",
        "description": "Needs the contributor role. An omitted field is left alone; assigneeIds and labelIds are replacements, so sending an empty array clears them. completedAt is maintained by the service from status and is not settable.",
        "tags": [
          "work"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateWorkItem"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Work item updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkItem"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Well-formed, but not a thing that can exist",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/work/remove": {
      "post": {
        "operationId": "removeWork",
        "summary": "Archive a work item",
        "description": "Needs the contributor role. Archives rather than deletes, so every reference to #142 keeps resolving. Its relationships are removed, because a dependency on something nobody is doing any more is a dependency that would block the wrong thing.",
        "tags": [
          "work"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveWorkItem"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Work item archived",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkItem"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/relationships/add": {
      "post": {
        "operationId": "addRelationship",
        "summary": "Connect two work items",
        "description": "Needs the contributor role on the project. Both items must be in the same project. depends_on is accepted and stored as a blocks row in the opposite direction, because they are the same fact; related_to and duplicates are symmetric and stored once, so adding one from either end finds the same row.",
        "tags": [
          "relationships"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddWorkRelationship"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Relationship recorded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkRelationship"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Well-formed, but not a thing that can exist",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/relationships/list": {
      "get": {
        "operationId": "listRelationships",
        "summary": "List a work item's relationships",
        "description": "Both directions: what this item blocks and what blocks it. Which column an id sits in is a storage detail rather than something the reader asked about.",
        "tags": [
          "relationships"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "workId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "blocks",
                "related_to",
                "duplicates",
                "supersedes"
              ],
              "example": "blocks"
            },
            "required": false,
            "name": "relationship",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Relationships",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WorkRelationship"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/relationships/get": {
      "get": {
        "operationId": "getRelationship",
        "summary": "Fetch one relationship",
        "description": "Takes the same five names add does and normalises them the same way, so a relationship added as depends_on is found as depends_on.",
        "tags": [
          "relationships"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "sourceId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "targetId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "blocks",
                "depends_on",
                "related_to",
                "duplicates",
                "supersedes"
              ],
              "description": "blocks and supersedes are directional. related_to and duplicates are symmetric and stored once. depends_on is accepted and normalised to a blocks row in the opposite direction.",
              "example": "blocks"
            },
            "required": true,
            "name": "relationship",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Relationship",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkRelationship"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/relationships/remove": {
      "post": {
        "operationId": "removeRelationship",
        "summary": "Disconnect two work items",
        "description": "Needs the contributor role. Normalises the same way add does, so a relationship can be removed from whichever end the caller is looking at.",
        "tags": [
          "relationships"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveWorkRelationship"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Relationship removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "sourceId": {
                          "type": "string"
                        },
                        "targetId": {
                          "type": "string"
                        },
                        "relationship": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "sourceId",
                        "targetId",
                        "relationship"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/labels/add": {
      "post": {
        "operationId": "addLabel",
        "summary": "Create a label",
        "description": "With a projectId, needs the maintainer role on it. Without one the label is platform-wide, appears in every project's picker, and requires an RSX administrator. Names are lowercase and hyphenated so a label stays usable as a filter.",
        "tags": [
          "labels"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLabel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/labels/list": {
      "get": {
        "operationId": "listLabels",
        "summary": "List labels",
        "description": "With a projectId, returns that project's labels and every platform-wide one, because those are exactly the labels attachable from inside it. `scope` narrows to one or the other when managing rather than choosing.",
        "tags": [
          "labels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "project",
                "global"
              ],
              "default": "all",
              "description": "'project' excludes platform-wide labels; 'global' returns only those."
            },
            "required": false,
            "name": "scope",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Labels",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Label"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/labels/get": {
      "get": {
        "operationId": "getLabel",
        "summary": "Fetch one label",
        "tags": [
          "labels"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Label",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/labels/update": {
      "post": {
        "operationId": "updateLabel",
        "summary": "Rename a label",
        "description": "Only the name is mutable. A label cannot change scope: a project label becoming platform-wide would appear in pickers its author never saw, so that is a new label.",
        "tags": [
          "labels"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLabel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label renamed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Label"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/labels/remove": {
      "post": {
        "operationId": "removeLabel",
        "summary": "Delete a label",
        "description": "A real delete, not an archive, and it detaches the label from every work item carrying it. A label is a filter rather than a record of something that happened, so there is nothing here for history to want later.",
        "tags": [
          "labels"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveLabel"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Label deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/milestones/add": {
      "post": {
        "operationId": "addMilestone",
        "summary": "Create a milestone",
        "description": "Needs the maintainer role. Carries a roadmap bucket like a work item does, because a roadmap entry may reference either.",
        "tags": [
          "milestones"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMilestone"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Milestone created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Milestone"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/milestones/list": {
      "get": {
        "operationId": "listMilestones",
        "summary": "List milestones",
        "tags": [
          "milestones"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "planned",
                "active",
                "completed",
                "cancelled"
              ],
              "example": "planned"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "none",
                "now",
                "next",
                "later",
                "someday"
              ],
              "description": "Roadmap placement. 'none' is not on the roadmap.",
              "example": "next"
            },
            "required": false,
            "name": "bucket",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "exclude",
                "include",
                "only"
              ],
              "default": "exclude"
            },
            "required": false,
            "name": "archived",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Milestones",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Milestone"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/milestones/get": {
      "get": {
        "operationId": "getMilestone",
        "summary": "Fetch one milestone",
        "tags": [
          "milestones"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Milestone",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Milestone"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/milestones/update": {
      "post": {
        "operationId": "updateMilestone",
        "summary": "Update a milestone",
        "description": "Needs the maintainer role. An omitted field is left alone.",
        "tags": [
          "milestones"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMilestone"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Milestone updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Milestone"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/milestones/remove": {
      "post": {
        "operationId": "removeMilestone",
        "summary": "Archive a milestone",
        "description": "Needs the maintainer role. The work in it is detached rather than archived with it: a milestone is a grouping, and cascading would quietly archive items somebody is still doing.",
        "tags": [
          "milestones"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveMilestone"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Milestone archived",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Milestone"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/add": {
      "post": {
        "operationId": "addSpecification",
        "summary": "Create a specification",
        "description": "Needs the contributor role. Created at version 1 with its first revision, written in the same batch. Content is Markdown and is stored and exported as Markdown.",
        "tags": [
          "specifications"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateSpecification"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Specification created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Specification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/list": {
      "get": {
        "operationId": "listSpecifications",
        "summary": "List specifications",
        "tags": [
          "specifications"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "draft",
                "review",
                "approved",
                "implemented",
                "superseded"
              ],
              "example": "draft"
            },
            "required": false,
            "name": "status",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "exclude",
                "include",
                "only"
              ],
              "default": "exclude"
            },
            "required": false,
            "name": "archived",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Specifications",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Specification"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/get": {
      "get": {
        "operationId": "getSpecification",
        "summary": "Fetch one specification",
        "description": "By id, or by the project and slug pair a link carries.",
        "tags": [
          "specifications"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
              "example": "rsx-node"
            },
            "required": false,
            "name": "slug",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Specification",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Specification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/update": {
      "post": {
        "operationId": "updateSpecification",
        "summary": "Save a specification",
        "description": "Needs the contributor role, and the maintainer role to change the lifecycle status. Every save that changes the title, the content or the status writes a revision and bumps the version; a save that changes nothing writes neither.",
        "tags": [
          "specifications"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateSpecification"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Specification saved",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Specification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/supersede": {
      "post": {
        "operationId": "supersedeSpecification",
        "summary": "Retire a specification in favour of another",
        "description": "Needs the maintainer role. Its own action rather than a status on update, because a specification is superseded *by* something: a bare status change would leave a dead end nobody can follow. Both must be in the same project. The retired one's content freezes and its history stays readable.",
        "tags": [
          "specifications"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SupersedeSpecification"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Specification superseded",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Specification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Well-formed, but not a thing that can exist",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/remove": {
      "post": {
        "operationId": "removeSpecification",
        "summary": "Archive a specification",
        "description": "Needs the maintainer role. Archives rather than deletes, so links to it keep resolving and its revision history stays readable.",
        "tags": [
          "specifications"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveSpecification"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Specification archived",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Specification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/revisions/list": {
      "get": {
        "operationId": "listRevisions",
        "summary": "List a specification's revisions",
        "description": "Newest version first. Each revision carries the full title, content and lifecycle state as they were, so any two can be compared without reconstructing a chain of diffs.",
        "tags": [
          "revisions"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "specificationId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Revisions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SpecificationRevision"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/revisions/get": {
      "get": {
        "operationId": "getRevision",
        "summary": "Fetch one revision",
        "description": "The specification exactly as it was at that version.",
        "tags": [
          "revisions"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "specificationId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "example": 2
            },
            "required": true,
            "name": "version",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Revision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/SpecificationRevision"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/add": {
      "post": {
        "operationId": "addDocument",
        "summary": "Create a document",
        "description": "Needs the contributor role. Created at version 1 with its first revision, written in the same batch. Content is Markdown and is stored and exported as Markdown. `collection`, `section` and `position` place the document on docs.rsx.group once it is published; they mean something only in the built-in docs project.",
        "tags": [
          "documents"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateDocument"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/list": {
      "get": {
        "operationId": "listDocuments",
        "summary": "List documents",
        "tags": [
          "documents"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "rfc",
                "runbook",
                "note",
                "design"
              ],
              "example": "runbook"
            },
            "required": false,
            "name": "type",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "guides",
                "products",
                "support"
              ],
              "description": "Where a published page appears on docs.rsx.group. Read only for documents in the built-in docs project; recorded and ignored elsewhere.",
              "example": "guides"
            },
            "required": false,
            "name": "collection",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "any",
                "yes",
                "no"
              ],
              "default": "any",
              "description": "'yes' lists documents with a published revision, 'no' the rest."
            },
            "required": false,
            "name": "published",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "exclude",
                "include",
                "only"
              ],
              "default": "exclude"
            },
            "required": false,
            "name": "archived",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Documents",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Document"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/get": {
      "get": {
        "operationId": "getDocument",
        "summary": "Fetch one document",
        "description": "By id, or by the project and slug pair a link carries. The working head; the published text is the revision `publishedVersion` names.",
        "tags": [
          "documents"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "id",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 64,
              "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$",
              "example": "rsx-node"
            },
            "required": false,
            "name": "slug",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Document",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/update": {
      "post": {
        "operationId": "updateDocument",
        "summary": "Update a document",
        "description": "Needs the contributor role. An omitted field is left alone. A change to `title`, `summary` or `content` writes a new revision (with `note`, if given) and bumps `version`; a change to `type`, `collection`, `section` or `position` moves the document without writing one. Nothing here changes what is published.",
        "tags": [
          "documents"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateDocument"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document updated",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/remove": {
      "post": {
        "operationId": "removeDocument",
        "summary": "Archive a document",
        "description": "Needs the contributor role. Archives rather than deletes, and takes the document off docs.rsx.group if it was published: an archived page must leave the site. Restoring it does not republish it.",
        "tags": [
          "documents"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveDocument"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document archived",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/publish": {
      "post": {
        "operationId": "publishDocument",
        "summary": "Publish a document",
        "description": "Needs the maintainer role. Names the revision docs.rsx.group shows: the head when `version` is omitted, or an earlier revision, which is how a bad edit is undone. Changes no content. A document reaches the site only from the built-in docs project and only with a collection; publishing elsewhere records the intent and shows nothing.",
        "tags": [
          "documents"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishDocument"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document published",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/unpublish": {
      "post": {
        "operationId": "unpublishDocument",
        "summary": "Take a document off the site",
        "description": "Needs the maintainer role. Clears the published revision; the document and its history stay. Unpublishing something that is not published succeeds and changes nothing.",
        "tags": [
          "documents"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnpublishDocument"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document unpublished",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/document-revisions/list": {
      "get": {
        "operationId": "listDocumentRevisions",
        "summary": "List a document's revisions",
        "description": "Newest first. Every version that has ever existed; nothing deletes one.",
        "tags": [
          "document-revisions"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "documentId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Revisions",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/DocumentRevision"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/document-revisions/get": {
      "get": {
        "operationId": "getDocumentRevision",
        "summary": "Fetch one revision of a document",
        "tags": [
          "document-revisions"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "documentId",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "example": 2
            },
            "required": true,
            "name": "version",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Revision",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/DocumentRevision"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/comments/add": {
      "post": {
        "operationId": "addComment",
        "summary": "Comment on a work item, specification or document",
        "description": "Needs the contributor role on the target's project. Specifications are commentable because they are the point: review discussion belongs on the thing being argued about, not on a work item that links to it.",
        "tags": [
          "comments"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddComment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Comment added",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Comment"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/comments/list": {
      "get": {
        "operationId": "listComments",
        "summary": "Read a thread",
        "description": "Oldest first, which is the opposite of every other list here and deliberate: a conversation reads forwards. Deleted comments keep their place with an empty body unless excluded.",
        "tags": [
          "comments"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "work",
                "specification",
                "document"
              ],
              "example": "specification"
            },
            "required": true,
            "name": "entityType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "entityId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "include",
                "exclude"
              ],
              "default": "include"
            },
            "required": false,
            "name": "deleted",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The thread",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Comment"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/comments/get": {
      "get": {
        "operationId": "getComment",
        "summary": "Fetch one comment",
        "tags": [
          "comments"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Comment",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Comment"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/comments/update": {
      "post": {
        "operationId": "updateComment",
        "summary": "Edit a comment",
        "description": "The author, or a maintainer. Only the body is mutable.",
        "tags": [
          "comments"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateComment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Comment edited",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Comment"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/comments/remove": {
      "post": {
        "operationId": "removeComment",
        "summary": "Delete a comment",
        "description": "The author, or a maintainer. The row stays and the body goes, so a thread does not lose its shape. The text is cleared at rest rather than hidden on read.",
        "tags": [
          "comments"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveComment"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Comment deleted",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/references/add": {
      "post": {
        "operationId": "addReference",
        "summary": "Link a record to something outside Projects",
        "description": "Needs the contributor role. A GitHub PR, a deployment, a status page, an RSX CDN share link. Nothing here copies the other system's data: the far side stays authoritative for itself. http and https only.",
        "tags": [
          "references"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddExternalReference"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reference added",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExternalReference"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/references/list": {
      "get": {
        "operationId": "listReferences",
        "summary": "List external references",
        "tags": [
          "references"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "example": ""
            },
            "required": false,
            "name": "cursor",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "work",
                "specification",
                "document",
                "milestone"
              ],
              "example": "work"
            },
            "required": false,
            "name": "entityType",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "entityId",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "References",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/ExternalReference"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/ProjectsPageMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/references/get": {
      "get": {
        "operationId": "getReference",
        "summary": "Fetch one external reference",
        "tags": [
          "references"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "id",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Reference",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExternalReference"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/references/remove": {
      "post": {
        "operationId": "removeReference",
        "summary": "Remove an external reference",
        "description": "Needs the contributor role. A real delete: a reference is a link rather than a record of something that happened, and the thing it points at is unaffected either way.",
        "tags": [
          "references"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RemoveExternalReference"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Reference removed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        }
                      },
                      "required": [
                        "id"
                      ]
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/search/query": {
      "get": {
        "operationId": "searchProjects",
        "summary": "Search across projects",
        "description": "Cross-project full-text search over projects, work items, specifications, documents and comments. Reads are not membership-gated, so results come from everywhere. Titles are weighted above bodies. FTS5 syntax is available: quoted phrases, AND/OR, and * for a prefix; a malformed expression is a 400 rather than a 500.\n\nThere is no cursor. A ranked list is not stably pageable, so a caller wanting more should narrow the query.",
        "tags": [
          "search"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200,
              "example": "container"
            },
            "required": true,
            "name": "q",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "description": "Narrow to one project.",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": false,
            "name": "projectId",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "work",
                "specification",
                "document",
                "comment"
              ],
              "description": "Narrow to one kind of record.",
              "example": "specification"
            },
            "required": false,
            "name": "kind",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 20,
              "example": 20
            },
            "required": false,
            "name": "limit",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "Matching records, best first",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/SearchHit"
                      }
                    },
                    "meta": {
                      "$ref": "#/components/schemas/SearchMeta"
                    }
                  },
                  "required": [
                    "data",
                    "meta"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/export/get": {
      "get": {
        "operationId": "exportMarkdown",
        "summary": "Export a record as Markdown",
        "description": "A specification or document exports as front matter plus its content, and re-imports byte-identically. A project exports as an index of its milestones and open work, and a roadmap as the four buckets with the work under each; those two are documents Projects writes about its records rather than documents it stores, so they are readable outside Projects but are not importable.",
        "tags": [
          "export"
        ],
        "parameters": [
          {
            "schema": {
              "type": "string",
              "enum": [
                "project",
                "specification",
                "document",
                "roadmap"
              ],
              "description": "project: an index with milestones and open work. specification and document: front matter plus content. roadmap: the four buckets with the work under each.",
              "example": "specification"
            },
            "required": true,
            "name": "kind",
            "in": "query"
          },
          {
            "schema": {
              "type": "string",
              "format": "uuid",
              "example": "0198f3c4-7d2b-7e1f-8a2b-3c4d5e6f7a8b"
            },
            "required": true,
            "name": "id",
            "in": "query"
          },
          {
            "schema": {
              "type": "integer",
              "exclusiveMinimum": 0,
              "example": 2
            },
            "required": false,
            "name": "version",
            "in": "query"
          }
        ],
        "responses": {
          "200": {
            "description": "The exported file",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ExportResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/import/add": {
      "post": {
        "operationId": "importMarkdown",
        "summary": "Import a Markdown file",
        "description": "Needs the contributor role. Creates a real specification or document, never an opaque attachment. Front matter supplies the title, slug, status and type; anything given in the request overrides it, so a file exported from one project can land in another without being edited first.\n\nA file with no front matter is fine as long as a title and slug are supplied here.",
        "tags": [
          "import"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ImportMarkdown"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Imported",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/ImportResult"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Well-formed, but not a thing that can exist",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/projects/restore": {
      "post": {
        "operationId": "restoreProject",
        "summary": "Restore an archived project",
        "description": "Needs the owner role, matching what archiving it needed. Restoring something that is not archived succeeds and changes nothing: the caller named a state, and that is the state it is in.",
        "tags": [
          "projects"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreRecord"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Project restored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Project"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/work/restore": {
      "post": {
        "operationId": "restoreWorkitem",
        "summary": "Restore an archived work item",
        "description": "Needs the contributor role, matching what archiving it needed. Restoring something that is not archived succeeds and changes nothing: the caller named a state, and that is the state it is in.",
        "tags": [
          "work"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreRecord"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Work item restored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/WorkItem"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/specifications/restore": {
      "post": {
        "operationId": "restoreSpecification",
        "summary": "Restore an archived specification",
        "description": "Needs the maintainer role, matching what archiving it needed. Restoring something that is not archived succeeds and changes nothing: the caller named a state, and that is the state it is in.",
        "tags": [
          "specifications"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreRecord"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Specification restored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Specification"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/documents/restore": {
      "post": {
        "operationId": "restoreDocument",
        "summary": "Restore an archived document",
        "description": "Needs the contributor role, matching what archiving it needed. Restoring something that is not archived succeeds and changes nothing: the caller named a state, and that is the state it is in.",
        "tags": [
          "documents"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreRecord"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Document restored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Document"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/projects/v1/milestones/restore": {
      "post": {
        "operationId": "restoreMilestone",
        "summary": "Restore an archived milestone",
        "description": "Needs the maintainer role, matching what archiving it needed. Restoring something that is not archived succeeds and changes nothing: the caller named a state, and that is the state it is in.",
        "tags": [
          "milestones"
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RestoreRecord"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Milestone restored",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Milestone"
                    }
                  },
                  "required": [
                    "data"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "The request did not match the endpoint's schema",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "401": {
            "description": "Missing credential, or a token this application will not accept",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "403": {
            "description": "Admitted to Projects, but not permitted this operation",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "404": {
            "description": "No such record",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "409": {
            "description": "The record's state does not permit this",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    }
  },
  "webhooks": {}
}
