/** * Generated by orval 🍺 * Do not edit manually. * gitdata api * * ## Conventions * * ### Response envelope * Every JSON response uses the same envelope: * * | field | meaning | * |---|---| * | `code` | always equal to the HTTP status code | * | `message` | human-readable result / error summary | * | `data` | payload, `null` for errors and empty results | * | `error` | field-level / technical detail (e.g. validation errors), may be `null` | * | `error_code` | stable machine-readable code on 4xx (e.g. `conflict`, `rate_limited`), may be `null` | * | `request_id` | correlation id, also returned as the `X-Request-Id` header | * * Successful `POST` creation returns `200` (not `201`); empty results use `200` with `data: null`. * - `POST /auth/logout` is idempotent: repeating it always succeeds with `200`. * * ### Authentication * - `session_cookie`: opaque session carried in the `session` cookie and stored in * Redis. `GET /auth/login` redirects to the same-origin login page; * `POST /auth/logout` revokes the session and clears the cookie. * * ### URL & parameter style * - Paths are `kebab-case`, plural nouns, nesting expresses ownership. * - Query/path/JSON field names are `snake_case`; enum values are `snake_case`. * - All endpoints are versioned under `/api/v1`. `/api/v1/internal/*` is guarded * by the `x-gitdata-service-key` header and is NOT documented here. * - State-transition actions use `POST {resource}/{id}/{verb}` (close/reopen); * idempotent whole-resource state uses `PUT` (default branch, pin, read-state); * partial updates use `PATCH`. * * ### Pagination * - 唯一 offset 风格:`?limit=&offset=`(`limit` 默认 50;`offset` 上限 5000), * 分页响应的 `data` 恒为 `{ items, total, limit, offset }`,字段均为无符号整数。 * - `limit` 为 0、超过端点上限或 `offset` 超过 5000 时返回 400 * (`error_code: bad_request`),不会静默截断。 * - 排序参数为 `?sort=&order=asc|desc`;`sort` 的取值按端点枚举校验, * 未知值返回 400,未知参数同样返回 400。 * - chat 消息额外接受 `before_seq` / `after_seq` 作为筛选条件,响应仍是同一 `Page` 形状。 * - Git LFS 锁定列表的 `next_cursor` 是 LFS 协议字段,不适用本约定。 * * ### PATCH semantics (three-state fields) * Update commands use `Option>` for clearable fields: * - field **absent** → unchanged * - field `null` → cleared * - field value → set * * Example: `{"milestone_id": null}` unassigns the milestone; omitting * `milestone_id` leaves it untouched. * * ### 2FA * TOTP enrollment, recovery codes and sensitive-operation verification are * handled by identity; GitData only proxies the account-management endpoints. * * ### Operations * - `GET /healthz` — liveness probe (no auth, outside `/api/v1`). * - `GET /readyz` — readiness probe: database (primary) + redis live checks, * rocketmq + s3 sampled every 10s, `503` when any is down. * - Runtime metrics are pushed to the configured OTLP collector (30s interval); * there is no scrape endpoint. * - Cross-origin browser access is disabled by default; the API expects a * same-origin reverse proxy. Enable `web.cors_allow_origins` to allowlist * other origins. * * ### Abuse controls * - Creation endpoints are subject to per-user rolling 24h quotas * (`[quota]` config; 0 disables). Exceeding a quota returns `429` * with `error_code: "rate_limited"`. * * ### Idempotency * - `POST /chat/rooms/{room_id}/messages` accepts `nonce`: unique per room; * retrying with the same nonce returns the original message instead of a duplicate. * * ### Resource references * - User references in responses embed a `user` object (`UserDto`) wherever a * single person is shown; raw uuid fields are named `*_id` consistently. * - Viewer-specific state is embedded, not fetched separately: `RepoDto.me` * carries `starred`/`watch_mode`, `IssueDto.viewer_watch` carries the caller * watch mode. `PUT /repos/{space}/{repo}/star|unstar` style reads do not exist. * * ### Identifiers * - Issues are addressable by UUID **or** board-scoped number * (e.g. `/issues/{space}/boards/{board}/issues/123`). * - Binary uploads use raw request bodies with a content-type header * (e.g. `PUT /me/avatar` accepts `image/*` bytes, not base64 JSON). * * OpenAPI spec version: 1.0 */ export type AttachmentStatus = "Pending" | "Uploaded"; export interface AttachmentDto { content_type: string; created_at: string; /** @nullable */ description?: string | null; /** @nullable */ duration_secs?: number | null; filename: string; /** @nullable */ height?: number | null; id: string; /** @nullable */ message_id?: string | null; /** @nullable */ room_id?: string | null; size: number; status: AttachmentStatus; user_id: number; /** @nullable */ width?: number | null; } export type AuthorType = "User" | "Bot" | "Webhook"; export interface UserDto { avatar_url: string; display_name: string; user_id: number; username: string; } export type ChatMessageType = | "Default" | "Reply" | "ThreadCreated" | "ChannelJoin" | "ChannelLeave" | "ChannelTopic" | "ChannelPinnedItem" | "Reminder" | "System"; export interface EmbedAuthor { /** @nullable */ icon_url?: string | null; name?: string; /** @nullable */ proxy_icon_url?: string | null; /** @nullable */ url?: string | null; } export interface EmbedField { inline?: boolean; name?: string; value?: string; } export interface EmbedFooter { /** @nullable */ icon_url?: string | null; /** @nullable */ proxy_icon_url?: string | null; text?: string; } export interface EmbedMedia { /** @nullable */ content_hash?: string | null; /** @nullable */ content_type?: string | null; /** @nullable */ description?: string | null; /** * @minimum 0 * @nullable */ duration?: number | null; /** @minimum 0 */ flags?: number; /** * @minimum 0 * @nullable */ height?: number | null; /** @nullable */ placeholder?: string | null; /** @nullable */ proxy_url?: string | null; /** @nullable */ url?: string | null; /** * @minimum 0 * @nullable */ width?: number | null; } export interface EmbedProvider { name?: string; /** @nullable */ url?: string | null; } /** * Discord 风格的消息 embed。 * * `platform` / `kind` / `src` / `image_url` 等字段是旧消息与旧缓存的兼容外壳: * 历史 `chat_message.embeds` 里存的还是老结构,反序列化时不能丢字段;新写入 * 同时填富模型和这些兼容字段,前端可以逐步迁移。 */ export interface MessageEmbed { /** @nullable */ aspect?: string | null; audio?: null | EmbedMedia; author?: null | EmbedAuthor; /** @nullable */ category?: string | null; /** @nullable */ children?: MessageEmbed[] | null; /** * @minimum 0 * @nullable */ color?: number | null; /** @nullable */ description?: string | null; /** @nullable */ fields?: EmbedField[] | null; footer?: null | EmbedFooter; /** * @minimum 0 * @nullable */ height?: number | null; /** @nullable */ html?: string | null; /** * @minimum 0 * @nullable */ html_height?: number | null; /** * @minimum 0 * @nullable */ html_width?: number | null; image?: null | EmbedMedia; /** @nullable */ image_url?: string | null; /** @nullable */ kind?: string | null; /** @nullable */ nsfw?: boolean | null; /** @nullable */ platform?: string | null; /** @nullable */ platform_name?: string | null; provider?: null | EmbedProvider; /** @nullable */ site_name?: string | null; /** @nullable */ src?: string | null; thumbnail?: null | EmbedMedia; /** @nullable */ timestamp?: string | null; /** @nullable */ title?: string | null; type?: string; /** @nullable */ url?: string | null; video?: null | EmbedMedia; } export interface ReactionAggDto { count: number; emoji: string; me: boolean; } export type EnvelopeMessageDtoData = { attachments: AttachmentDto[]; author?: null | UserDto; author_id: number; author_type: AuthorType; content: string; created_at: string; /** @nullable */ deleted_at?: string | null; /** @nullable */ edited_at?: string | null; embeds?: MessageEmbed[]; /** @nullable */ forwarded_from_id?: string | null; has_thread: boolean; id: string; mention_everyone: boolean; mentions: number[]; message_type: ChatMessageType; pinned: boolean; /** @nullable */ pinned_at?: string | null; /** @nullable */ pinned_by_id?: number | null; reactions?: ReactionAggDto[]; /** @nullable */ reply_to_id?: string | null; room_id: string; seq: number; thread_broadcast: boolean; /** @nullable */ thread_id?: string | null; /** @nullable */ webhook_id?: string | null; }; export interface EnvelopeMessageDto { code: number; data?: EnvelopeMessageDtoData; /** @nullable */ error?: string | null; /** @nullable */ error_code?: string | null; message: string; request_id?: string; } export interface EnvelopeNoData { code: number; data?: unknown; /** @nullable */ error?: string | null; /** @nullable */ error_code?: string | null; message: string; request_id?: string; }