{
  "openapi": "3.0.3",
  "info": {
    "title": "Radix Guild API v1",
    "version": "1",
    "description": "Machine-readable contract for /api/v1. Generated by guild-app/scripts/gen-openapi.mjs from the route files and the zod schemas in src/lib/validation.ts; CI fails on drift. Auth is a ROLA session cookie: GET /auth/challenge, sign it in the wallet, POST /auth/verify. Prose reference: src/app/api/v1/README.md."
  },
  "servers": [
    {
      "url": "https://radixguild.com/api/v1"
    }
  ],
  "components": {
    "securitySchemes": {
      "sessionCookie": {
        "type": "apiKey",
        "in": "cookie",
        "name": "guild_session",
        "description": "Session cookie set by POST /auth/verify after a ROLA-signed challenge."
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "required": [
          "ok",
          "error"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "enum": [
              false
            ]
          },
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "properties": {
              "code": {
                "type": "string",
                "description": "AUTH_REQUIRED, FORBIDDEN, NOT_FOUND, VALIDATION_ERROR, INVALID_STATUS, RATE_LIMITED, INTERNAL_ERROR, or a route-specific code"
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      },
      "createFundingPoolSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "target_xrd": {
            "type": "string",
            "pattern": "^\\d+(\\.\\d{1,18})?$"
          },
          "charter": {
            "type": "object",
            "properties": {
              "problem": {
                "type": "string",
                "minLength": 40,
                "maxLength": 600
              },
              "deliverables": {
                "minItems": 1,
                "maxItems": 7,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 200
                }
              },
              "outOfScope": {
                "maxItems": 7,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 200
                }
              },
              "prerequisites": {
                "maxItems": 5,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 200
                }
              },
              "steward": {
                "type": "string",
                "enum": [
                  "poster",
                  "working-group",
                  "operator"
                ]
              },
              "terms": {
                "type": "object",
                "properties": {
                  "deliverableType": {
                    "type": "string",
                    "enum": [
                      "code",
                      "design",
                      "content",
                      "research",
                      "ops"
                    ]
                  },
                  "reviewWindowDays": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 30
                  },
                  "revisionsIncluded": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 3
                  },
                  "repoUrl": {
                    "type": "string",
                    "maxLength": 300,
                    "format": "uri"
                  },
                  "specUrl": {
                    "type": "string",
                    "maxLength": 300,
                    "format": "uri"
                  },
                  "acceptanceCriteria": {
                    "minItems": 1,
                    "maxItems": 7,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "minLength": 3,
                      "maxLength": 200
                    }
                  },
                  "definitionOfDone": {
                    "minItems": 1,
                    "maxItems": 5,
                    "type": "array",
                    "items": {
                      "type": "string",
                      "enum": [
                        "tests-pass",
                        "ci-green",
                        "code-reviewed",
                        "deployed",
                        "docs-updated"
                      ]
                    }
                  },
                  "license": {
                    "type": "string",
                    "enum": [
                      "mit",
                      "apache-2.0",
                      "cc0",
                      "assigned-on-payment",
                      "custom"
                    ]
                  },
                  "licenseNote": {
                    "type": "string",
                    "minLength": 3,
                    "maxLength": 200
                  },
                  "commChannel": {
                    "type": "string",
                    "minLength": 2,
                    "maxLength": 120
                  },
                  "claimEligibility": {
                    "type": "string",
                    "enum": [
                      "humans",
                      "agents",
                      "both"
                    ]
                  },
                  "minTrustTier": {
                    "type": "string",
                    "enum": [
                      "established",
                      "top_rated"
                    ]
                  }
                },
                "additionalProperties": false
              }
            },
            "additionalProperties": false
          },
          "deadline_secs": {
            "type": "integer",
            "minimum": 604800,
            "maximum": 2592000
          }
        },
        "required": [
          "title",
          "description",
          "target_xrd"
        ]
      },
      "createProjectSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 80
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "name"
        ]
      },
      "createSubmissionSchema": {
        "type": "object",
        "properties": {
          "content": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10000
          }
        },
        "required": [
          "content"
        ]
      },
      "createTaskSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "reward_amount": {
            "type": "string",
            "pattern": "^\\d+(\\.\\d{1,8})?$"
          },
          "requirements": {
            "type": "string",
            "maxLength": 5000
          },
          "deadline": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          },
          "terms": {
            "type": "object",
            "properties": {
              "deliverableType": {
                "type": "string",
                "enum": [
                  "code",
                  "design",
                  "content",
                  "research",
                  "ops"
                ]
              },
              "reviewWindowDays": {
                "type": "integer",
                "minimum": 1,
                "maximum": 30
              },
              "revisionsIncluded": {
                "type": "integer",
                "minimum": 0,
                "maximum": 3
              },
              "repoUrl": {
                "type": "string",
                "maxLength": 300,
                "format": "uri"
              },
              "specUrl": {
                "type": "string",
                "maxLength": 300,
                "format": "uri"
              },
              "acceptanceCriteria": {
                "minItems": 1,
                "maxItems": 7,
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 3,
                  "maxLength": 200
                }
              },
              "definitionOfDone": {
                "minItems": 1,
                "maxItems": 5,
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "tests-pass",
                    "ci-green",
                    "code-reviewed",
                    "deployed",
                    "docs-updated"
                  ]
                }
              },
              "license": {
                "type": "string",
                "enum": [
                  "mit",
                  "apache-2.0",
                  "cc0",
                  "assigned-on-payment",
                  "custom"
                ]
              },
              "licenseNote": {
                "type": "string",
                "minLength": 3,
                "maxLength": 200
              },
              "commChannel": {
                "type": "string",
                "minLength": 2,
                "maxLength": 120
              },
              "claimEligibility": {
                "type": "string",
                "enum": [
                  "humans",
                  "agents",
                  "both"
                ]
              },
              "minTrustTier": {
                "type": "string",
                "enum": [
                  "established",
                  "top_rated"
                ]
              }
            },
            "additionalProperties": false
          },
          "project_id": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "maximum": 9007199254740991
          },
          "working_group_id": {
            "type": "integer",
            "minimum": 0,
            "exclusiveMinimum": true,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "title",
          "description",
          "reward_amount"
        ]
      },
      "markNotificationsReadSchema": {
        "type": "object",
        "properties": {
          "ids": {
            "maxItems": 100,
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 0,
              "exclusiveMinimum": true,
              "maximum": 9007199254740991
            }
          }
        }
      },
      "pledgeFundingPoolSchema": {
        "type": "object",
        "properties": {
          "amount_xrd": {
            "type": "string",
            "pattern": "^\\d+(\\.\\d{1,18})?$"
          }
        },
        "required": [
          "amount_xrd"
        ]
      },
      "proposeWorkingGroupSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 80
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          }
        },
        "required": [
          "name"
        ]
      },
      "reviewSubmissionSchema": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "approved",
              "rejected",
              "revision_requested"
            ]
          },
          "reviewer_notes": {
            "type": "string",
            "maxLength": 5000
          },
          "decline_reason": {
            "type": "string",
            "enum": [
              "unclear_requirements",
              "incomplete_delivery",
              "quality_issues",
              "off_topic",
              "duplicate_work",
              "spam_submission",
              "doesnt_compile",
              "tests_fail",
              "other"
            ]
          }
        },
        "required": [
          "status"
        ]
      },
      "tempCheckVoteSchema": {
        "type": "object",
        "properties": {
          "option": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          }
        },
        "required": [
          "option"
        ]
      },
      "updateProjectSchema": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "minLength": 3,
            "maxLength": 80
          },
          "description": {
            "type": "string",
            "maxLength": 2000
          }
        }
      },
      "updateTaskSchema": {
        "type": "object",
        "properties": {
          "title": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "maxLength": 5000
          },
          "reward_amount": {
            "type": "string",
            "pattern": "^\\d+(\\.\\d{1,8})?$"
          },
          "requirements": {
            "type": "string",
            "maxLength": 5000
          },
          "deadline": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
          }
        }
      },
      "verifyAuthSchema": {
        "type": "object",
        "properties": {
          "signed_challenge": {
            "type": "object",
            "properties": {
              "challenge": {
                "type": "string"
              },
              "address": {
                "type": "string"
              },
              "proof": {
                "type": "object",
                "properties": {
                  "publicKey": {
                    "type": "string"
                  },
                  "signature": {
                    "type": "string"
                  },
                  "curve": {
                    "type": "string",
                    "enum": [
                      "curve25519",
                      "secp256k1"
                    ]
                  }
                },
                "required": [
                  "publicKey",
                  "signature",
                  "curve"
                ]
              },
              "type": {
                "type": "string",
                "enum": [
                  "persona",
                  "account"
                ]
              }
            },
            "required": [
              "challenge",
              "address",
              "proof",
              "type"
            ]
          }
        },
        "required": [
          "signed_challenge"
        ]
      }
    }
  },
  "paths": {
    "/auth/challenge": {
      "get": {
        "summary": "Get a ROLA challenge for wallet auth (rate-limited: 10/min per IP)",
        "tags": [
          "auth"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "summary": "Clear the session cookie",
        "tags": [
          "auth"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/auth/me": {
      "get": {
        "summary": "Current user for the session",
        "tags": [
          "auth"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/auth/verify": {
      "post": {
        "summary": "Verify the signed challenge and create a session (rate-limited: 10/min per IP)",
        "tags": [
          "auth"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/verifyAuthSchema"
              }
            }
          }
        }
      }
    },
    "/csp-report": {
      "post": {
        "summary": "CSP violation report sink (report-uri / Reporting API)",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "Always 405 — the sink accepts POST only",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "put": {
        "summary": "Always 405 — the sink accepts POST only",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Always 405 — the sink accepts POST only",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Always 405 — the sink accepts POST only",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/escrow/{taskId}": {
      "get": {
        "summary": "Escrow transactions for a task (poster or assigned worker only)",
        "tags": [
          "escrow"
        ],
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/escrow/posting-status": {
      "get": {
        "summary": "Whether the escrow component accepts new tasks (frozen flag, component address)",
        "tags": [
          "escrow"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/funding-pools/{id}/charter": {
      "put": {
        "summary": "Save a draft pool's charter (poster only, draft only)",
        "tags": [
          "funding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/funding-pools/{id}/pledge": {
      "post": {
        "summary": "Pledge XRD to a funding pool",
        "tags": [
          "funding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/pledgeFundingPoolSchema"
              }
            }
          }
        }
      }
    },
    "/funding-pools/{id}/publish": {
      "post": {
        "summary": "Publish a draft's charter and open it for pledges",
        "tags": [
          "funding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/funding-pools/{id}/refund": {
      "post": {
        "summary": "Refund your pledge from a pool that missed its target",
        "tags": [
          "funding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/funding-pools/{id}": {
      "get": {
        "summary": "Get a funding pool",
        "tags": [
          "funding"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/funding-pools/leaderboard": {
      "get": {
        "summary": "Top pledgers",
        "tags": [
          "funding"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/funding-pools": {
      "get": {
        "summary": "List community funding pools",
        "tags": [
          "funding"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a community funding pool",
        "tags": [
          "funding"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/createFundingPoolSchema"
              }
            }
          }
        }
      }
    },
    "/game/leaderboard": {
      "get": {
        "summary": "Meme-grid game leaderboard",
        "tags": [
          "game"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/game/roll": {
      "post": {
        "summary": "Roll (once per day per user)",
        "tags": [
          "game"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/game/state": {
      "get": {
        "summary": "Your game state",
        "tags": [
          "game"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/groups/{slug}/membership": {
      "put": {
        "summary": "Join a group or change level (upsert; rate-limited: 30/min per user)",
        "tags": [
          "groups"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      },
      "delete": {
        "summary": "Leave a group (rate-limited: 30/min per user)",
        "tags": [
          "groups"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/groups/browse": {
      "get": {
        "summary": "Custom-feed browse: ?groups=<slug,slug,...>, no membership needed",
        "tags": [
          "groups"
        ],
        "parameters": [
          {
            "name": "groups",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/groups/feed": {
      "get": {
        "summary": "Member feed: tasks from your joined groups, any status",
        "tags": [
          "groups"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/groups/memberships": {
      "get": {
        "summary": "Your own joined groups",
        "tags": [
          "groups"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/groups/propose": {
      "get": {
        "summary": "Your own working-group proposals",
        "tags": [
          "groups"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      },
      "post": {
        "summary": "Submit a working-group proposal (rate-limited: 5/min per user)",
        "tags": [
          "groups"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/proposeWorkingGroupSchema"
              }
            }
          }
        }
      }
    },
    "/groups": {
      "get": {
        "summary": "Working-group catalogue (viewer-aware when signed in)",
        "tags": [
          "groups"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/network/status": {
      "get": {
        "summary": "Radix network liveness as seen by the app",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/notifications/read": {
      "patch": {
        "summary": "Mark notifications read (ids omitted = all)",
        "tags": [
          "notifications"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/markNotificationsReadSchema"
              }
            }
          }
        }
      }
    },
    "/notifications": {
      "get": {
        "summary": "Your notification inbox",
        "tags": [
          "notifications"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/projects/{slug}": {
      "get": {
        "summary": "Get a project with its tasks",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a project's name or description (commissioner only, rate-limited: 5/min per user)",
        "description": "Correct a project's public copy. Before this route existed the only write to the projects table was the create insert, so a description was write-once and fixing it meant a database shell. `slug` is deliberately not editable: it is the project's URL identity and stable after create, so a rename must not break existing links.",
        "tags": [
          "projects"
        ],
        "parameters": [
          {
            "name": "slug",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/updateProjectSchema"
              }
            }
          }
        }
      }
    },
    "/projects": {
      "get": {
        "summary": "List projects",
        "tags": [
          "projects"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a project",
        "tags": [
          "projects"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/createProjectSchema"
              }
            }
          }
        }
      }
    },
    "/quote/xrd-usd": {
      "get": {
        "summary": "XRD/USD quote used for display",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/": {
      "get": {
        "summary": "API health check",
        "tags": [
          "meta"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/submissions/{id}/review": {
      "patch": {
        "summary": "Review a submission (task creator only)",
        "tags": [
          "submissions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/reviewSubmissionSchema"
              }
            }
          }
        }
      }
    },
    "/submissions/{id}/verify-pr": {
      "post": {
        "summary": "Verify a submitted pull-request link against GitHub",
        "tags": [
          "submissions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/tasks/{id}/dispute-evidence": {
      "post": {
        "summary": "Attach the hashed dispute statement for a task",
        "tags": [
          "escrow"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/tasks/{id}/escrow/claim-check": {
      "get": {
        "summary": "Pre-flight for a claim: bond, badge and allowlist checks",
        "tags": [
          "escrow"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/tasks/{id}/escrow/resync": {
      "post": {
        "summary": "Re-read the task's on-chain escrow state into the app",
        "tags": [
          "escrow"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/tasks/{id}/escrow": {
      "post": {
        "summary": "Confirm an escrow transaction for a task (create/claim/submit/approve/cancel/dispute/withdraw)",
        "tags": [
          "escrow"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/tasks/{id}": {
      "get": {
        "summary": "Get a task by id with its submission count",
        "tags": [
          "tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update a task (creator only)",
        "tags": [
          "tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/updateTaskSchema"
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Cancel a task (creator only, no submissions)",
        "tags": [
          "tasks"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      }
    },
    "/tasks/{id}/submissions": {
      "get": {
        "summary": "List submissions for a task (creator or submitters only)",
        "tags": [
          "submissions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ]
      },
      "post": {
        "summary": "Submit work for a task (rate-limited: 5/min per user)",
        "tags": [
          "submissions"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/createSubmissionSchema"
              }
            }
          }
        }
      }
    },
    "/tasks": {
      "get": {
        "summary": "List tasks with filters (status, creator, assignee, project, cursor, limit, sort)",
        "tags": [
          "tasks"
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "creator",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "assignee",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "project",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a task (rate-limited: 5/min per user)",
        "description": "Create the DB task row. DB-FIRST REQUIRED: this must be called BEFORE the task is funded on-chain — fund first (no prior row) and the task can NEVER be reconciled. The reconciler hard-refuses a chain-only `create` with `NOT_RECONCILABLE` (HTTP 501): \"Cannot reconcile 'create': linking an unconfirmed create to a DB task requires the poster's intent\" (src/lib/escrow-confirm.ts:296-303). Proven order: POST /tasks (this) -> fund on-chain (create_task, hashing this response's OWN stored title/description) -> POST /tasks/{id}/escrow {kind: \"create\"} to confirm. See scripts/post-micro-tasks.mjs, scripts/gate1-e2e.mjs, and packages/agent-client's `guild-poster post`, which already follows this order.",
        "tags": [
          "tasks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "401": {
            "description": "AUTH_REQUIRED — sign in with ROLA first",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "security": [
          {
            "sessionCookie": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/createTaskSchema"
              }
            }
          }
        }
      }
    },
    "/tasks/stats": {
      "get": {
        "summary": "Per-status task counts and total paid XRD",
        "tags": [
          "tasks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/tempcheck/{checkId}": {
      "get": {
        "summary": "Lights-on temperature check tallies",
        "tags": [
          "tempcheck"
        ],
        "parameters": [
          {
            "name": "checkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Vote in a lights-on temperature check",
        "tags": [
          "tempcheck"
        ],
        "parameters": [
          {
            "name": "checkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/tempCheckVoteSchema"
              }
            }
          }
        }
      }
    },
    "/users/{address}/profile": {
      "get": {
        "summary": "Public profile for a wallet address",
        "tags": [
          "users"
        ],
        "parameters": [
          {
            "name": "address",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    },
    "/users/leaderboard": {
      "get": {
        "summary": "XP leaderboard (app ledger)",
        "tags": [
          "users"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "OK. Envelope `{ ok: true, data: ... }` or the route's own JSON shape; see src/app/api/v1/README.md."
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED — see Retry-After",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorEnvelope"
                }
              }
            }
          }
        }
      }
    }
  }
}
